{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "817eab1e-33c5-422b-9090-d0a416f72394",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "source": [
    "# Parasha statistic analysis with BHSA (Text-Fabric)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "97d3d4d3-7fc9-4706-98f1-4482f0e5f5d6",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "source": [
    "# Table of Content<a class=\"anchor\" id=\"TOC\"></a> (ToC)\n",
    "\n",
    "* <a href=\"#bullet1\">1 - Introduction</a>\n",
    "* <a href=\"#bullet2\">2 - Load Text-Fabric app and data</a>\n",
    "* <a href=\"#bullet3\">3 - Performing the queries</a>\n",
    "* <a href=\"#bullet4\">4 - Display the results</a>\n",
    "    * <a href=\"#bullet4x1\">4.1 - Verbal forms distribution in the parasha</a>\n",
    "    * <a href=\"#bullet4x2\">4.2 - Ratio of direct speech versus narrative</a>\n",
    "    * <a href=\"#bullet4x3\">4.3 - Term frequency (excluding stopwords)</a>\n",
    "    * <a href=\"#bullet4x4\">4.4 - Clause types and phrase functions</a>\n",
    "* <a href=\"#bullet5\">5 - References</a>\n",
    "* <a href=\"#bullet6\">6 - Notebook version details</a>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2b6a395a-7903-4885-bbb2-efe113bdece8",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "source": [
    "# 1 - Introduction <a class=\"anchor\" id=\"bullet1\"></a>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d24d4a22-4f03-46cb-a449-653e12e96267",
   "metadata": {},
   "source": [
    "In this notebook, we will first select a Torah portion by its numeric value (1โ€“54) for BHSaddons feature [`parashanum`](https://tonyjurg.github.io/BHSaddons/docs/features/parashanum.html) and perform various analyses on that parasha:\n",
    "- *Data Loading:* Initialize Text-Fabric and load the BHSA corpus with BHSaddons parasha features.\n",
    "- *Selection:* Extract all verses and words belonging to the chosen parasha.\n",
    "- *Verbal Forms Distribution:* Analyze the frequency of Hebrew verb forms (e.g. wayyiqtol, qatal/perfect, yiqtol/imperfect, etc.) in the parasha. We will use the BHSA morphological feature `vt` (verbal tense) which categorizes verb forms (`perf` = perfect/qatal, `impf` = imperfect/yiqtol, `wayq` = wayyiqtol, etc. ([Vt - BHSA](https://etcbc.github.io/bhsa/features/vt))).\n",
    "- *Direct Speech vs Narrative:* Compute the ratio of text that is direct speech vs. narrative. BHSA marks each clause's discourse type using the `domain`/*text type* feature (`Q` = quotation/direct speech, `N` = narrative, `D` = discursive) ([Domain - BHSA](https://etcbc.github.io/bhsa/features/domain/#)). We will measure how much of the parasha is in quoted speech versus narrative description.\n",
    "- *Term Frequency (excluding stopwords):* Determine the most frequent words (lexemes) in the parasha, excluding common function words (like articles, conjunctions, prepositions, pronouns, etc.) to focus on content words. This will be presented as a frequency list and chart.\n",
    "- *Structural Patterns:* Examine syntactic structure by looking at clause and phrase markers. Weโ€™ll mention how BHSA classifies clause types (e.g. `WayX` for a wayyiqtol clause with explicit subject, `Way0` without explicit subject ([Typ - BHSA](https://etcbc.github.io/bhsa/features/typ/#))) and demonstrate analysis of phrase functions (syntactic roles like subject, object, predicate, etc. ([Function - BHSA](https://etcbc.github.io/bhsa/features/function/#))) within the parasha."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0af8fde8-c5fc-4bba-a1bf-ee0618dc95dd",
   "metadata": {},
   "source": [
    "# 2 - Load Text-Fabric app and data <a class=\"anchor\" id=\"bullet2\"></a>\n",
    "##### [Back to ToC](#TOC)\n",
    "\n",
    "First, we  load the BHSA corpus with the BHSaddons module for handling parashot. We use `mod=\"tonyjurg/BHSaddons/tf/\"` to include the parasha features. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "27c41b73-ac23-4e8e-9aec-dfe6ab83c353",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/markdown": [
       "**Locating corpus resources ...**"
      ],
      "text/plain": [
       "<IPython.core.display.Markdown object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<b title=\"local release\">app:</b> <span title=\"rv1.8=#gd905e3fb6e80d0fa537600337614adc2af157309 offline under C:/Users/tonyj/text-fabric-data/github\">~/text-fabric-data/github/etcbc/BHSA/app</span>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<b title=\"local release\">data:</b> <span title=\"rv1.8=#gd905e3fb6e80d0fa537600337614adc2af157309 offline under C:/Users/tonyj/text-fabric-data/github\">~/text-fabric-data/github/etcbc/BHSA/tf/2021</span>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<b title=\"local commit\">data:</b> <span title=\"#79c84ec8b922c7d9632449b2d3a41324294cea03 offline under C:/Users/tonyj/text-fabric-data/github\">~/text-fabric-data/github/tonyjurg/BHSaddons/tf/2021</span>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<b title=\"local release\">data:</b> <span title=\"rv2.1=#gaba4367b49750089e4e4122415a77cac43bd97bc offline under C:/Users/tonyj/text-fabric-data/github\">~/text-fabric-data/github/etcbc/phono/tf/2021</span>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<b title=\"local release\">data:</b> <span title=\"rv2.1=#f45f6cc3c4f933dba6e649f49cdb14a40dcf333f offline under C:/Users/tonyj/text-fabric-data/github\">~/text-fabric-data/github/etcbc/parallels/tf/2021</span>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "            <b>TF:</b> <a target=\"_blank\" href=\"https://annotation.github.io/text-fabric/tf/cheatsheet.html\" title=\"text-fabric api\">TF API 12.6.1</a>, <a target=\"_blank\" href=\"https://github.com/etcbc/BHSA/blob/master/app\" title=\"etcbc/BHSA app\">etcbc/BHSA/app  v3</a>, <a target=\"_blank\" href=\"https://annotation.github.io/text-fabric/tf/about/searchusage.html\" title=\"Search Templates Introduction and Reference\">Search Reference</a><br>\n",
       "            <b>Data:</b> <a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/\" title=\"provenance of BHSA = Biblia Hebraica Stuttgartensia Amstelodamensis\">etcbc - BHSA 2021</a>, <a target=\"_blank\" href=\"https://annotation.github.io/text-fabric/tf/writing/hebrew.html\" title=\"How TF features represent text\">Character table</a>, <a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/0_home\" title=\"etcbc - BHSA feature documentation\">Feature docs</a><br>\n",
       "            <details class=\"nodeinfo\"><summary><b>Node types</b></summary>\n",
       "<table class=\"nodeinfo\">\n",
       "    <tr>\n",
       "        <th>Name</th>\n",
       "        <th># of nodes</th>\n",
       "        <th># slots / node</th>\n",
       "        <th>% coverage</th>\n",
       "    </tr>\n",
       "\n",
       "<tr>\n",
       "    <th>book</th>\n",
       "    <td>39</td>\n",
       "    <td>10938.21</td>\n",
       "    <td><b>100</b></td>\n",
       "</tr>\n",
       "\n",
       "<tr>\n",
       "    <th>chapter</th>\n",
       "    <td>929</td>\n",
       "    <td>459.19</td>\n",
       "    <td><b>100</b></td>\n",
       "</tr>\n",
       "\n",
       "<tr>\n",
       "    <th>lex</th>\n",
       "    <td>9230</td>\n",
       "    <td>46.22</td>\n",
       "    <td><b>100</b></td>\n",
       "</tr>\n",
       "\n",
       "<tr>\n",
       "    <th>verse</th>\n",
       "    <td>23213</td>\n",
       "    <td>18.38</td>\n",
       "    <td><b>100</b></td>\n",
       "</tr>\n",
       "\n",
       "<tr>\n",
       "    <th>half_verse</th>\n",
       "    <td>45179</td>\n",
       "    <td>9.44</td>\n",
       "    <td><b>100</b></td>\n",
       "</tr>\n",
       "\n",
       "<tr>\n",
       "    <th>sentence</th>\n",
       "    <td>63717</td>\n",
       "    <td>6.70</td>\n",
       "    <td><b>100</b></td>\n",
       "</tr>\n",
       "\n",
       "<tr>\n",
       "    <th>sentence_atom</th>\n",
       "    <td>64514</td>\n",
       "    <td>6.61</td>\n",
       "    <td><b>100</b></td>\n",
       "</tr>\n",
       "\n",
       "<tr>\n",
       "    <th>clause</th>\n",
       "    <td>88131</td>\n",
       "    <td>4.84</td>\n",
       "    <td><b>100</b></td>\n",
       "</tr>\n",
       "\n",
       "<tr>\n",
       "    <th>clause_atom</th>\n",
       "    <td>90704</td>\n",
       "    <td>4.70</td>\n",
       "    <td><b>100</b></td>\n",
       "</tr>\n",
       "\n",
       "<tr>\n",
       "    <th>phrase</th>\n",
       "    <td>253203</td>\n",
       "    <td>1.68</td>\n",
       "    <td><b>100</b></td>\n",
       "</tr>\n",
       "\n",
       "<tr>\n",
       "    <th>phrase_atom</th>\n",
       "    <td>267532</td>\n",
       "    <td>1.59</td>\n",
       "    <td><b>100</b></td>\n",
       "</tr>\n",
       "\n",
       "<tr>\n",
       "    <th>subphrase</th>\n",
       "    <td>113850</td>\n",
       "    <td>1.42</td>\n",
       "    <td>38</td>\n",
       "</tr>\n",
       "\n",
       "<tr>\n",
       "    <th><i>word</i></th>\n",
       "    <td>426590</td>\n",
       "    <td>1.00</td>\n",
       "    <td><b>100</b></td>\n",
       "</tr>\n",
       "</table></details>\n",
       "            <b>Sets:</b> no custom sets<br>\n",
       "            <b>Features:</b><br>\n",
       "<details><summary><b>Parallel Passages</b></summary>\n",
       "    <div class=\"fcorpus\">\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat edge\">\n",
       "<a target=\"_blank\" href=\"https://nbviewer.jupyter.org/github/etcbc/parallels/blob/master/programs/parallels.ipynb\" title=\"~/text-fabric-data/github/etcbc/parallels/tf/2021/crossref.tf\">crossref</a>\n",
       "</div>\n",
       "<div class=\"fmono\">int</div>\n",
       "\n",
       "<span> ๐Ÿ†— links between similar passages</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "    </div>\n",
       "</details>\n",
       "\n",
       "<details><summary><b>BHSA = Biblia Hebraica Stuttgartensia Amstelodamensis</b></summary>\n",
       "    <div class=\"fcorpus\">\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/book\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/book.tf\">book</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… book name in Latin (Genesis; Numeri; Reges1; ...)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/book@ll\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/book@am.tf\">book@ll</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… book name in amharic (แŠฃแˆ›แˆญแŠ›)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/chapter\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/chapter.tf\">chapter</a>\n",
       "</div>\n",
       "<div class=\"fmono\">int</div>\n",
       "\n",
       "<span> โœ… chapter number (1; 2; 3; ...)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/code\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/code.tf\">code</a>\n",
       "</div>\n",
       "<div class=\"fmono\">int</div>\n",
       "\n",
       "<span> โœ… identifier of a clause atom relationship (0; 74; 367; ...)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/det\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/det.tf\">det</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… determinedness of phrase(atom) (det; und; NA.)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/domain\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/domain.tf\">domain</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… text type of clause (? (Unknown); N (narrative); D (discursive); Q (Quotation).)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/freq_lex\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/freq_lex.tf\">freq_lex</a>\n",
       "</div>\n",
       "<div class=\"fmono\">int</div>\n",
       "\n",
       "<span> โœ… frequency of lexemes</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/function\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/function.tf\">function</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… syntactic function of phrase (Cmpl; Objc; Pred; ...)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/g_cons\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/g_cons.tf\">g_cons</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… word consonantal-transliterated (B R>CJT BR> >LHJM ...)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/g_cons_utf8\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/g_cons_utf8.tf\">g_cons_utf8</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… word consonantal-Hebrew (ื‘ ืจืืฉืื™ืช ื‘ืจื ืืœื”ื™ื)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/g_lex\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/g_lex.tf\">g_lex</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… lexeme pointed-transliterated (B.:- R;>CIJT B.@R@> >:ELOH ...)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/g_lex_utf8\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/g_lex_utf8.tf\">g_lex_utf8</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… lexeme pointed-Hebrew (ื‘ึฐึผ ืจึตืืฉึดืื™ืช ื‘ึธึผืจึธื ืึฑืœึนื”)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/g_word\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/g_word.tf\">g_word</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… word pointed-transliterated (B.:- R;>CI73JT B.@R@74> >:ELOHI92JM)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/g_word_utf8\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/g_word_utf8.tf\">g_word_utf8</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… word pointed-Hebrew (ื‘ึผึฐ ืจึตืืฉืึดึ–ื™ืช ื‘ึผึธืจึธึฃื ืึฑืœึนื”ึดึ‘ื™ื)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/gloss\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/gloss.tf\">gloss</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> ๐Ÿ†— english translation of lexeme (beginning create god(s))</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/gn\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/gn.tf\">gn</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… grammatical gender (m; f; NA; unknown.)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/label\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/label.tf\">label</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… (half-)verse label (half verses: A; B; C; verses:  GEN 01,02)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/language\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/language.tf\">language</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… of word or lexeme (Hebrew; Aramaic.)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/lex\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/lex.tf\">lex</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… lexeme consonantal-transliterated (B R>CJT/ BR>[ >LHJM/)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/lex_utf8\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/lex_utf8.tf\">lex_utf8</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… lexeme consonantal-Hebrew (ื‘ ืจืืฉืื™ืชึœ ื‘ืจื ืืœื”ื™ืึœ)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/ls\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/ls.tf\">ls</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… lexical set, subclassification of part-of-speech (card; ques; mult)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/nametype\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/nametype.tf\">nametype</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โš ๏ธ named entity type (pers; mens; gens; topo; ppde.)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/nme\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/nme.tf\">nme</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… nominal ending consonantal-transliterated (absent; n/a; JM, ...)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/nu\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/nu.tf\">nu</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… grammatical number (sg; du; pl; NA; unknown.)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/number\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/number.tf\">number</a>\n",
       "</div>\n",
       "<div class=\"fmono\">int</div>\n",
       "\n",
       "<span> โœ… sequence number of an object within its context</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/otype\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/otype.tf\">otype</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> </span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/pargr\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/pargr.tf\">pargr</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> ๐Ÿ†— hierarchical paragraph number (1; 1.2; 1.2.3.4; ...)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/pdp\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/pdp.tf\">pdp</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… phrase dependent part-of-speech (art; verb; subs; nmpr, ...)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/pfm\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/pfm.tf\">pfm</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… preformative consonantal-transliterated (absent; n/a; J, ...)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/prs\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/prs.tf\">prs</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… pronominal suffix consonantal-transliterated (absent; n/a; W; ...)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/prs_gn\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/prs_gn.tf\">prs_gn</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… pronominal suffix gender (m; f; NA; unknown.)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/prs_nu\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/prs_nu.tf\">prs_nu</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… pronominal suffix number (sg; du; pl; NA; unknown.)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/prs_ps\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/prs_ps.tf\">prs_ps</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… pronominal suffix person (p1; p2; p3; NA; unknown.)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/ps\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/ps.tf\">ps</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… grammatical person (p1; p2; p3; NA; unknown.)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/qere\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/qere.tf\">qere</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… word pointed-transliterated masoretic reading correction</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/qere_trailer\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/qere_trailer.tf\">qere_trailer</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… interword material -pointed-transliterated (Masoretic correction)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/qere_trailer_utf8\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/qere_trailer_utf8.tf\">qere_trailer_utf8</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… interword material -pointed-transliterated (Masoretic correction)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/qere_utf8\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/qere_utf8.tf\">qere_utf8</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… word pointed-Hebrew masoretic reading correction</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/rank_lex\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/rank_lex.tf\">rank_lex</a>\n",
       "</div>\n",
       "<div class=\"fmono\">int</div>\n",
       "\n",
       "<span> โœ… ranking of lexemes based on freqnuecy</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/rela\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/rela.tf\">rela</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… linguistic relation between clause/(sub)phrase(atom) (ADJ; MOD; ATR; ...)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/sp\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/sp.tf\">sp</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… part-of-speech (art; verb; subs; nmpr, ...)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/st\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/st.tf\">st</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… state of a noun (a (absolute); c (construct); e (emphatic).)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/tab\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/tab.tf\">tab</a>\n",
       "</div>\n",
       "<div class=\"fmono\">int</div>\n",
       "\n",
       "<span> โœ… clause atom: its level in the linguistic embedding</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/trailer\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/trailer.tf\">trailer</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… interword material pointed-transliterated (& 00 05 00_P ...)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/trailer_utf8\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/trailer_utf8.tf\">trailer_utf8</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… interword material pointed-Hebrew (ึพ ืƒ)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/txt\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/txt.tf\">txt</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… text type of clause and surrounding (repetion of ? N D Q as in feature domain)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/typ\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/typ.tf\">typ</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… clause/phrase(atom) type (VP; NP; Ellp; Ptcp; WayX)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/uvf\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/uvf.tf\">uvf</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… univalent final consonant consonantal-transliterated (absent; N; J; ...)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/vbe\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/vbe.tf\">vbe</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… verbal ending consonantal-transliterated (n/a; W; ...)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/vbs\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/vbs.tf\">vbs</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… root formation consonantal-transliterated (absent; n/a; H; ...)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/verse\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/verse.tf\">verse</a>\n",
       "</div>\n",
       "<div class=\"fmono\">int</div>\n",
       "\n",
       "<span> โœ… verse number</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/voc_lex\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/voc_lex.tf\">voc_lex</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… vocalized lexeme pointed-transliterated (B.: R;>CIJT BR> >:ELOHIJM)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/voc_lex_utf8\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/voc_lex_utf8.tf\">voc_lex_utf8</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… vocalized lexeme pointed-Hebrew (ื‘ึผึฐ ืจึตืืฉืึดื™ืช ื‘ืจื ืึฑืœึนื”ึดื™ื)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/vs\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/vs.tf\">vs</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… verbal stem (qal; piel; hif; apel; pael)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/vt\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/vt.tf\">vt</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> โœ… verbal tense (perf; impv; wayq; infc)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat edge\">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/mother\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/mother.tf\">mother</a>\n",
       "</div>\n",
       "<div class=\"fmono\">none</div>\n",
       "\n",
       "<span> โœ… linguistic dependency between textual objects</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat edge\">\n",
       "<a target=\"_blank\" href=\"https://etcbc.github.io/BHSA/features/oslots\" title=\"~/text-fabric-data/github/etcbc/BHSA/tf/2021/oslots.tf\">oslots</a>\n",
       "</div>\n",
       "<div class=\"fmono\">none</div>\n",
       "\n",
       "<span> </span>\n",
       "\n",
       "</div>\n",
       "\n",
       "    </div>\n",
       "</details>\n",
       "\n",
       "<details><summary><b>Phonetic Transcriptions</b></summary>\n",
       "    <div class=\"fcorpus\">\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://nbviewer.jupyter.org/github/etcbc/phono/blob/master/programs/phono.ipynb\" title=\"~/text-fabric-data/github/etcbc/phono/tf/2021/phono.tf\">phono</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> ๐Ÿ†— phonological transcription (bแตŠ rฤ“ลกหŒรฎแนฏ bฤrหˆฤ ส”แต‰lลhหˆรฎm)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://nbviewer.jupyter.org/github/etcbc/phono/blob/master/programs/phono.ipynb\" title=\"~/text-fabric-data/github/etcbc/phono/tf/2021/phono_trailer.tf\">phono_trailer</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> ๐Ÿ†— interword material in phonological transcription</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "    </div>\n",
       "</details>\n",
       "\n",
       "<details><summary><b><github>tonyjurg/BHSaddons/tf</b></summary>\n",
       "    <div class=\"fcorpus\">\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://github.com/tonyjurg/BHSaddons/tree/master/tf\" title=\"~/text-fabric-data/github/tonyjurg/BHSaddons/tf/2021/aliyotnum.tf\">aliyotnum</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> The sequence number of the aliyot within the parasha</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://github.com/tonyjurg/BHSaddons/tree/master/tf\" title=\"~/text-fabric-data/github/tonyjurg/BHSaddons/tf/2021/maftir.tf\">maftir</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> Set to 1 if this verse is part of a maftir</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://github.com/tonyjurg/BHSaddons/tree/master/tf\" title=\"~/text-fabric-data/github/tonyjurg/BHSaddons/tf/2021/parashahebr.tf\">parashahebr</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> The name of the parasha in Hebrew</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://github.com/tonyjurg/BHSaddons/tree/master/tf\" title=\"~/text-fabric-data/github/tonyjurg/BHSaddons/tf/2021/parashanum.tf\">parashanum</a>\n",
       "</div>\n",
       "<div class=\"fmono\">int</div>\n",
       "\n",
       "<span> The sequence number of the parasha</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://github.com/tonyjurg/BHSaddons/tree/master/tf\" title=\"~/text-fabric-data/github/tonyjurg/BHSaddons/tf/2021/parashatrans.tf\">parashatrans</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> Transliteration of the Hebrew parasha name</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://github.com/tonyjurg/BHSaddons/tree/master/tf\" title=\"~/text-fabric-data/github/tonyjurg/BHSaddons/tf/2021/parashaverse.tf\">parashaverse</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> The sequence number of the verse within the parasha</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "<div class=\"frow\">\n",
       "    <div class=\"fnamecat \">\n",
       "<a target=\"_blank\" href=\"https://github.com/tonyjurg/BHSaddons/tree/master/tf\" title=\"~/text-fabric-data/github/tonyjurg/BHSaddons/tf/2021/wordboundary.tf\">wordboundary</a>\n",
       "</div>\n",
       "<div class=\"fmono\">str</div>\n",
       "\n",
       "<span> indicates wordboudaries (spaces OR maqaf)</span>\n",
       "\n",
       "</div>\n",
       "\n",
       "    </div>\n",
       "</details>\n",
       "\n",
       "            <b>Settings:</b><br><details ><summary><b>specified</b></summary><ol><li><b>apiVersion</b>: <code>3</code></li><li><b>appName</b>: <code>etcbc/BHSA</code></li><li><b>appPath</b>: <code>C:/Users/tonyj/text-fabric-data/github/etcbc/BHSA/app</code></li><li><b>commit</b>: <code>gd905e3fb6e80d0fa537600337614adc2af157309</code></li><li><b>css</b>: <code>''</code></li><li><details><summary><b>dataDisplay</b>:</summary><ul><li><details><summary><b>exampleSectionHtml</b>:</summary><code>&lt;code&gt;Genesis 1:1&lt;/code&gt; (use &lt;a href=\"https://github.com/{org}/{repo}/blob/master/tf/{version}/book%40en.tf\" target=\"_blank\"&gt;English book names&lt;/a&gt;)</code></details></li><li><details><summary><b>excludedFeatures</b>:</summary><ul><li><code>g_uvf_utf8</code></li><li><code>g_vbs</code></li><li><code>kq_hybrid</code></li><li><code>languageISO</code></li><li><code>g_nme</code></li><li><code>lex0</code></li><li><code>is_root</code></li><li><code>g_vbs_utf8</code></li><li><code>g_uvf</code></li><li><code>dist</code></li><li><code>root</code></li><li><code>suffix_person</code></li><li><code>g_vbe</code></li><li><code>dist_unit</code></li><li><code>suffix_number</code></li><li><code>distributional_parent</code></li><li><code>kq_hybrid_utf8</code></li><li><code>crossrefSET</code></li><li><code>instruction</code></li><li><code>g_prs</code></li><li><code>lexeme_count</code></li><li><code>rank_occ</code></li><li><code>g_pfm_utf8</code></li><li><code>freq_occ</code></li><li><code>crossrefLCS</code></li><li><code>functional_parent</code></li><li><code>g_pfm</code></li><li><code>g_nme_utf8</code></li><li><code>g_vbe_utf8</code></li><li><code>kind</code></li><li><code>g_prs_utf8</code></li><li><code>suffix_gender</code></li><li><code>mother_object_type</code></li></ul></details></li><li><details><summary><b>noneValues</b>:</summary><ul><li><code>none</code></li><li><code>unknown</code></li><li><i>no value</i></li><li><code>NA</code></li></ul></details></li></ul></details></li><li><details><summary><b>docs</b>:</summary><ul><li><b>docBase</b>: <code>{docRoot}/{repo}</code></li><li><b>docExt</b>: <code>''</code></li><li><b>docPage</b>: <code>''</code></li><li><b>docRoot</b>: <code>https://{org}.github.io</code></li><li><b>featurePage</b>: <code>0_home</code></li></ul></details></li><li><b>interfaceDefaults</b>: <code>{}</code></li><li><b>isCompatible</b>: <code>True</code></li><li><b>local</b>: <code>local</code></li><li><b>localDir</b>: <code>C:/Users/tonyj/text-fabric-data/github/etcbc/BHSA/_temp</code></li><li><details><summary><b>provenanceSpec</b>:</summary><ul><li><b>corpus</b>: <code>BHSA = Biblia Hebraica Stuttgartensia Amstelodamensis</code></li><li><b>doi</b>: <code>10.5281/zenodo.1007624</code></li><li><details><summary><b>moduleSpecs</b>:</summary><ul><li><details><summary>:</summary><ul><li><b>backend</b>: <i>no value</i></li><li><b>corpus</b>: <code>Phonetic Transcriptions</code></li><li><details><summary><b>docUrl</b>:</summary><code>https://nbviewer.jupyter.org/github/etcbc/phono/blob/master/programs/phono.ipynb</code></details></li><li><b>doi</b>: <code>10.5281/zenodo.1007636</code></li><li><b>org</b>: <code>etcbc</code></li><li><b>relative</b>: <code>/tf</code></li><li><b>repo</b>: <code>phono</code></li></ul></details></li><li><details><summary>:</summary><ul><li><b>backend</b>: <i>no value</i></li><li><b>corpus</b>: <code>Parallel Passages</code></li><li><details><summary><b>docUrl</b>:</summary><code>https://nbviewer.jupyter.org/github/etcbc/parallels/blob/master/programs/parallels.ipynb</code></details></li><li><b>doi</b>: <code>10.5281/zenodo.1007642</code></li><li><b>org</b>: <code>etcbc</code></li><li><b>relative</b>: <code>/tf</code></li><li><b>repo</b>: <code>parallels</code></li></ul></details></li></ul></details></li><li><b>org</b>: <code>etcbc</code></li><li><b>relative</b>: <code>/tf</code></li><li><b>repo</b>: <code>BHSA</code></li><li><b>version</b>: <code>2021</code></li><li><b>webBase</b>: <code>https://shebanq.ancient-data.org/hebrew</code></li><li><b>webHint</b>: <code>Show this on SHEBANQ</code></li><li><b>webLang</b>: <code>la</code></li><li><b>webLexId</b>: <code>True</code></li><li><details><summary><b>webUrl</b>:</summary><code>{webBase}/text?book=&lt;1&gt;&amp;chapter=&lt;2&gt;&amp;verse=&lt;3&gt;&amp;version={version}&amp;mr=m&amp;qw=q&amp;tp=txt_p&amp;tr=hb&amp;wget=v&amp;qget=v&amp;nget=vt</code></details></li><li><b>webUrlLex</b>: <code>{webBase}/word?version={version}&amp;id=&lt;lid&gt;</code></li></ul></details></li><li><b>release</b>: <code>v1.8</code></li><li><details><summary><b>typeDisplay</b>:</summary><ul><li><details><summary><b>clause</b>:</summary><ul><li><b>label</b>: <code>{typ} {rela}</code></li><li><b>style</b>: <code>''</code></li></ul></details></li><li><details><summary><b>clause_atom</b>:</summary><ul><li><b>hidden</b>: <code>True</code></li><li><b>label</b>: <code>{code}</code></li><li><b>level</b>: <code>1</code></li><li><b>style</b>: <code>''</code></li></ul></details></li><li><details><summary><b>half_verse</b>:</summary><ul><li><b>hidden</b>: <code>True</code></li><li><b>label</b>: <code>{label}</code></li><li><b>style</b>: <code>''</code></li><li><b>verselike</b>: <code>True</code></li></ul></details></li><li><details><summary><b>lex</b>:</summary><ul><li><b>featuresBare</b>: <code>gloss</code></li><li><b>label</b>: <code>{voc_lex_utf8}</code></li><li><b>lexOcc</b>: <code>word</code></li><li><b>style</b>: <code>orig</code></li><li><b>template</b>: <code>{voc_lex_utf8}</code></li></ul></details></li><li><details><summary><b>phrase</b>:</summary><ul><li><b>label</b>: <code>{typ} {function}</code></li><li><b>style</b>: <code>''</code></li></ul></details></li><li><details><summary><b>phrase_atom</b>:</summary><ul><li><b>hidden</b>: <code>True</code></li><li><b>label</b>: <code>{typ} {rela}</code></li><li><b>level</b>: <code>1</code></li><li><b>style</b>: <code>''</code></li></ul></details></li><li><details><summary><b>sentence</b>:</summary><ul><li><b>label</b>: <code>{number}</code></li><li><b>style</b>: <code>''</code></li></ul></details></li><li><details><summary><b>sentence_atom</b>:</summary><ul><li><b>hidden</b>: <code>True</code></li><li><b>label</b>: <code>{number}</code></li><li><b>level</b>: <code>1</code></li><li><b>style</b>: <code>''</code></li></ul></details></li><li><details><summary><b>subphrase</b>:</summary><ul><li><b>hidden</b>: <code>True</code></li><li><b>label</b>: <code>{number}</code></li><li><b>style</b>: <code>''</code></li></ul></details></li><li><details><summary><b>word</b>:</summary><ul><li><b>features</b>: <code>pdp vs vt</code></li><li><b>featuresBare</b>: <code>lex:gloss</code></li></ul></details></li></ul></details></li><li><b>writing</b>: <code>hbo</code></li></ol></details>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<style>tr.tf.ltr, td.tf.ltr, th.tf.ltr { text-align: left ! important;}\n",
       "tr.tf.rtl, td.tf.rtl, th.tf.rtl { text-align: right ! important;}\n",
       "@font-face {\n",
       "  font-family: \"Gentium Plus\";\n",
       "  src: local('Gentium Plus'), local('GentiumPlus'),\n",
       "    url('/browser/static/fonts/GentiumPlus-R.woff') format('woff'),\n",
       "    url('https://github.com/annotation/text-fabric/blob/master/tf/browser/static/fonts/GentiumPlus-R.woff?raw=true') format('woff');\n",
       "}\n",
       "\n",
       "@font-face {\n",
       "  font-family: \"Ezra SIL\";\n",
       "  src: local('Ezra SIL'), local('EzraSIL'),\n",
       "    url('/browser/static/fonts/SILEOT.woff') format('woff'),\n",
       "    url('https://github.com/annotation/text-fabric/blob/master/tf/browser/static/fonts/SILEOT.woff?raw=true') format('woff');\n",
       "}\n",
       "\n",
       "@font-face {\n",
       "  font-family: \"SBL Hebrew\";\n",
       "  src: local('SBL Hebrew'), local('SBLHebrew'),\n",
       "    url('/browser/static/fonts/SBL_Hbrw.woff') format('woff'),\n",
       "    url('https://github.com/annotation/text-fabric/blob/master/tf/browser/static/fonts/SBL_Hbrw.woff?raw=true') format('woff');\n",
       "}\n",
       "\n",
       "@font-face {\n",
       "  font-family: \"Estrangelo Edessa\";\n",
       "  src: local('Estrangelo Edessa'), local('EstrangeloEdessa');\n",
       "    url('/browser/static/fonts/SyrCOMEdessa.woff') format('woff'),\n",
       "    url('https://github.com/annotation/text-fabric/blob/master/tf/browser/static/fonts/SyrCOMEdessa.woff?raw=true') format('woff');\n",
       "}\n",
       "\n",
       "@font-face {\n",
       "  font-family: AmiriQuran;\n",
       "  font-style: normal;\n",
       "  font-weight: 400;\n",
       "  src: local('Amiri Quran'), local('AmiriQuran'),\n",
       "    url('/browser/static/fonts/AmiriQuran.woff') format('woff'),\n",
       "    url('https://github.com/annotation/text-fabric/blob/master/tf/browser/static/fonts/AmiriQuran.woff?raw=true') format('woff');\n",
       "}\n",
       "\n",
       "@font-face {\n",
       "  font-family: AmiriQuranColored;\n",
       "  font-style: normal;\n",
       "  font-weight: 400;\n",
       "  src: local('Amiri Quran Colored'), local('AmiriQuranColored'),\n",
       "    url('/browser/static/fonts/AmiriQuranColored.woff') format('woff'),\n",
       "    url('https://github.com/annotation/text-fabric/blob/master/tf/browser/static/fonts/AmiriQuranColored.woff?raw=true') format('woff');\n",
       "}\n",
       "\n",
       "@font-face {\n",
       "  font-family: \"Santakku\";\n",
       "  src: local('Santakku'),\n",
       "    url('/browser/static/fonts/Santakku.woff') format('woff'),\n",
       "    url('https://github.com/annotation/text-fabric/blob/master/tf/browser/static/fonts/Santakku.woff?raw=true') format('woff');\n",
       "}\n",
       "\n",
       "@font-face {\n",
       "  font-family: \"SantakkuM\";\n",
       "  src: local('SantakkuM'),\n",
       "    url('/browser/static/fonts/SantakkuM.woff') format('woff'),\n",
       "    url('https://github.com/annotation/text-fabric/blob/master/tf/browser/static/fonts/SantakkuM.woff?raw=true') format('woff');\n",
       "}\n",
       "\n",
       "/* bypassing some classical notebook settings */\n",
       "div#notebook {\n",
       "  line-height: unset;\n",
       "}\n",
       "/* neutral text */\n",
       ".txtn,.txtn a:visited,.txtn a:link {\n",
       "    font-family: sans-serif;\n",
       "    font-size: medium;\n",
       "    direction: ltr;\n",
       "    unicode-bidi: embed;\n",
       "    text-decoration: none;\n",
       "    color: var(--text-color);\n",
       "}\n",
       "/* transcription text */\n",
       ".txtt,.txtt a:visited,.txtt a:link {\n",
       "    font-family: monospace;\n",
       "    font-size: medium;\n",
       "    direction: ltr;\n",
       "    unicode-bidi: embed;\n",
       "    text-decoration: none;\n",
       "    color: var(--text-color);\n",
       "}\n",
       "/* source text */\n",
       ".txto,.txto a:visited,.txto a:link {\n",
       "    font-family: serif;\n",
       "    font-size: medium;\n",
       "    direction: ltr;\n",
       "    unicode-bidi: embed;\n",
       "    text-decoration: none;\n",
       "    color: var(--text-color);\n",
       "}\n",
       "/* phonetic text */\n",
       ".txtp,.txtp a:visited,.txtp a:link {\n",
       "    font-family: Gentium, sans-serif;\n",
       "    font-size: medium;\n",
       "    direction: ltr;\n",
       "    unicode-bidi: embed;\n",
       "    text-decoration: none;\n",
       "    color: var(--text-color);\n",
       "}\n",
       "/* original script text */\n",
       ".txtu,.txtu a:visited,.txtu a:link {\n",
       "    font-family: Gentium, sans-serif;\n",
       "    font-size: medium;\n",
       "    text-decoration: none;\n",
       "    color: var(--text-color);\n",
       "}\n",
       "/* hebrew */\n",
       ".txtu.hbo,.lex.hbo {\n",
       "    font-family: \"Ezra SIL\", \"SBL Hebrew\", sans-serif;\n",
       "    font-size: large;\n",
       "    direction: rtl ! important;\n",
       "    unicode-bidi: embed;\n",
       "}\n",
       "/* syriac */\n",
       ".txtu.syc,.lex.syc {\n",
       "    font-family: \"Estrangelo Edessa\", sans-serif;\n",
       "    font-size: medium;\n",
       "    direction: rtl ! important;\n",
       "    unicode-bidi: embed;\n",
       "}\n",
       "/* neo aramaic */\n",
       ".txtu.cld,.lex.cld {\n",
       "    font-family: \"CharisSIL-R\", sans-serif;\n",
       "    font-size: medium;\n",
       "    direction: ltr ! important;\n",
       "    unicode-bidi: embed;\n",
       "}\n",
       "/* standard arabic */\n",
       ".txtu.ara,.lex.ara {\n",
       "    font-family: \"AmiriQuran\", sans-serif;\n",
       "    font-size: large;\n",
       "    direction: rtl ! important;\n",
       "    unicode-bidi: embed;\n",
       "}\n",
       "/* cuneiform */\n",
       ".txtu.akk,.lex.akk {\n",
       "    font-family: Santakku, sans-serif;\n",
       "    font-size: large;\n",
       "    direction: ltr ! important;\n",
       "    unicode-bidi: embed;\n",
       "}\n",
       ".txtu.uga,.lex.uga {\n",
       "    font-family: sans-serif;\n",
       "    /*font-family: Noto Sans Ugaritic, sans-serif;*/\n",
       "    font-size: large;\n",
       "    direction: ltr ! important;\n",
       "    unicode-bidi: embed;\n",
       "}\n",
       "/* greek */\n",
       ".txtu.grc,.lex.grc a:link {\n",
       "    font-family: Gentium, sans-serif;\n",
       "    font-size: medium;\n",
       "    direction: ltr ! important;\n",
       "    unicode-bidi: embed;\n",
       "}\n",
       "a:hover {\n",
       "    text-decoration: underline | important;\n",
       "    color: #0000ff | important;\n",
       "}\n",
       ".ltr {\n",
       "    direction: ltr ! important;\n",
       "    unicode-bidi: embed;\n",
       "}\n",
       ".rtl {\n",
       "    direction: rtl ! important;\n",
       "    unicode-bidi: embed;\n",
       "}\n",
       ".ubd {\n",
       "    unicode-bidi: embed;\n",
       "}\n",
       ".col {\n",
       "   display: inline-block;\n",
       "}\n",
       ".features {\n",
       "    font-family: monospace;\n",
       "    font-size: medium;\n",
       "    font-weight: bold;\n",
       "    color: var(--features);\n",
       "    display: flex;\n",
       "    flex-flow: column nowrap;\n",
       "    justify-content: flex-start;\n",
       "    align-items: flex-start;\n",
       "    align-content: flex-start;\n",
       "    padding: 2px;\n",
       "    margin: 2px;\n",
       "    direction: ltr;\n",
       "    unicode-bidi: embed;\n",
       "    border: var(--meta-width) solid var(--meta-color);\n",
       "    border-radius: var(--meta-width);\n",
       "}\n",
       ".features div,.features span {\n",
       "    padding: 0;\n",
       "    margin: -2px 0;\n",
       "}\n",
       ".features .f {\n",
       "    font-family: sans-serif;\n",
       "    font-size: small;\n",
       "    font-weight: normal;\n",
       "    color: #5555bb;\n",
       "}\n",
       ".features .xft {\n",
       "  color: #000000;\n",
       "  background-color: #eeeeee;\n",
       "  font-size: medium;\n",
       "  margin: 2px 0px;\n",
       "}\n",
       ".features .xft .f {\n",
       "  color: #000000;\n",
       "  background-color: #eeeeee;\n",
       "  font-size: small;\n",
       "  font-weight: normal;\n",
       "}\n",
       ".tfsechead {\n",
       "    font-family: sans-serif;\n",
       "    font-size: small;\n",
       "    font-weight: bold;\n",
       "    color: var(--tfsechead);\n",
       "    unicode-bidi: embed;\n",
       "    text-align: start;\n",
       "}\n",
       ".structure {\n",
       "    font-family: sans-serif;\n",
       "    font-size: small;\n",
       "    font-weight: bold;\n",
       "    color: var(--structure);\n",
       "    unicode-bidi: embed;\n",
       "    text-align: start;\n",
       "}\n",
       ".comments {\n",
       "    display: flex;\n",
       "    justify-content: flex-start;\n",
       "    align-items: flex-start;\n",
       "    align-content: flex-start;\n",
       "    flex-flow: column nowrap;\n",
       "}\n",
       ".nd, a:link.nd {\n",
       "    font-family: sans-serif;\n",
       "    font-size: small;\n",
       "    color: var(--node);\n",
       "    vertical-align: super;\n",
       "    direction: ltr ! important;\n",
       "    unicode-bidi: embed;\n",
       "}\n",
       ".nde, a:link.nde {\n",
       "    font-family: sans-serif;\n",
       "    font-size: small;\n",
       "    color: var(--node);\n",
       "    direction: ltr ! important;\n",
       "    unicode-bidi: embed;\n",
       "}\n",
       ".etf {\n",
       "    font-size: normal;\n",
       "    border-radius: 0.2rem;\n",
       "    border: 1pt solid white;\n",
       "    padding: 0 0.2rem ! important;\n",
       "    margin: 0 0.2rem ! important;\n",
       "}\n",
       ".etfx {\n",
       "    font-size: x-large;\n",
       "}\n",
       ".lex {\n",
       "  color: var(--lex-color);;\n",
       "}\n",
       "#colormapplus, #colormapmin, .ecolormapmin {\n",
       "  font-weight: bold;\n",
       "  border-radius: 0.1rem;\n",
       "  background-color: #eeeeff;\n",
       "  padding: 0 1rem;\n",
       "  margin: 0 1rem;\n",
       "}\n",
       ".clr {\n",
       "  font-style: italic;\n",
       "  font-size: small;\n",
       "}\n",
       ".clmap,.eclmap {\n",
       "  padding: 0;\n",
       "}\n",
       ".children,.children.ltr {\n",
       "    display: flex;\n",
       "    border: 0;\n",
       "    background-color: #ffffff;\n",
       "    justify-content: flex-start;\n",
       "    align-items: flex-start;\n",
       "    align-content: flex-start;\n",
       "}\n",
       ".children.stretch {\n",
       "    align-items: stretch;\n",
       "}\n",
       ".children.hor {\n",
       "    flex-flow: row nowrap;\n",
       "}\n",
       ".children.hor.wrap {\n",
       "    flex-flow: row wrap;\n",
       "}\n",
       ".children.ver {\n",
       "    flex-flow: column nowrap;\n",
       "}\n",
       ".children.ver.wrap {\n",
       "    flex-flow: column wrap;\n",
       "}\n",
       ".contnr {\n",
       "    width: fit-content;\n",
       "    display: flex;\n",
       "    justify-content: flex-start;\n",
       "    align-items: flex-start;\n",
       "    align-content: flex-start;\n",
       "    flex-flow: column nowrap;\n",
       "    background: #ffffff none repeat scroll 0 0;\n",
       "    padding:  10px 2px 2px 2px;\n",
       "    margin: 16px 2px 2px 2px;\n",
       "    border-style: solid;\n",
       "    font-size: small;\n",
       "}\n",
       ".contnr.trm {\n",
       "    background-attachment: local;\n",
       "}\n",
       ".contnr.cnul {\n",
       "    padding:  0;\n",
       "    margin: 0;\n",
       "    border-style: solid;\n",
       "    font-size: xx-small;\n",
       "}\n",
       ".contnr.cnul,.lbl.cnul {\n",
       "    border-color: var(--border-color-nul);\n",
       "    border-width: var(--border-width-nul);\n",
       "    border-radius: var(--border-width-nul);\n",
       "}\n",
       ".contnr.c0,.lbl.c0 {\n",
       "    border-color: var(--border-color0);\n",
       "    border-width: var(--border-width0);\n",
       "    border-radius: var(--border-width0);\n",
       "}\n",
       ".contnr.c1,.lbl.c1 {\n",
       "    border-color: var(--border-color1);\n",
       "    border-width: var(--border-width1);\n",
       "    border-radius: var(--border-width1);\n",
       "}\n",
       ".contnr.c2,.lbl.c2 {\n",
       "    border-color: var(--border-color2);\n",
       "    border-width: var(--border-width2);\n",
       "    border-radius: var(--border-width2);\n",
       "}\n",
       ".contnr.c3,.lbl.c3 {\n",
       "    border-color: var(--border-color3);\n",
       "    border-width: var(--border-width3);\n",
       "    border-radius: var(--border-width3);\n",
       "}\n",
       ".contnr.c4,.lbl.c4 {\n",
       "    border-color: var(--border-color4);\n",
       "    border-width: var(--border-width4);\n",
       "    border-radius: var(--border-width4);\n",
       "}\n",
       "span.plain {\n",
       "    /*display: inline-block;*/\n",
       "    display: inline-flex;\n",
       "    flex-flow: row wrap;\n",
       "    white-space: pre-wrap;\n",
       "}\n",
       "span.break {\n",
       "  flex-basis: 100%;\n",
       "  height: 0;\n",
       "}\n",
       ".plain {\n",
       "    background-color: #ffffff;\n",
       "}\n",
       ".plain.l,.contnr.l,.contnr.l>.lbl {\n",
       "    border-left-style: dotted\n",
       "}\n",
       ".plain.r,.contnr.r,.contnr.r>.lbl {\n",
       "    border-right-style: dotted\n",
       "}\n",
       ".plain.lno,.contnr.lno,.contnr.lno>.lbl {\n",
       "    border-left-style: none\n",
       "}\n",
       ".plain.rno,.contnr.rno,.contnr.rno>.lbl {\n",
       "    border-right-style: none\n",
       "}\n",
       ".plain.l {\n",
       "    padding-left: 4px;\n",
       "    margin-left: 2px;\n",
       "    border-width: var(--border-width-plain);\n",
       "}\n",
       ".plain.r {\n",
       "    padding-right: 4px;\n",
       "    margin-right: 2px;\n",
       "    border-width: var(--border-width-plain);\n",
       "}\n",
       ".lbl {\n",
       "    font-family: monospace;\n",
       "    margin-top: -24px;\n",
       "    margin-left: 20px;\n",
       "    background: #ffffff none repeat scroll 0 0;\n",
       "    padding: 0 6px;\n",
       "    border-style: solid;\n",
       "    display: block;\n",
       "    color: var(--label)\n",
       "}\n",
       ".lbl.trm {\n",
       "    background-attachment: local;\n",
       "    margin-top: 2px;\n",
       "    margin-left: 2px;\n",
       "    padding: 2px 2px;\n",
       "    border-style: none;\n",
       "}\n",
       ".lbl.cnul {\n",
       "    font-size: xx-small;\n",
       "}\n",
       ".lbl.c0 {\n",
       "    font-size: small;\n",
       "}\n",
       ".lbl.c1 {\n",
       "    font-size: small;\n",
       "}\n",
       ".lbl.c2 {\n",
       "    font-size: medium;\n",
       "}\n",
       ".lbl.c3 {\n",
       "    font-size: medium;\n",
       "}\n",
       ".lbl.c4 {\n",
       "    font-size: large;\n",
       "}\n",
       ".occs, a:link.occs {\n",
       "    font-size: small;\n",
       "}\n",
       "\n",
       "/* PROVENANCE */\n",
       "\n",
       "div.prov {\n",
       "\tmargin: 40px;\n",
       "\tpadding: 20px;\n",
       "\tborder: 2px solid var(--fog-rim);\n",
       "}\n",
       "div.pline {\n",
       "\tdisplay: flex;\n",
       "\tflex-flow: row nowrap;\n",
       "\tjustify-content: stretch;\n",
       "\talign-items: baseline;\n",
       "}\n",
       "div.p2line {\n",
       "\tmargin-left: 2em;\n",
       "\tdisplay: flex;\n",
       "\tflex-flow: row nowrap;\n",
       "\tjustify-content: stretch;\n",
       "\talign-items: baseline;\n",
       "}\n",
       "div.psline {\n",
       "\tdisplay: flex;\n",
       "\tflex-flow: row nowrap;\n",
       "\tjustify-content: stretch;\n",
       "\talign-items: baseline;\n",
       "\tbackground-color: var(--gold-mist-back);\n",
       "}\n",
       "div.pname {\n",
       "\tflex: 0 0 5rem;\n",
       "\tfont-weight: bold;\n",
       "}\n",
       "div.pval {\n",
       "    flex: 1 1 auto;\n",
       "}\n",
       "\n",
       "/* KEYBOARD */\n",
       ".ccoff {\n",
       "  background-color: inherit;\n",
       "}\n",
       ".ccon {\n",
       "  background-color: yellow ! important;\n",
       "}\n",
       ".ccon,.ccoff {\n",
       "  padding: 0.2rem;\n",
       "  margin: 0.2rem;\n",
       "  border: 0.1rem solid var(--letter-box-border);\n",
       "  border-radius: 0.1rem;\n",
       "}\n",
       ".ccline {\n",
       "  font-size: xx-large ! important;\n",
       "  font-weight: bold;\n",
       "  line-height: 2em ! important;\n",
       "}\n",
       "/* TF header */\n",
       "\n",
       "summary {\n",
       "  /* needed to override the normalize.less\n",
       "   * in the classical Jupyter Notebook\n",
       "   */\n",
       "  display: list-item ! important;\n",
       "}\n",
       "\n",
       ".fcorpus {\n",
       "  display: flex;\n",
       "  flex-flow: column nowrap;\n",
       "  justify-content: flex-start;\n",
       "  align-items: flex-start;\n",
       "  align-content: flex-start;\n",
       "  overflow: auto;\n",
       "}\n",
       ".frow {\n",
       "  display: flex;\n",
       "  flex-flow: row nowrap;\n",
       "  justify-content: flex-start;\n",
       "  align-items: flex-start;\n",
       "  align-content: flex-start;\n",
       "}\n",
       ".fmeta {\n",
       "  display: flex;\n",
       "  flex-flow: column nowrap;\n",
       "  justify-content: flex-start;\n",
       "  align-items: flex-start;\n",
       "  align-content: flex-start;\n",
       "}\n",
       ".fmetarow {\n",
       "  display: flex;\n",
       "  flex-flow: row nowrap;\n",
       "  justify-content: flex-start;\n",
       "  align-items: flex-start;\n",
       "  align-content: flex-start;\n",
       "}\n",
       ".fmetakey {\n",
       "  min-width: 8em;\n",
       "  font-family: monospace;\n",
       "}\n",
       ".fnamecat {\n",
       "  min-width: 8em;\n",
       "}\n",
       ".fnamecat.edge {\n",
       "  font-weight: bold;\n",
       "  font-style: italic;\n",
       "}\n",
       ".fmono {\n",
       "    font-family: monospace;\n",
       "}\n",
       "\n",
       ":root {\n",
       "\t--node:               hsla(120, 100%,  20%, 1.0  );\n",
       "\t--label:              hsla(  0, 100%,  20%, 1.0  );\n",
       "\t--tfsechead:          hsla(  0, 100%,  25%, 1.0  );\n",
       "\t--structure:          hsla(120, 100%,  25%, 1.0  );\n",
       "\t--features:           hsla(  0,   0%,  30%, 1.0  );\n",
       "  --text-color:         hsla( 60,  80%,  10%, 1.0  );\n",
       "  --lex-color:          hsla(220,  90%,  60%, 1.0  );\n",
       "  --meta-color:         hsla(  0,   0%,  90%, 0.7  );\n",
       "  --meta-width:         3px;\n",
       "  --border-color-nul:   hsla(  0,   0%,  90%, 0.5  );\n",
       "  --border-color0:      hsla(  0,   0%,  90%, 0.9  );\n",
       "  --border-color1:      hsla(  0,   0%,  80%, 0.9  );\n",
       "  --border-color2:      hsla(  0,   0%,  70%, 0.9  );\n",
       "  --border-color3:      hsla(  0,   0%,  80%, 0.8  );\n",
       "  --border-color4:      hsla(  0,   0%,  60%, 0.9  );\n",
       "\t--letter-box-border:  hsla(  0,   0%,  80%, 0.5  );\n",
       "  --border-width-nul:   2px;\n",
       "  --border-width0:      2px;\n",
       "  --border-width1:      3px;\n",
       "  --border-width2:      4px;\n",
       "  --border-width3:      6px;\n",
       "  --border-width4:      5px;\n",
       "  --border-width-plain: 2px;\n",
       "}\n",
       ".hl {\n",
       "  background-color: var(--hl-strong);\n",
       "}\n",
       "span.hl {\n",
       "\tbackground-color: var(--hl-strong);\n",
       "\tborder-width: 0;\n",
       "\tborder-radius: 2px;\n",
       "\tborder-style: solid;\n",
       "}\n",
       "div.contnr.hl,div.lbl.hl {\n",
       "  background-color: var(--hl-strong);\n",
       "}\n",
       "div.contnr.hl {\n",
       "  border-color: var(--hl-rim) ! important;\n",
       "\tborder-width: 4px ! important;\n",
       "}\n",
       "\n",
       "span.hlbx {\n",
       "\tborder-color: var(--hl-rim);\n",
       "\tborder-width: 4px ! important;\n",
       "\tborder-style: solid;\n",
       "\tborder-radius: 6px;\n",
       "  padding: 4px;\n",
       "  margin: 4px;\n",
       "}\n",
       ".ehl {\n",
       "  background-color: var(--ehl-strong);\n",
       "}\n",
       "\n",
       ":root {\n",
       "\t--hl-strong:        hsla( 60, 100%,  70%, 0.9  );\n",
       "\t--hl-rim:           hsla( 55,  80%,  50%, 1.0  );\n",
       "\t--ehl-strong:       hsla(240, 100%,  70%, 0.9  );\n",
       "}\n",
       "</style>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "<script>\n",
       "globalThis.copyChar = (el, c) => {\n",
       "    for (const el of document.getElementsByClassName('ccon')) {\n",
       "        el.className = 'ccoff'\n",
       "    }\n",
       "    el.className = 'ccon'\n",
       "    navigator.clipboard.writeText(String.fromCharCode(c))\n",
       "}\n",
       "</script>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div><b>TF API:</b> names <a target=\"_blank\" href=\"https://annotation.github.io/text-fabric/tf/cheatsheet.html\" title=\"doc\">N F E L T S C TF Fs Fall Es Eall Cs Call</a> directly usable</div><hr>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Import necessary libraries\n",
    "from tf.app import use\n",
    "from collections import Counter\n",
    "import pandas as pd  # for easy data manipulation (optional, for frequency tables)\n",
    "from bokeh.io import output_file, show\n",
    "from bokeh.plotting import figure\n",
    "from bokeh.models import ColumnDataSource, Select, CustomJS, HoverTool\n",
    "from wordcloud import WordCloud\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "# Load BHSA with BHSaddons features\n",
    "# This will load the BHSA data (version 2021) and the additional parashot markers.\n",
    "A = use(\"etcbc/BHSA\", version=\"2021\", mod=\"tonyjurg/BHSaddons/tf/\", hoist=globals())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "14a071cc-2ef7-43bf-8cca-1fe4ecf0bdb3",
   "metadata": {},
   "source": [
    "# 3 - Performing the queries <a class=\"anchor\" id=\"bullet3\"></a>\n",
    "##### [Back to ToC](#TOC)\n",
    "\n",
    "In this step, set the `parasha_num` to the portion we want to analyze. The number corresponds to the traditional sequence of weekly Torah readings (1 = Bereshit, 2 = Noach, ..., 54 = V'Zot HaBerakhah). The code below will find all verses belonging to that parasha, then gather all the words in those verses for analysis."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "c4e60413-58a6-49e7-84c5-87074aa83634",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Selected Parasha 12: Vayechi (ื•ึทื™ึฐื—ึดื™)\n",
      "Parasha range: Genesis 47:28 through Genesis 50:26\n"
     ]
    }
   ],
   "source": [
    "# Select the parasha by its number (1 to 54)\n",
    "parasha_num = 12  # <-- Change this number to select a different parasha\n",
    "\n",
    "# Find all verse nodes that belong to the chosen parasha\n",
    "verses_in_parasha = [v for v in F.otype.s(\"verse\") if F.parashanum.v(v) == parasha_num]\n",
    "\n",
    "if verses_in_parasha: \n",
    "    # Identify the range of verses (from first to last)\n",
    "    first_verse = verses_in_parasha[0]\n",
    "    last_verse = verses_in_parasha[-1]\n",
    "    # Get the parasha name in Hebrew and transliteration\n",
    "    parasha_name_trans = F.parashatrans.v(first_verse) \n",
    "    parasha_name_hebrew = F.parashahebr.v(first_verse)  \n",
    "    print(f\"Selected Parasha {parasha_num}: {parasha_name_trans} ({parasha_name_hebrew})\")\n",
    "    start_ref = T.sectionFromNode(first_verse)  # (Book, chapter, verse)\n",
    "    end_ref   = T.sectionFromNode(last_verse)\n",
    "    print(f\"Parasha range: {start_ref[0]} {start_ref[1]}:{start_ref[2]} through {end_ref[0]} {end_ref[1]}:{end_ref[2]}\")\n",
    "else:\n",
    "    print(\"No verses found for the given parasha number. Make sure the number is 1-54.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9b57b19a-d503-4601-ac55-d0bda63e3182",
   "metadata": {},
   "source": [
    "Now we gather all word tokens in these verses, and also collect clause and phrase units for later structural analysis:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "296762ab-7007-4529-b939-25d562bb32cd",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Total verses: 85\n",
      "Total words: 1558\n",
      "Total clauses: 353\n",
      "Total phrases: 1009\n"
     ]
    }
   ],
   "source": [
    "# Gather all word nodes in the selected parasha\n",
    "words_in_parasha = []\n",
    "for v in verses_in_parasha:\n",
    "    words_in_parasha += L.d(v, \"word\")  # all word objects descending from the verse\n",
    "\n",
    "# Also gather all clauses and phrases in the parasha (for later analysis)\n",
    "clauses_in_parasha = []\n",
    "phrases_in_parasha = []\n",
    "for v in verses_in_parasha:\n",
    "    clauses_in_parasha += L.d(v, \"clause\")\n",
    "    phrases_in_parasha += L.d(v, \"phrase\")\n",
    "\n",
    "print(f\"Total verses: {len(verses_in_parasha)}\")\n",
    "print(f\"Total words: {len(words_in_parasha)}\")\n",
    "print(f\"Total clauses: {len(clauses_in_parasha)}\")\n",
    "print(f\"Total phrases: {len(phrases_in_parasha)}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "114f397a-05cb-4ca1-b3fe-e2ec85c5d02a",
   "metadata": {},
   "source": [
    "This will output the counts of verses, words, clauses, and phrases in the parasha. We will use `words_in_parasha` for lexical statistics and `clauses_in_parasha`/`phrases_in_parasha` for discourse and syntax analysis. \n",
    "\n",
    "*(Note: \"word\", \"clause\", and \"phrase\" are Text-Fabric object types in BHSA. Each word is a smallest textual unit (generally corresponding to a lexical item, including prefixes if attached). \"Clause\" here refers to a clause or clause atom in the syntactic hierarchy, and \"phrase\" to a phrase or subphrase. The BHSA annotations allow us to traverse these levels easily via the `L` api for local relations.)*"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6dfa2b06-4328-4d72-98c5-c1940dd42dec",
   "metadata": {
    "editable": true,
    "slideshow": {
     "slide_type": ""
    },
    "tags": []
   },
   "source": [
    "# 4 - Display the results <a class=\"anchor\" id=\"bullet4\"></a>\n",
    "##### [Back to ToC](#TOC)\n",
    "\n",
    "## 4.1 - Verbal forms distribution in the parasha <a class=\"anchor\" id=\"bullet4x1\"></a>\n",
    "\n",
    "Biblical Hebrew verbs appear in different conjugations / forms such as *qatal* (perfect), *yiqtol* (imperfect), *wayyiqtol* (the narrative past form with prefixed *waw*), *imperative*, *infinitive*, *participle*, etc. Weโ€™ll quantify how often each form occurs in this parasha.\n",
    "\n",
    "The BHSA feature `vt` (verbal tense) classifies verb *words* by form ([Vt - BHSA](https://etcbc.github.io/bhsa/features/vt/#)). Possible values include `\"perf\"` (perfect/qatal), `\"impf\"` (imperfect/yiqtol), `\"wayq\"` (wayyiqtol), `\"impv\"` (imperative), `\"infa\"/\"infc\"` (infinitive absolute/construct), `\"ptca\"/\"ptcp\"` (participle active/passive), or `\"NA\"` for words that are not verbs. \n",
    "\n",
    "Let's count the verb instances by `vt` value:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "a5eedd98-828f-4f7f-8a3b-d89ea0cf1371",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Verb Form Distribution:\n",
      "  wayq: 103\n",
      "  perf: 63\n",
      "  impf: 54\n",
      "  ptca: 25\n",
      "  infc: 24\n",
      "  impv: 14\n",
      "  infa: 3\n",
      "  ptcp: 2\n"
     ]
    }
   ],
   "source": [
    "# Filter the words to only verbs and count each verb form (vt value)\n",
    "verb_words = [w for w in words_in_parasha if F.sp.v(w) == \"verb\"]  # sp = part of speech\n",
    "verb_form_counts = Counter(F.vt.v(w) for w in verb_words)\n",
    "\n",
    "# Pretty-print the counts of each verb form\n",
    "print(\"Verb Form Distribution:\")\n",
    "for form, count in verb_form_counts.most_common():\n",
    "    if form == \"NA\":\n",
    "        continue  # skip \"NA\" (if any, non-verbs)\n",
    "    print(f\"  {form}: {count}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cdc03ae2-7397-4e02-8498-761b9cf5d328",
   "metadata": {},
   "source": [
    "This will list the verb forms present and their frequencies. Now, we create a bar chart to visualize this distribution. Additionally, we want to make it interactive: allow filtering by narrative vs. direct speech contexts.\n",
    "To enable this, we will use the clause `domain` feature (text type) to separate verbs used in direct speech (domain = `Q`) versus narrative (domain = `N` or `D`). We'll prepare counts for: \n",
    "- *All* occurrences (default),\n",
    "- *Narrative* (including discursive, i.e. domain != Q),\n",
    "- *Direct Speech* (domain = Q).\n",
    "\n",
    "Then, using a Bokeh `Select` widget, the user can switch the view between All/Narrative/Direct speech."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "70a50830-4c9a-4a4a-a334-229302803365",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "    <style>\n",
       "        .bk-notebook-logo {\n",
       "            display: block;\n",
       "            width: 20px;\n",
       "            height: 20px;\n",
       "            background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAOkSURBVDiNjZRtaJVlGMd/1/08zzln5zjP1LWcU9N0NkN8m2CYjpgQYQXqSs0I84OLIC0hkEKoPtiH3gmKoiJDU7QpLgoLjLIQCpEsNJ1vqUOdO7ppbuec5+V+rj4ctwzd8IIbbi6u+8f1539dt3A78eXC7QizUF7gyV1fD1Yqg4JWz84yffhm0qkFqBogB9rM8tZdtwVsPUhWhGcFJngGeWrPzHm5oaMmkfEg1usvLFyc8jLRqDOMru7AyC8saQr7GG7f5fvDeH7Ej8CM66nIF+8yngt6HWaKh7k49Soy9nXurCi1o3qUbS3zWfrYeQDTB/Qj6kX6Ybhw4B+bOYoLKCC9H3Nu/leUTZ1JdRWkkn2ldcCamzrcf47KKXdAJllSlxAOkRgyHsGC/zRday5Qld9DyoM4/q/rUoy/CXh3jzOu3bHUVZeU+DEn8FInkPBFlu3+nW3Nw0mk6vCDiWg8CeJaxEwuHS3+z5RgY+YBR6V1Z1nxSOfoaPa4LASWxxdNp+VWTk7+4vzaou8v8PN+xo+KY2xsw6une2frhw05CTYOmQvsEhjhWjn0bmXPjpE1+kplmmkP3suftwTubK9Vq22qKmrBhpY4jvd5afdRA3wGjFAgcnTK2s4hY0/GPNIb0nErGMCRxWOOX64Z8RAC4oCXdklmEvcL8o0BfkNK4lUg9HTl+oPlQxdNo3Mg4Nv175e/1LDGzZen30MEjRUtmXSfiTVu1kK8W4txyV6BMKlbgk3lMwYCiusNy9fVfvvwMxv8Ynl6vxoByANLTWplvuj/nF9m2+PDtt1eiHPBr1oIfhCChQMBw6Aw0UulqTKZdfVvfG7VcfIqLG9bcldL/+pdWTLxLUy8Qq38heUIjh4XlzZxzQm19lLFlr8vdQ97rjZVOLf8nclzckbcD4wxXMidpX30sFd37Fv/GtwwhzhxGVAprjbg0gCAEeIgwCZyTV2Z1REEW8O4py0wsjeloKoMr6iCY6dP92H6Vw/oTyICIthibxjm/DfN9lVz8IqtqKYLUXfoKVMVQVVJOElGjrnnUt9T9wbgp8AyYKaGlqingHZU/uG2NTZSVqwHQTWkx9hxjkpWDaCg6Ckj5qebgBVbT3V3NNXMSiWSDdGV3hrtzla7J+duwPOToIg42ChPQOQjspnSlp1V+Gjdged7+8UN5CRAV7a5EdFNwCjEaBR27b3W890TE7g24NAP/mMDXRWrGoFPQI9ls/MWO2dWFAar/xcOIImbbpA3zgAAAABJRU5ErkJggg==);\n",
       "        }\n",
       "    </style>\n",
       "    <div>\n",
       "        <a href=\"https://bokeh.org\" target=\"_blank\" class=\"bk-notebook-logo\"></a>\n",
       "        <span id=\"f8960120-f043-4a81-91cf-46b7d25b428f\">Loading BokehJS ...</span>\n",
       "    </div>\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/javascript": [
       "'use strict';\n",
       "(function(root) {\n",
       "  function now() {\n",
       "    return new Date();\n",
       "  }\n",
       "\n",
       "  const force = true;\n",
       "\n",
       "  if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n",
       "    root._bokeh_onload_callbacks = [];\n",
       "    root._bokeh_is_loading = undefined;\n",
       "  }\n",
       "\n",
       "const JS_MIME_TYPE = 'application/javascript';\n",
       "  const HTML_MIME_TYPE = 'text/html';\n",
       "  const EXEC_MIME_TYPE = 'application/vnd.bokehjs_exec.v0+json';\n",
       "  const CLASS_NAME = 'output_bokeh rendered_html';\n",
       "\n",
       "  /**\n",
       "   * Render data to the DOM node\n",
       "   */\n",
       "  function render(props, node) {\n",
       "    const script = document.createElement(\"script\");\n",
       "    node.appendChild(script);\n",
       "  }\n",
       "\n",
       "  /**\n",
       "   * Handle when an output is cleared or removed\n",
       "   */\n",
       "  function handleClearOutput(event, handle) {\n",
       "    function drop(id) {\n",
       "      const view = Bokeh.index.get_by_id(id)\n",
       "      if (view != null) {\n",
       "        view.model.document.clear()\n",
       "        Bokeh.index.delete(view)\n",
       "      }\n",
       "    }\n",
       "\n",
       "    const cell = handle.cell;\n",
       "\n",
       "    const id = cell.output_area._bokeh_element_id;\n",
       "    const server_id = cell.output_area._bokeh_server_id;\n",
       "\n",
       "    // Clean up Bokeh references\n",
       "    if (id != null) {\n",
       "      drop(id)\n",
       "    }\n",
       "\n",
       "    if (server_id !== undefined) {\n",
       "      // Clean up Bokeh references\n",
       "      const cmd_clean = \"from bokeh.io.state import curstate; print(curstate().uuid_to_server['\" + server_id + \"'].get_sessions()[0].document.roots[0]._id)\";\n",
       "      cell.notebook.kernel.execute(cmd_clean, {\n",
       "        iopub: {\n",
       "          output: function(msg) {\n",
       "            const id = msg.content.text.trim()\n",
       "            drop(id)\n",
       "          }\n",
       "        }\n",
       "      });\n",
       "      // Destroy server and session\n",
       "      const cmd_destroy = \"import bokeh.io.notebook as ion; ion.destroy_server('\" + server_id + \"')\";\n",
       "      cell.notebook.kernel.execute(cmd_destroy);\n",
       "    }\n",
       "  }\n",
       "\n",
       "  /**\n",
       "   * Handle when a new output is added\n",
       "   */\n",
       "  function handleAddOutput(event, handle) {\n",
       "    const output_area = handle.output_area;\n",
       "    const output = handle.output;\n",
       "\n",
       "    // limit handleAddOutput to display_data with EXEC_MIME_TYPE content only\n",
       "    if ((output.output_type != \"display_data\") || (!Object.prototype.hasOwnProperty.call(output.data, EXEC_MIME_TYPE))) {\n",
       "      return\n",
       "    }\n",
       "\n",
       "    const toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n",
       "\n",
       "    if (output.metadata[EXEC_MIME_TYPE][\"id\"] !== undefined) {\n",
       "      toinsert[toinsert.length - 1].firstChild.textContent = output.data[JS_MIME_TYPE];\n",
       "      // store reference to embed id on output_area\n",
       "      output_area._bokeh_element_id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n",
       "    }\n",
       "    if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n",
       "      const bk_div = document.createElement(\"div\");\n",
       "      bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n",
       "      const script_attrs = bk_div.children[0].attributes;\n",
       "      for (let i = 0; i < script_attrs.length; i++) {\n",
       "        toinsert[toinsert.length - 1].firstChild.setAttribute(script_attrs[i].name, script_attrs[i].value);\n",
       "        toinsert[toinsert.length - 1].firstChild.textContent = bk_div.children[0].textContent\n",
       "      }\n",
       "      // store reference to server id on output_area\n",
       "      output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n",
       "    }\n",
       "  }\n",
       "\n",
       "  function register_renderer(events, OutputArea) {\n",
       "\n",
       "    function append_mime(data, metadata, element) {\n",
       "      // create a DOM node to render to\n",
       "      const toinsert = this.create_output_subarea(\n",
       "        metadata,\n",
       "        CLASS_NAME,\n",
       "        EXEC_MIME_TYPE\n",
       "      );\n",
       "      this.keyboard_manager.register_events(toinsert);\n",
       "      // Render to node\n",
       "      const props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n",
       "      render(props, toinsert[toinsert.length - 1]);\n",
       "      element.append(toinsert);\n",
       "      return toinsert\n",
       "    }\n",
       "\n",
       "    /* Handle when an output is cleared or removed */\n",
       "    events.on('clear_output.CodeCell', handleClearOutput);\n",
       "    events.on('delete.Cell', handleClearOutput);\n",
       "\n",
       "    /* Handle when a new output is added */\n",
       "    events.on('output_added.OutputArea', handleAddOutput);\n",
       "\n",
       "    /**\n",
       "     * Register the mime type and append_mime function with output_area\n",
       "     */\n",
       "    OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n",
       "      /* Is output safe? */\n",
       "      safe: true,\n",
       "      /* Index of renderer in `output_area.display_order` */\n",
       "      index: 0\n",
       "    });\n",
       "  }\n",
       "\n",
       "  // register the mime type if in Jupyter Notebook environment and previously unregistered\n",
       "  if (root.Jupyter !== undefined) {\n",
       "    const events = require('base/js/events');\n",
       "    const OutputArea = require('notebook/js/outputarea').OutputArea;\n",
       "\n",
       "    if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n",
       "      register_renderer(events, OutputArea);\n",
       "    }\n",
       "  }\n",
       "  if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n",
       "    root._bokeh_timeout = Date.now() + 5000;\n",
       "    root._bokeh_failed_load = false;\n",
       "  }\n",
       "\n",
       "  const NB_LOAD_WARNING = {'data': {'text/html':\n",
       "     \"<div style='background-color: #fdd'>\\n\"+\n",
       "     \"<p>\\n\"+\n",
       "     \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n",
       "     \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n",
       "     \"</p>\\n\"+\n",
       "     \"<ul>\\n\"+\n",
       "     \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n",
       "     \"<li>use INLINE resources instead, as so:</li>\\n\"+\n",
       "     \"</ul>\\n\"+\n",
       "     \"<code>\\n\"+\n",
       "     \"from bokeh.resources import INLINE\\n\"+\n",
       "     \"output_notebook(resources=INLINE)\\n\"+\n",
       "     \"</code>\\n\"+\n",
       "     \"</div>\"}};\n",
       "\n",
       "  function display_loaded(error = null) {\n",
       "    const el = document.getElementById(\"f8960120-f043-4a81-91cf-46b7d25b428f\");\n",
       "    if (el != null) {\n",
       "      const html = (() => {\n",
       "        if (typeof root.Bokeh === \"undefined\") {\n",
       "          if (error == null) {\n",
       "            return \"BokehJS is loading ...\";\n",
       "          } else {\n",
       "            return \"BokehJS failed to load.\";\n",
       "          }\n",
       "        } else {\n",
       "          const prefix = `BokehJS ${root.Bokeh.version}`;\n",
       "          if (error == null) {\n",
       "            return `${prefix} successfully loaded.`;\n",
       "          } else {\n",
       "            return `${prefix} <b>encountered errors</b> while loading and may not function as expected.`;\n",
       "          }\n",
       "        }\n",
       "      })();\n",
       "      el.innerHTML = html;\n",
       "\n",
       "      if (error != null) {\n",
       "        const wrapper = document.createElement(\"div\");\n",
       "        wrapper.style.overflow = \"auto\";\n",
       "        wrapper.style.height = \"5em\";\n",
       "        wrapper.style.resize = \"vertical\";\n",
       "        const content = document.createElement(\"div\");\n",
       "        content.style.fontFamily = \"monospace\";\n",
       "        content.style.whiteSpace = \"pre-wrap\";\n",
       "        content.style.backgroundColor = \"rgb(255, 221, 221)\";\n",
       "        content.textContent = error.stack ?? error.toString();\n",
       "        wrapper.append(content);\n",
       "        el.append(wrapper);\n",
       "      }\n",
       "    } else if (Date.now() < root._bokeh_timeout) {\n",
       "      setTimeout(() => display_loaded(error), 100);\n",
       "    }\n",
       "  }\n",
       "\n",
       "  function run_callbacks() {\n",
       "    try {\n",
       "      root._bokeh_onload_callbacks.forEach(function(callback) {\n",
       "        if (callback != null)\n",
       "          callback();\n",
       "      });\n",
       "    } finally {\n",
       "      delete root._bokeh_onload_callbacks\n",
       "    }\n",
       "    console.debug(\"Bokeh: all callbacks have finished\");\n",
       "  }\n",
       "\n",
       "  function load_libs(css_urls, js_urls, callback) {\n",
       "    if (css_urls == null) css_urls = [];\n",
       "    if (js_urls == null) js_urls = [];\n",
       "\n",
       "    root._bokeh_onload_callbacks.push(callback);\n",
       "    if (root._bokeh_is_loading > 0) {\n",
       "      console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n",
       "      return null;\n",
       "    }\n",
       "    if (js_urls == null || js_urls.length === 0) {\n",
       "      run_callbacks();\n",
       "      return null;\n",
       "    }\n",
       "    console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n",
       "    root._bokeh_is_loading = css_urls.length + js_urls.length;\n",
       "\n",
       "    function on_load() {\n",
       "      root._bokeh_is_loading--;\n",
       "      if (root._bokeh_is_loading === 0) {\n",
       "        console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n",
       "        run_callbacks()\n",
       "      }\n",
       "    }\n",
       "\n",
       "    function on_error(url) {\n",
       "      console.error(\"failed to load \" + url);\n",
       "    }\n",
       "\n",
       "    for (let i = 0; i < css_urls.length; i++) {\n",
       "      const url = css_urls[i];\n",
       "      const element = document.createElement(\"link\");\n",
       "      element.onload = on_load;\n",
       "      element.onerror = on_error.bind(null, url);\n",
       "      element.rel = \"stylesheet\";\n",
       "      element.type = \"text/css\";\n",
       "      element.href = url;\n",
       "      console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n",
       "      document.body.appendChild(element);\n",
       "    }\n",
       "\n",
       "    for (let i = 0; i < js_urls.length; i++) {\n",
       "      const url = js_urls[i];\n",
       "      const element = document.createElement('script');\n",
       "      element.onload = on_load;\n",
       "      element.onerror = on_error.bind(null, url);\n",
       "      element.async = false;\n",
       "      element.src = url;\n",
       "      console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n",
       "      document.head.appendChild(element);\n",
       "    }\n",
       "  };\n",
       "\n",
       "  function inject_raw_css(css) {\n",
       "    const element = document.createElement(\"style\");\n",
       "    element.appendChild(document.createTextNode(css));\n",
       "    document.body.appendChild(element);\n",
       "  }\n",
       "\n",
       "  const js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-3.6.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.6.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.6.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.6.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-3.6.0.min.js\"];\n",
       "  const css_urls = [];\n",
       "\n",
       "  const inline_js = [    function(Bokeh) {\n",
       "      Bokeh.set_log_level(\"info\");\n",
       "    },\n",
       "function(Bokeh) {\n",
       "    }\n",
       "  ];\n",
       "\n",
       "  function run_inline_js() {\n",
       "    if (root.Bokeh !== undefined || force === true) {\n",
       "      try {\n",
       "            for (let i = 0; i < inline_js.length; i++) {\n",
       "      inline_js[i].call(root, root.Bokeh);\n",
       "    }\n",
       "\n",
       "      } catch (error) {display_loaded(error);throw error;\n",
       "      }if (force === true) {\n",
       "        display_loaded();\n",
       "      }} else if (Date.now() < root._bokeh_timeout) {\n",
       "      setTimeout(run_inline_js, 100);\n",
       "    } else if (!root._bokeh_failed_load) {\n",
       "      console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n",
       "      root._bokeh_failed_load = true;\n",
       "    } else if (force !== true) {\n",
       "      const cell = $(document.getElementById(\"f8960120-f043-4a81-91cf-46b7d25b428f\")).parents('.cell').data().cell;\n",
       "      cell.output_area.append_execute_result(NB_LOAD_WARNING)\n",
       "    }\n",
       "  }\n",
       "\n",
       "  if (root._bokeh_is_loading === 0) {\n",
       "    console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n",
       "    run_inline_js();\n",
       "  } else {\n",
       "    load_libs(css_urls, js_urls, function() {\n",
       "      console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n",
       "      run_inline_js();\n",
       "    });\n",
       "  }\n",
       "}(window));"
      ],
      "application/vnd.bokehjs_load.v0+json": "'use strict';\n(function(root) {\n  function now() {\n    return new Date();\n  }\n\n  const force = true;\n\n  if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n    root._bokeh_onload_callbacks = [];\n    root._bokeh_is_loading = undefined;\n  }\n\n\n  if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n    root._bokeh_timeout = Date.now() + 5000;\n    root._bokeh_failed_load = false;\n  }\n\n  const NB_LOAD_WARNING = {'data': {'text/html':\n     \"<div style='background-color: #fdd'>\\n\"+\n     \"<p>\\n\"+\n     \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n     \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n     \"</p>\\n\"+\n     \"<ul>\\n\"+\n     \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n     \"<li>use INLINE resources instead, as so:</li>\\n\"+\n     \"</ul>\\n\"+\n     \"<code>\\n\"+\n     \"from bokeh.resources import INLINE\\n\"+\n     \"output_notebook(resources=INLINE)\\n\"+\n     \"</code>\\n\"+\n     \"</div>\"}};\n\n  function display_loaded(error = null) {\n    const el = document.getElementById(\"f8960120-f043-4a81-91cf-46b7d25b428f\");\n    if (el != null) {\n      const html = (() => {\n        if (typeof root.Bokeh === \"undefined\") {\n          if (error == null) {\n            return \"BokehJS is loading ...\";\n          } else {\n            return \"BokehJS failed to load.\";\n          }\n        } else {\n          const prefix = `BokehJS ${root.Bokeh.version}`;\n          if (error == null) {\n            return `${prefix} successfully loaded.`;\n          } else {\n            return `${prefix} <b>encountered errors</b> while loading and may not function as expected.`;\n          }\n        }\n      })();\n      el.innerHTML = html;\n\n      if (error != null) {\n        const wrapper = document.createElement(\"div\");\n        wrapper.style.overflow = \"auto\";\n        wrapper.style.height = \"5em\";\n        wrapper.style.resize = \"vertical\";\n        const content = document.createElement(\"div\");\n        content.style.fontFamily = \"monospace\";\n        content.style.whiteSpace = \"pre-wrap\";\n        content.style.backgroundColor = \"rgb(255, 221, 221)\";\n        content.textContent = error.stack ?? error.toString();\n        wrapper.append(content);\n        el.append(wrapper);\n      }\n    } else if (Date.now() < root._bokeh_timeout) {\n      setTimeout(() => display_loaded(error), 100);\n    }\n  }\n\n  function run_callbacks() {\n    try {\n      root._bokeh_onload_callbacks.forEach(function(callback) {\n        if (callback != null)\n          callback();\n      });\n    } finally {\n      delete root._bokeh_onload_callbacks\n    }\n    console.debug(\"Bokeh: all callbacks have finished\");\n  }\n\n  function load_libs(css_urls, js_urls, callback) {\n    if (css_urls == null) css_urls = [];\n    if (js_urls == null) js_urls = [];\n\n    root._bokeh_onload_callbacks.push(callback);\n    if (root._bokeh_is_loading > 0) {\n      console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n      return null;\n    }\n    if (js_urls == null || js_urls.length === 0) {\n      run_callbacks();\n      return null;\n    }\n    console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n    root._bokeh_is_loading = css_urls.length + js_urls.length;\n\n    function on_load() {\n      root._bokeh_is_loading--;\n      if (root._bokeh_is_loading === 0) {\n        console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n        run_callbacks()\n      }\n    }\n\n    function on_error(url) {\n      console.error(\"failed to load \" + url);\n    }\n\n    for (let i = 0; i < css_urls.length; i++) {\n      const url = css_urls[i];\n      const element = document.createElement(\"link\");\n      element.onload = on_load;\n      element.onerror = on_error.bind(null, url);\n      element.rel = \"stylesheet\";\n      element.type = \"text/css\";\n      element.href = url;\n      console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n      document.body.appendChild(element);\n    }\n\n    for (let i = 0; i < js_urls.length; i++) {\n      const url = js_urls[i];\n      const element = document.createElement('script');\n      element.onload = on_load;\n      element.onerror = on_error.bind(null, url);\n      element.async = false;\n      element.src = url;\n      console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n      document.head.appendChild(element);\n    }\n  };\n\n  function inject_raw_css(css) {\n    const element = document.createElement(\"style\");\n    element.appendChild(document.createTextNode(css));\n    document.body.appendChild(element);\n  }\n\n  const js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-3.6.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.6.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.6.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.6.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-3.6.0.min.js\"];\n  const css_urls = [];\n\n  const inline_js = [    function(Bokeh) {\n      Bokeh.set_log_level(\"info\");\n    },\nfunction(Bokeh) {\n    }\n  ];\n\n  function run_inline_js() {\n    if (root.Bokeh !== undefined || force === true) {\n      try {\n            for (let i = 0; i < inline_js.length; i++) {\n      inline_js[i].call(root, root.Bokeh);\n    }\n\n      } catch (error) {display_loaded(error);throw error;\n      }if (force === true) {\n        display_loaded();\n      }} else if (Date.now() < root._bokeh_timeout) {\n      setTimeout(run_inline_js, 100);\n    } else if (!root._bokeh_failed_load) {\n      console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n      root._bokeh_failed_load = true;\n    } else if (force !== true) {\n      const cell = $(document.getElementById(\"f8960120-f043-4a81-91cf-46b7d25b428f\")).parents('.cell').data().cell;\n      cell.output_area.append_execute_result(NB_LOAD_WARNING)\n    }\n  }\n\n  if (root._bokeh_is_loading === 0) {\n    console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n    run_inline_js();\n  } else {\n    load_libs(css_urls, js_urls, function() {\n      console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n      run_inline_js();\n    });\n  }\n}(window));"
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "  <div id=\"efde9041-3e75-4597-9eb2-ef97da76e91e\" data-root-id=\"p1052\" style=\"display: contents;\"></div>\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/javascript": [
       "(function(root) {\n",
       "  function embed_document(root) {\n",
       "  const docs_json = {\"4eead55b-a011-462c-a21e-8bbf84654600\":{\"version\":\"3.6.0\",\"title\":\"Bokeh Application\",\"roots\":[{\"type\":\"object\",\"name\":\"Column\",\"id\":\"p1052\",\"attributes\":{\"children\":[{\"type\":\"object\",\"name\":\"Figure\",\"id\":\"p1005\",\"attributes\":{\"width\":500,\"height\":300,\"x_range\":{\"type\":\"object\",\"name\":\"FactorRange\",\"id\":\"p1015\",\"attributes\":{\"factors\":[\"impf\",\"impv\",\"infa\",\"infc\",\"perf\",\"ptca\",\"ptcp\",\"wayq\"]}},\"y_range\":{\"type\":\"object\",\"name\":\"Range1d\",\"id\":\"p1004\",\"attributes\":{\"end\":113.30000000000001,\"bounds\":[0,113.30000000000001]}},\"x_scale\":{\"type\":\"object\",\"name\":\"CategoricalScale\",\"id\":\"p1016\"},\"y_scale\":{\"type\":\"object\",\"name\":\"LinearScale\",\"id\":\"p1017\"},\"title\":{\"type\":\"object\",\"name\":\"Title\",\"id\":\"p1008\",\"attributes\":{\"text\":\"Parasha #12: Vayechi - Verb form distribution\"}},\"renderers\":[{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"p1047\",\"attributes\":{\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"p1001\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"p1002\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"p1003\"},\"data\":{\"type\":\"map\",\"entries\":[[\"form\",[\"impf\",\"impv\",\"infa\",\"infc\",\"perf\",\"ptca\",\"ptcp\",\"wayq\"]],[\"count_all\",[54,14,3,24,63,25,2,103]],[\"count_narr\",[5,0,0,14,13,8,0,103]],[\"count_direct\",[49,14,3,10,50,17,2,0]],[\"count\",[54,14,3,24,63,25,2,103]]]}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"p1048\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"p1049\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"p1044\",\"attributes\":{\"x\":{\"type\":\"field\",\"field\":\"form\"},\"width\":{\"type\":\"value\",\"value\":0.8},\"top\":{\"type\":\"field\",\"field\":\"count\"},\"line_color\":{\"type\":\"value\",\"value\":\"#718dbf\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#718dbf\"},\"hatch_color\":{\"type\":\"value\",\"value\":\"#718dbf\"}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"p1045\",\"attributes\":{\"x\":{\"type\":\"field\",\"field\":\"form\"},\"width\":{\"type\":\"value\",\"value\":0.8},\"top\":{\"type\":\"field\",\"field\":\"count\"},\"line_color\":{\"type\":\"value\",\"value\":\"#718dbf\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"#718dbf\"},\"fill_alpha\":{\"type\":\"value\",\"value\":0.1},\"hatch_color\":{\"type\":\"value\",\"value\":\"#718dbf\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"p1046\",\"attributes\":{\"x\":{\"type\":\"field\",\"field\":\"form\"},\"width\":{\"type\":\"value\",\"value\":0.8},\"top\":{\"type\":\"field\",\"field\":\"count\"},\"line_color\":{\"type\":\"value\",\"value\":\"#718dbf\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"fill_color\":{\"type\":\"value\",\"value\":\"#718dbf\"},\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"hatch_color\":{\"type\":\"value\",\"value\":\"#718dbf\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}}}}],\"toolbar\":{\"type\":\"object\",\"name\":\"Toolbar\",\"id\":\"p1014\",\"attributes\":{\"tools\":[{\"type\":\"object\",\"name\":\"PanTool\",\"id\":\"p1028\"},{\"type\":\"object\",\"name\":\"WheelZoomTool\",\"id\":\"p1029\",\"attributes\":{\"renderers\":\"auto\"}},{\"type\":\"object\",\"name\":\"BoxZoomTool\",\"id\":\"p1030\",\"attributes\":{\"overlay\":{\"type\":\"object\",\"name\":\"BoxAnnotation\",\"id\":\"p1031\",\"attributes\":{\"syncable\":false,\"line_color\":\"black\",\"line_alpha\":1.0,\"line_width\":2,\"line_dash\":[4,4],\"fill_color\":\"lightgrey\",\"fill_alpha\":0.5,\"level\":\"overlay\",\"visible\":false,\"left\":{\"type\":\"number\",\"value\":\"nan\"},\"right\":{\"type\":\"number\",\"value\":\"nan\"},\"top\":{\"type\":\"number\",\"value\":\"nan\"},\"bottom\":{\"type\":\"number\",\"value\":\"nan\"},\"left_units\":\"canvas\",\"right_units\":\"canvas\",\"top_units\":\"canvas\",\"bottom_units\":\"canvas\",\"handles\":{\"type\":\"object\",\"name\":\"BoxInteractionHandles\",\"id\":\"p1037\",\"attributes\":{\"all\":{\"type\":\"object\",\"name\":\"AreaVisuals\",\"id\":\"p1036\",\"attributes\":{\"fill_color\":\"white\",\"hover_fill_color\":\"lightgray\"}}}}}}}},{\"type\":\"object\",\"name\":\"SaveTool\",\"id\":\"p1038\"},{\"type\":\"object\",\"name\":\"ResetTool\",\"id\":\"p1039\"},{\"type\":\"object\",\"name\":\"HelpTool\",\"id\":\"p1040\"}],\"active_drag\":null,\"active_scroll\":null}},\"left\":[{\"type\":\"object\",\"name\":\"LinearAxis\",\"id\":\"p1023\",\"attributes\":{\"ticker\":{\"type\":\"object\",\"name\":\"BasicTicker\",\"id\":\"p1024\",\"attributes\":{\"mantissas\":[1,2,5]}},\"formatter\":{\"type\":\"object\",\"name\":\"BasicTickFormatter\",\"id\":\"p1025\"},\"axis_label\":\"Frequency\",\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"p1026\"}}}],\"below\":[{\"type\":\"object\",\"name\":\"CategoricalAxis\",\"id\":\"p1018\",\"attributes\":{\"ticker\":{\"type\":\"object\",\"name\":\"CategoricalTicker\",\"id\":\"p1019\"},\"formatter\":{\"type\":\"object\",\"name\":\"CategoricalTickFormatter\",\"id\":\"p1020\"},\"axis_label\":\"Verb Form\",\"major_label_orientation\":1.0,\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"p1021\"}}}],\"center\":[{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"p1022\",\"attributes\":{\"axis\":{\"id\":\"p1018\"}}},{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"p1027\",\"attributes\":{\"dimension\":1,\"axis\":{\"id\":\"p1023\"}}}]}},{\"type\":\"object\",\"name\":\"Select\",\"id\":\"p1050\",\"attributes\":{\"js_property_callbacks\":{\"type\":\"map\",\"entries\":[[\"change:value\",[{\"type\":\"object\",\"name\":\"CustomJS\",\"id\":\"p1051\",\"attributes\":{\"args\":{\"type\":\"map\",\"entries\":[[\"source\",{\"id\":\"p1001\"}]]},\"code\":\"\\n    const data = source.data;\\n    const filter = cb_obj.value;\\n    if (filter === 'Narrative only') {\\n        data['count'] = data['count_narr'];\\n    } else if (filter === 'Direct speech only') {\\n        data['count'] = data['count_direct'];\\n    } else {\\n        data['count'] = data['count_all'];\\n    }\\n    source.change.emit();\\n\"}}]]]},\"title\":\"Filter by Text Type:\",\"options\":[\"All\",\"Narrative only\",\"Direct speech only\"],\"value\":\"All\"}}]}}]}};\n",
       "  const render_items = [{\"docid\":\"4eead55b-a011-462c-a21e-8bbf84654600\",\"roots\":{\"p1052\":\"efde9041-3e75-4597-9eb2-ef97da76e91e\"},\"root_ids\":[\"p1052\"]}];\n",
       "  void root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n",
       "  }\n",
       "  if (root.Bokeh !== undefined) {\n",
       "    embed_document(root);\n",
       "  } else {\n",
       "    let attempts = 0;\n",
       "    const timer = setInterval(function(root) {\n",
       "      if (root.Bokeh !== undefined) {\n",
       "        clearInterval(timer);\n",
       "        embed_document(root);\n",
       "      } else {\n",
       "        attempts++;\n",
       "        if (attempts > 100) {\n",
       "          clearInterval(timer);\n",
       "          console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n",
       "        }\n",
       "      }\n",
       "    }, 10, root)\n",
       "  }\n",
       "})(window);"
      ],
      "application/vnd.bokehjs_exec.v0+json": ""
     },
     "metadata": {
      "application/vnd.bokehjs_exec.v0+json": {
       "id": "p1052"
      }
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "from bokeh.layouts import column\n",
    "from bokeh.models import ColumnDataSource, CustomJS, Select, Range1d\n",
    "from bokeh.plotting import figure, output_file, show\n",
    "from collections import Counter\n",
    "from bokeh.io import output_notebook\n",
    "\n",
    "# Prepare the Bokeh output to display in the notebook\n",
    "output_notebook()\n",
    "\n",
    "# Prepare data for interactive bar chart\n",
    "verb_form_counts_all = Counter(F.vt.v(w) for w in verb_words)\n",
    "verb_form_counts_narr = Counter(F.vt.v(w) for w in verb_words if F.domain.v(L.u(w, \"clause\")[0]) != \"Q\")\n",
    "verb_form_counts_direct = Counter(F.vt.v(w) for w in verb_words if F.domain.v(L.u(w, \"clause\")[0]) == \"Q\")\n",
    "\n",
    "# Define the categories (verb forms) to plot (excluding \"NA\")\n",
    "verb_forms = [vf for vf in verb_form_counts_all.keys() if vf != \"NA\"]\n",
    "verb_forms.sort()  # sort alphabetically\n",
    "\n",
    "# Create data source for Bokeh\n",
    "data = {\n",
    "    'form': verb_forms,\n",
    "    'count_all': [verb_form_counts_all.get(vf, 0) for vf in verb_forms],\n",
    "    'count_narr': [verb_form_counts_narr.get(vf, 0) for vf in verb_forms],\n",
    "    'count_direct': [verb_form_counts_direct.get(vf, 0) for vf in verb_forms],\n",
    "    # Use 'count' as the currently selected counts (start with all by default)\n",
    "    'count': [verb_form_counts_all.get(vf, 0) for vf in verb_forms]\n",
    "}\n",
    "source = ColumnDataSource(data=data)\n",
    "\n",
    "# Compute maximum count across all categories and add padding (10%)\n",
    "max_count = max(max(data['count_all']), max(data['count_narr']), max(data['count_direct']))\n",
    "y_end = max_count * 1.1\n",
    "\n",
    "# Create a Bokeh bar chart with a fixed y_range\n",
    "p = figure(x_range=verb_forms, height=300, width=500,\n",
    "           title=f\"Parasha #{parasha_num}: {parasha_name_trans} - Verb form distribution\",\n",
    "           x_axis_label=\"Verb Form\", y_axis_label=\"Frequency\",\n",
    "           toolbar_location='right',\n",
    "           y_range=Range1d(start=0, end=y_end))\n",
    "\n",
    "p.vbar(x='form', top='count', width=0.8, source=source, color=\"#718dbf\")\n",
    "\n",
    "# Lock the y_range so it cannot be changed by interactions\n",
    "p.y_range.bounds = (0, y_end)\n",
    "\n",
    "# Deactivate any active drag or scroll tools (if the toolbar exists)\n",
    "if p.toolbar:\n",
    "    p.toolbar.active_drag = None\n",
    "    p.toolbar.active_scroll = None\n",
    "\n",
    "# Configure x-axis labels for better readability (rotate if needed)\n",
    "p.xaxis.major_label_orientation = 1.0\n",
    "\n",
    "# Add a dropdown to filter by context (All / Narrative / Direct)\n",
    "select = Select(title=\"Filter by Text Type:\", value=\"All\",\n",
    "                options=[\"All\", \"Narrative only\", \"Direct speech only\"])\n",
    "\n",
    "# JavaScript callback to update the bar heights based on selection\n",
    "callback_code = \"\"\"\n",
    "    const data = source.data;\n",
    "    const filter = cb_obj.value;\n",
    "    if (filter === 'Narrative only') {\n",
    "        data['count'] = data['count_narr'];\n",
    "    } else if (filter === 'Direct speech only') {\n",
    "        data['count'] = data['count_direct'];\n",
    "    } else {\n",
    "        data['count'] = data['count_all'];\n",
    "    }\n",
    "    source.change.emit();\n",
    "\"\"\"\n",
    "select.js_on_change('value', CustomJS(args={'source': source}, code=callback_code))\n",
    "\n",
    "# Combine the plot and dropdown in a layout and show\n",
    "layout = column(p, select)\n",
    "show(layout)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6e4cddc7-7833-43ed-9de1-b6b9cae60697",
   "metadata": {},
   "source": [
    "Now also make a static image:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "810df0c9-5898-4187-b168-87df531ecd3d",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "    <style>\n",
       "        .bk-notebook-logo {\n",
       "            display: block;\n",
       "            width: 20px;\n",
       "            height: 20px;\n",
       "            background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAOkSURBVDiNjZRtaJVlGMd/1/08zzln5zjP1LWcU9N0NkN8m2CYjpgQYQXqSs0I84OLIC0hkEKoPtiH3gmKoiJDU7QpLgoLjLIQCpEsNJ1vqUOdO7ppbuec5+V+rj4ctwzd8IIbbi6u+8f1539dt3A78eXC7QizUF7gyV1fD1Yqg4JWz84yffhm0qkFqBogB9rM8tZdtwVsPUhWhGcFJngGeWrPzHm5oaMmkfEg1usvLFyc8jLRqDOMru7AyC8saQr7GG7f5fvDeH7Ej8CM66nIF+8yngt6HWaKh7k49Soy9nXurCi1o3qUbS3zWfrYeQDTB/Qj6kX6Ybhw4B+bOYoLKCC9H3Nu/leUTZ1JdRWkkn2ldcCamzrcf47KKXdAJllSlxAOkRgyHsGC/zRday5Qld9DyoM4/q/rUoy/CXh3jzOu3bHUVZeU+DEn8FInkPBFlu3+nW3Nw0mk6vCDiWg8CeJaxEwuHS3+z5RgY+YBR6V1Z1nxSOfoaPa4LASWxxdNp+VWTk7+4vzaou8v8PN+xo+KY2xsw6une2frhw05CTYOmQvsEhjhWjn0bmXPjpE1+kplmmkP3suftwTubK9Vq22qKmrBhpY4jvd5afdRA3wGjFAgcnTK2s4hY0/GPNIb0nErGMCRxWOOX64Z8RAC4oCXdklmEvcL8o0BfkNK4lUg9HTl+oPlQxdNo3Mg4Nv175e/1LDGzZen30MEjRUtmXSfiTVu1kK8W4txyV6BMKlbgk3lMwYCiusNy9fVfvvwMxv8Ynl6vxoByANLTWplvuj/nF9m2+PDtt1eiHPBr1oIfhCChQMBw6Aw0UulqTKZdfVvfG7VcfIqLG9bcldL/+pdWTLxLUy8Qq38heUIjh4XlzZxzQm19lLFlr8vdQ97rjZVOLf8nclzckbcD4wxXMidpX30sFd37Fv/GtwwhzhxGVAprjbg0gCAEeIgwCZyTV2Z1REEW8O4py0wsjeloKoMr6iCY6dP92H6Vw/oTyICIthibxjm/DfN9lVz8IqtqKYLUXfoKVMVQVVJOElGjrnnUt9T9wbgp8AyYKaGlqingHZU/uG2NTZSVqwHQTWkx9hxjkpWDaCg6Ckj5qebgBVbT3V3NNXMSiWSDdGV3hrtzla7J+duwPOToIg42ChPQOQjspnSlp1V+Gjdged7+8UN5CRAV7a5EdFNwCjEaBR27b3W890TE7g24NAP/mMDXRWrGoFPQI9ls/MWO2dWFAar/xcOIImbbpA3zgAAAABJRU5ErkJggg==);\n",
       "        }\n",
       "    </style>\n",
       "    <div>\n",
       "        <a href=\"https://bokeh.org\" target=\"_blank\" class=\"bk-notebook-logo\"></a>\n",
       "        <span id=\"fe7e2b0f-1078-41c0-b452-06d989308f69\">Loading BokehJS ...</span>\n",
       "    </div>\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/javascript": [
       "'use strict';\n",
       "(function(root) {\n",
       "  function now() {\n",
       "    return new Date();\n",
       "  }\n",
       "\n",
       "  const force = true;\n",
       "\n",
       "  if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n",
       "    root._bokeh_onload_callbacks = [];\n",
       "    root._bokeh_is_loading = undefined;\n",
       "  }\n",
       "\n",
       "const JS_MIME_TYPE = 'application/javascript';\n",
       "  const HTML_MIME_TYPE = 'text/html';\n",
       "  const EXEC_MIME_TYPE = 'application/vnd.bokehjs_exec.v0+json';\n",
       "  const CLASS_NAME = 'output_bokeh rendered_html';\n",
       "\n",
       "  /**\n",
       "   * Render data to the DOM node\n",
       "   */\n",
       "  function render(props, node) {\n",
       "    const script = document.createElement(\"script\");\n",
       "    node.appendChild(script);\n",
       "  }\n",
       "\n",
       "  /**\n",
       "   * Handle when an output is cleared or removed\n",
       "   */\n",
       "  function handleClearOutput(event, handle) {\n",
       "    function drop(id) {\n",
       "      const view = Bokeh.index.get_by_id(id)\n",
       "      if (view != null) {\n",
       "        view.model.document.clear()\n",
       "        Bokeh.index.delete(view)\n",
       "      }\n",
       "    }\n",
       "\n",
       "    const cell = handle.cell;\n",
       "\n",
       "    const id = cell.output_area._bokeh_element_id;\n",
       "    const server_id = cell.output_area._bokeh_server_id;\n",
       "\n",
       "    // Clean up Bokeh references\n",
       "    if (id != null) {\n",
       "      drop(id)\n",
       "    }\n",
       "\n",
       "    if (server_id !== undefined) {\n",
       "      // Clean up Bokeh references\n",
       "      const cmd_clean = \"from bokeh.io.state import curstate; print(curstate().uuid_to_server['\" + server_id + \"'].get_sessions()[0].document.roots[0]._id)\";\n",
       "      cell.notebook.kernel.execute(cmd_clean, {\n",
       "        iopub: {\n",
       "          output: function(msg) {\n",
       "            const id = msg.content.text.trim()\n",
       "            drop(id)\n",
       "          }\n",
       "        }\n",
       "      });\n",
       "      // Destroy server and session\n",
       "      const cmd_destroy = \"import bokeh.io.notebook as ion; ion.destroy_server('\" + server_id + \"')\";\n",
       "      cell.notebook.kernel.execute(cmd_destroy);\n",
       "    }\n",
       "  }\n",
       "\n",
       "  /**\n",
       "   * Handle when a new output is added\n",
       "   */\n",
       "  function handleAddOutput(event, handle) {\n",
       "    const output_area = handle.output_area;\n",
       "    const output = handle.output;\n",
       "\n",
       "    // limit handleAddOutput to display_data with EXEC_MIME_TYPE content only\n",
       "    if ((output.output_type != \"display_data\") || (!Object.prototype.hasOwnProperty.call(output.data, EXEC_MIME_TYPE))) {\n",
       "      return\n",
       "    }\n",
       "\n",
       "    const toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n",
       "\n",
       "    if (output.metadata[EXEC_MIME_TYPE][\"id\"] !== undefined) {\n",
       "      toinsert[toinsert.length - 1].firstChild.textContent = output.data[JS_MIME_TYPE];\n",
       "      // store reference to embed id on output_area\n",
       "      output_area._bokeh_element_id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n",
       "    }\n",
       "    if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n",
       "      const bk_div = document.createElement(\"div\");\n",
       "      bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n",
       "      const script_attrs = bk_div.children[0].attributes;\n",
       "      for (let i = 0; i < script_attrs.length; i++) {\n",
       "        toinsert[toinsert.length - 1].firstChild.setAttribute(script_attrs[i].name, script_attrs[i].value);\n",
       "        toinsert[toinsert.length - 1].firstChild.textContent = bk_div.children[0].textContent\n",
       "      }\n",
       "      // store reference to server id on output_area\n",
       "      output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n",
       "    }\n",
       "  }\n",
       "\n",
       "  function register_renderer(events, OutputArea) {\n",
       "\n",
       "    function append_mime(data, metadata, element) {\n",
       "      // create a DOM node to render to\n",
       "      const toinsert = this.create_output_subarea(\n",
       "        metadata,\n",
       "        CLASS_NAME,\n",
       "        EXEC_MIME_TYPE\n",
       "      );\n",
       "      this.keyboard_manager.register_events(toinsert);\n",
       "      // Render to node\n",
       "      const props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n",
       "      render(props, toinsert[toinsert.length - 1]);\n",
       "      element.append(toinsert);\n",
       "      return toinsert\n",
       "    }\n",
       "\n",
       "    /* Handle when an output is cleared or removed */\n",
       "    events.on('clear_output.CodeCell', handleClearOutput);\n",
       "    events.on('delete.Cell', handleClearOutput);\n",
       "\n",
       "    /* Handle when a new output is added */\n",
       "    events.on('output_added.OutputArea', handleAddOutput);\n",
       "\n",
       "    /**\n",
       "     * Register the mime type and append_mime function with output_area\n",
       "     */\n",
       "    OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n",
       "      /* Is output safe? */\n",
       "      safe: true,\n",
       "      /* Index of renderer in `output_area.display_order` */\n",
       "      index: 0\n",
       "    });\n",
       "  }\n",
       "\n",
       "  // register the mime type if in Jupyter Notebook environment and previously unregistered\n",
       "  if (root.Jupyter !== undefined) {\n",
       "    const events = require('base/js/events');\n",
       "    const OutputArea = require('notebook/js/outputarea').OutputArea;\n",
       "\n",
       "    if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n",
       "      register_renderer(events, OutputArea);\n",
       "    }\n",
       "  }\n",
       "  if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n",
       "    root._bokeh_timeout = Date.now() + 5000;\n",
       "    root._bokeh_failed_load = false;\n",
       "  }\n",
       "\n",
       "  const NB_LOAD_WARNING = {'data': {'text/html':\n",
       "     \"<div style='background-color: #fdd'>\\n\"+\n",
       "     \"<p>\\n\"+\n",
       "     \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n",
       "     \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n",
       "     \"</p>\\n\"+\n",
       "     \"<ul>\\n\"+\n",
       "     \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n",
       "     \"<li>use INLINE resources instead, as so:</li>\\n\"+\n",
       "     \"</ul>\\n\"+\n",
       "     \"<code>\\n\"+\n",
       "     \"from bokeh.resources import INLINE\\n\"+\n",
       "     \"output_notebook(resources=INLINE)\\n\"+\n",
       "     \"</code>\\n\"+\n",
       "     \"</div>\"}};\n",
       "\n",
       "  function display_loaded(error = null) {\n",
       "    const el = document.getElementById(\"fe7e2b0f-1078-41c0-b452-06d989308f69\");\n",
       "    if (el != null) {\n",
       "      const html = (() => {\n",
       "        if (typeof root.Bokeh === \"undefined\") {\n",
       "          if (error == null) {\n",
       "            return \"BokehJS is loading ...\";\n",
       "          } else {\n",
       "            return \"BokehJS failed to load.\";\n",
       "          }\n",
       "        } else {\n",
       "          const prefix = `BokehJS ${root.Bokeh.version}`;\n",
       "          if (error == null) {\n",
       "            return `${prefix} successfully loaded.`;\n",
       "          } else {\n",
       "            return `${prefix} <b>encountered errors</b> while loading and may not function as expected.`;\n",
       "          }\n",
       "        }\n",
       "      })();\n",
       "      el.innerHTML = html;\n",
       "\n",
       "      if (error != null) {\n",
       "        const wrapper = document.createElement(\"div\");\n",
       "        wrapper.style.overflow = \"auto\";\n",
       "        wrapper.style.height = \"5em\";\n",
       "        wrapper.style.resize = \"vertical\";\n",
       "        const content = document.createElement(\"div\");\n",
       "        content.style.fontFamily = \"monospace\";\n",
       "        content.style.whiteSpace = \"pre-wrap\";\n",
       "        content.style.backgroundColor = \"rgb(255, 221, 221)\";\n",
       "        content.textContent = error.stack ?? error.toString();\n",
       "        wrapper.append(content);\n",
       "        el.append(wrapper);\n",
       "      }\n",
       "    } else if (Date.now() < root._bokeh_timeout) {\n",
       "      setTimeout(() => display_loaded(error), 100);\n",
       "    }\n",
       "  }\n",
       "\n",
       "  function run_callbacks() {\n",
       "    try {\n",
       "      root._bokeh_onload_callbacks.forEach(function(callback) {\n",
       "        if (callback != null)\n",
       "          callback();\n",
       "      });\n",
       "    } finally {\n",
       "      delete root._bokeh_onload_callbacks\n",
       "    }\n",
       "    console.debug(\"Bokeh: all callbacks have finished\");\n",
       "  }\n",
       "\n",
       "  function load_libs(css_urls, js_urls, callback) {\n",
       "    if (css_urls == null) css_urls = [];\n",
       "    if (js_urls == null) js_urls = [];\n",
       "\n",
       "    root._bokeh_onload_callbacks.push(callback);\n",
       "    if (root._bokeh_is_loading > 0) {\n",
       "      console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n",
       "      return null;\n",
       "    }\n",
       "    if (js_urls == null || js_urls.length === 0) {\n",
       "      run_callbacks();\n",
       "      return null;\n",
       "    }\n",
       "    console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n",
       "    root._bokeh_is_loading = css_urls.length + js_urls.length;\n",
       "\n",
       "    function on_load() {\n",
       "      root._bokeh_is_loading--;\n",
       "      if (root._bokeh_is_loading === 0) {\n",
       "        console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n",
       "        run_callbacks()\n",
       "      }\n",
       "    }\n",
       "\n",
       "    function on_error(url) {\n",
       "      console.error(\"failed to load \" + url);\n",
       "    }\n",
       "\n",
       "    for (let i = 0; i < css_urls.length; i++) {\n",
       "      const url = css_urls[i];\n",
       "      const element = document.createElement(\"link\");\n",
       "      element.onload = on_load;\n",
       "      element.onerror = on_error.bind(null, url);\n",
       "      element.rel = \"stylesheet\";\n",
       "      element.type = \"text/css\";\n",
       "      element.href = url;\n",
       "      console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n",
       "      document.body.appendChild(element);\n",
       "    }\n",
       "\n",
       "    for (let i = 0; i < js_urls.length; i++) {\n",
       "      const url = js_urls[i];\n",
       "      const element = document.createElement('script');\n",
       "      element.onload = on_load;\n",
       "      element.onerror = on_error.bind(null, url);\n",
       "      element.async = false;\n",
       "      element.src = url;\n",
       "      console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n",
       "      document.head.appendChild(element);\n",
       "    }\n",
       "  };\n",
       "\n",
       "  function inject_raw_css(css) {\n",
       "    const element = document.createElement(\"style\");\n",
       "    element.appendChild(document.createTextNode(css));\n",
       "    document.body.appendChild(element);\n",
       "  }\n",
       "\n",
       "  const js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-3.6.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.6.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.6.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.6.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-3.6.0.min.js\"];\n",
       "  const css_urls = [];\n",
       "\n",
       "  const inline_js = [    function(Bokeh) {\n",
       "      Bokeh.set_log_level(\"info\");\n",
       "    },\n",
       "function(Bokeh) {\n",
       "    }\n",
       "  ];\n",
       "\n",
       "  function run_inline_js() {\n",
       "    if (root.Bokeh !== undefined || force === true) {\n",
       "      try {\n",
       "            for (let i = 0; i < inline_js.length; i++) {\n",
       "      inline_js[i].call(root, root.Bokeh);\n",
       "    }\n",
       "\n",
       "      } catch (error) {display_loaded(error);throw error;\n",
       "      }if (force === true) {\n",
       "        display_loaded();\n",
       "      }} else if (Date.now() < root._bokeh_timeout) {\n",
       "      setTimeout(run_inline_js, 100);\n",
       "    } else if (!root._bokeh_failed_load) {\n",
       "      console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n",
       "      root._bokeh_failed_load = true;\n",
       "    } else if (force !== true) {\n",
       "      const cell = $(document.getElementById(\"fe7e2b0f-1078-41c0-b452-06d989308f69\")).parents('.cell').data().cell;\n",
       "      cell.output_area.append_execute_result(NB_LOAD_WARNING)\n",
       "    }\n",
       "  }\n",
       "\n",
       "  if (root._bokeh_is_loading === 0) {\n",
       "    console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n",
       "    run_inline_js();\n",
       "  } else {\n",
       "    load_libs(css_urls, js_urls, function() {\n",
       "      console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n",
       "      run_inline_js();\n",
       "    });\n",
       "  }\n",
       "}(window));"
      ],
      "application/vnd.bokehjs_load.v0+json": "'use strict';\n(function(root) {\n  function now() {\n    return new Date();\n  }\n\n  const force = true;\n\n  if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n    root._bokeh_onload_callbacks = [];\n    root._bokeh_is_loading = undefined;\n  }\n\n\n  if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n    root._bokeh_timeout = Date.now() + 5000;\n    root._bokeh_failed_load = false;\n  }\n\n  const NB_LOAD_WARNING = {'data': {'text/html':\n     \"<div style='background-color: #fdd'>\\n\"+\n     \"<p>\\n\"+\n     \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n     \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n     \"</p>\\n\"+\n     \"<ul>\\n\"+\n     \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n     \"<li>use INLINE resources instead, as so:</li>\\n\"+\n     \"</ul>\\n\"+\n     \"<code>\\n\"+\n     \"from bokeh.resources import INLINE\\n\"+\n     \"output_notebook(resources=INLINE)\\n\"+\n     \"</code>\\n\"+\n     \"</div>\"}};\n\n  function display_loaded(error = null) {\n    const el = document.getElementById(\"fe7e2b0f-1078-41c0-b452-06d989308f69\");\n    if (el != null) {\n      const html = (() => {\n        if (typeof root.Bokeh === \"undefined\") {\n          if (error == null) {\n            return \"BokehJS is loading ...\";\n          } else {\n            return \"BokehJS failed to load.\";\n          }\n        } else {\n          const prefix = `BokehJS ${root.Bokeh.version}`;\n          if (error == null) {\n            return `${prefix} successfully loaded.`;\n          } else {\n            return `${prefix} <b>encountered errors</b> while loading and may not function as expected.`;\n          }\n        }\n      })();\n      el.innerHTML = html;\n\n      if (error != null) {\n        const wrapper = document.createElement(\"div\");\n        wrapper.style.overflow = \"auto\";\n        wrapper.style.height = \"5em\";\n        wrapper.style.resize = \"vertical\";\n        const content = document.createElement(\"div\");\n        content.style.fontFamily = \"monospace\";\n        content.style.whiteSpace = \"pre-wrap\";\n        content.style.backgroundColor = \"rgb(255, 221, 221)\";\n        content.textContent = error.stack ?? error.toString();\n        wrapper.append(content);\n        el.append(wrapper);\n      }\n    } else if (Date.now() < root._bokeh_timeout) {\n      setTimeout(() => display_loaded(error), 100);\n    }\n  }\n\n  function run_callbacks() {\n    try {\n      root._bokeh_onload_callbacks.forEach(function(callback) {\n        if (callback != null)\n          callback();\n      });\n    } finally {\n      delete root._bokeh_onload_callbacks\n    }\n    console.debug(\"Bokeh: all callbacks have finished\");\n  }\n\n  function load_libs(css_urls, js_urls, callback) {\n    if (css_urls == null) css_urls = [];\n    if (js_urls == null) js_urls = [];\n\n    root._bokeh_onload_callbacks.push(callback);\n    if (root._bokeh_is_loading > 0) {\n      console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n      return null;\n    }\n    if (js_urls == null || js_urls.length === 0) {\n      run_callbacks();\n      return null;\n    }\n    console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n    root._bokeh_is_loading = css_urls.length + js_urls.length;\n\n    function on_load() {\n      root._bokeh_is_loading--;\n      if (root._bokeh_is_loading === 0) {\n        console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n        run_callbacks()\n      }\n    }\n\n    function on_error(url) {\n      console.error(\"failed to load \" + url);\n    }\n\n    for (let i = 0; i < css_urls.length; i++) {\n      const url = css_urls[i];\n      const element = document.createElement(\"link\");\n      element.onload = on_load;\n      element.onerror = on_error.bind(null, url);\n      element.rel = \"stylesheet\";\n      element.type = \"text/css\";\n      element.href = url;\n      console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n      document.body.appendChild(element);\n    }\n\n    for (let i = 0; i < js_urls.length; i++) {\n      const url = js_urls[i];\n      const element = document.createElement('script');\n      element.onload = on_load;\n      element.onerror = on_error.bind(null, url);\n      element.async = false;\n      element.src = url;\n      console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n      document.head.appendChild(element);\n    }\n  };\n\n  function inject_raw_css(css) {\n    const element = document.createElement(\"style\");\n    element.appendChild(document.createTextNode(css));\n    document.body.appendChild(element);\n  }\n\n  const js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-3.6.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.6.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.6.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.6.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-3.6.0.min.js\"];\n  const css_urls = [];\n\n  const inline_js = [    function(Bokeh) {\n      Bokeh.set_log_level(\"info\");\n    },\nfunction(Bokeh) {\n    }\n  ];\n\n  function run_inline_js() {\n    if (root.Bokeh !== undefined || force === true) {\n      try {\n            for (let i = 0; i < inline_js.length; i++) {\n      inline_js[i].call(root, root.Bokeh);\n    }\n\n      } catch (error) {display_loaded(error);throw error;\n      }if (force === true) {\n        display_loaded();\n      }} else if (Date.now() < root._bokeh_timeout) {\n      setTimeout(run_inline_js, 100);\n    } else if (!root._bokeh_failed_load) {\n      console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n      root._bokeh_failed_load = true;\n    } else if (force !== true) {\n      const cell = $(document.getElementById(\"fe7e2b0f-1078-41c0-b452-06d989308f69\")).parents('.cell').data().cell;\n      cell.output_area.append_execute_result(NB_LOAD_WARNING)\n    }\n  }\n\n  if (root._bokeh_is_loading === 0) {\n    console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n    run_inline_js();\n  } else {\n    load_libs(css_urls, js_urls, function() {\n      console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n      run_inline_js();\n    });\n  }\n}(window));"
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "  <div id=\"c2de6911-27ff-4572-bdc8-baa562fc7c9c\" data-root-id=\"p1057\" style=\"display: contents;\"></div>\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/javascript": [
       "(function(root) {\n",
       "  function embed_document(root) {\n",
       "  const docs_json = {\"aacde5bf-9ac1-4522-8293-f33d16e9658e\":{\"version\":\"3.6.0\",\"title\":\"Bokeh Application\",\"roots\":[{\"type\":\"object\",\"name\":\"Figure\",\"id\":\"p1057\",\"attributes\":{\"width\":500,\"height\":300,\"x_range\":{\"type\":\"object\",\"name\":\"FactorRange\",\"id\":\"p1067\",\"attributes\":{\"factors\":[\"impf\",\"impv\",\"infa\",\"infc\",\"perf\",\"ptca\",\"ptcp\",\"wayq\"]}},\"y_range\":{\"type\":\"object\",\"name\":\"Range1d\",\"id\":\"p1056\",\"attributes\":{\"end\":113.30000000000001,\"bounds\":[0,113.30000000000001]}},\"x_scale\":{\"type\":\"object\",\"name\":\"CategoricalScale\",\"id\":\"p1068\"},\"y_scale\":{\"type\":\"object\",\"name\":\"LinearScale\",\"id\":\"p1069\"},\"title\":{\"type\":\"object\",\"name\":\"Title\",\"id\":\"p1060\",\"attributes\":{\"text\":\"Parasha #12: Vayechi - Verb form distribution\"}},\"renderers\":[{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"p1100\",\"attributes\":{\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"p1053\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"p1054\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"p1055\"},\"data\":{\"type\":\"map\",\"entries\":[[\"form\",[\"impf\",\"impv\",\"infa\",\"infc\",\"perf\",\"ptca\",\"ptcp\",\"wayq\"]],[\"count_narr\",[5,0,0,14,13,8,0,103]],[\"count_direct\",[49,14,3,10,50,17,2,0]]]}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"p1101\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"p1102\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"p1097\",\"attributes\":{\"x\":{\"type\":\"field\",\"field\":\"form\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"p1093\",\"attributes\":{\"value\":-0.15,\"range\":{\"id\":\"p1067\"}}}},\"width\":{\"type\":\"value\",\"value\":0.3},\"top\":{\"type\":\"field\",\"field\":\"count_direct\"},\"line_color\":{\"type\":\"value\",\"value\":\"#718dbf\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#718dbf\"},\"hatch_color\":{\"type\":\"value\",\"value\":\"#718dbf\"}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"p1098\",\"attributes\":{\"x\":{\"type\":\"field\",\"field\":\"form\",\"transform\":{\"id\":\"p1093\"}},\"width\":{\"type\":\"value\",\"value\":0.3},\"top\":{\"type\":\"field\",\"field\":\"count_direct\"},\"line_color\":{\"type\":\"value\",\"value\":\"#718dbf\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"#718dbf\"},\"fill_alpha\":{\"type\":\"value\",\"value\":0.1},\"hatch_color\":{\"type\":\"value\",\"value\":\"#718dbf\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"p1099\",\"attributes\":{\"x\":{\"type\":\"field\",\"field\":\"form\",\"transform\":{\"id\":\"p1093\"}},\"width\":{\"type\":\"value\",\"value\":0.3},\"top\":{\"type\":\"field\",\"field\":\"count_direct\"},\"line_color\":{\"type\":\"value\",\"value\":\"#718dbf\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"fill_color\":{\"type\":\"value\",\"value\":\"#718dbf\"},\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"hatch_color\":{\"type\":\"value\",\"value\":\"#718dbf\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}}}},{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"p1112\",\"attributes\":{\"data_source\":{\"id\":\"p1053\"},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"p1113\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"p1114\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"p1109\",\"attributes\":{\"x\":{\"type\":\"field\",\"field\":\"form\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"p1105\",\"attributes\":{\"value\":0.15,\"range\":{\"id\":\"p1067\"}}}},\"width\":{\"type\":\"value\",\"value\":0.3},\"top\":{\"type\":\"field\",\"field\":\"count_narr\"},\"line_color\":{\"type\":\"value\",\"value\":\"#c9d9d3\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#c9d9d3\"},\"hatch_color\":{\"type\":\"value\",\"value\":\"#c9d9d3\"}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"p1110\",\"attributes\":{\"x\":{\"type\":\"field\",\"field\":\"form\",\"transform\":{\"id\":\"p1105\"}},\"width\":{\"type\":\"value\",\"value\":0.3},\"top\":{\"type\":\"field\",\"field\":\"count_narr\"},\"line_color\":{\"type\":\"value\",\"value\":\"#c9d9d3\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"#c9d9d3\"},\"fill_alpha\":{\"type\":\"value\",\"value\":0.1},\"hatch_color\":{\"type\":\"value\",\"value\":\"#c9d9d3\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"p1111\",\"attributes\":{\"x\":{\"type\":\"field\",\"field\":\"form\",\"transform\":{\"id\":\"p1105\"}},\"width\":{\"type\":\"value\",\"value\":0.3},\"top\":{\"type\":\"field\",\"field\":\"count_narr\"},\"line_color\":{\"type\":\"value\",\"value\":\"#c9d9d3\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"fill_color\":{\"type\":\"value\",\"value\":\"#c9d9d3\"},\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"hatch_color\":{\"type\":\"value\",\"value\":\"#c9d9d3\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}}}}],\"toolbar\":{\"type\":\"object\",\"name\":\"Toolbar\",\"id\":\"p1066\",\"attributes\":{\"tools\":[{\"type\":\"object\",\"name\":\"PanTool\",\"id\":\"p1080\"},{\"type\":\"object\",\"name\":\"WheelZoomTool\",\"id\":\"p1081\",\"attributes\":{\"renderers\":\"auto\"}},{\"type\":\"object\",\"name\":\"BoxZoomTool\",\"id\":\"p1082\",\"attributes\":{\"overlay\":{\"type\":\"object\",\"name\":\"BoxAnnotation\",\"id\":\"p1083\",\"attributes\":{\"syncable\":false,\"line_color\":\"black\",\"line_alpha\":1.0,\"line_width\":2,\"line_dash\":[4,4],\"fill_color\":\"lightgrey\",\"fill_alpha\":0.5,\"level\":\"overlay\",\"visible\":false,\"left\":{\"type\":\"number\",\"value\":\"nan\"},\"right\":{\"type\":\"number\",\"value\":\"nan\"},\"top\":{\"type\":\"number\",\"value\":\"nan\"},\"bottom\":{\"type\":\"number\",\"value\":\"nan\"},\"left_units\":\"canvas\",\"right_units\":\"canvas\",\"top_units\":\"canvas\",\"bottom_units\":\"canvas\",\"handles\":{\"type\":\"object\",\"name\":\"BoxInteractionHandles\",\"id\":\"p1089\",\"attributes\":{\"all\":{\"type\":\"object\",\"name\":\"AreaVisuals\",\"id\":\"p1088\",\"attributes\":{\"fill_color\":\"white\",\"hover_fill_color\":\"lightgray\"}}}}}}}},{\"type\":\"object\",\"name\":\"SaveTool\",\"id\":\"p1090\"},{\"type\":\"object\",\"name\":\"ResetTool\",\"id\":\"p1091\"},{\"type\":\"object\",\"name\":\"HelpTool\",\"id\":\"p1092\"}],\"active_drag\":null,\"active_scroll\":null}},\"left\":[{\"type\":\"object\",\"name\":\"LinearAxis\",\"id\":\"p1075\",\"attributes\":{\"ticker\":{\"type\":\"object\",\"name\":\"BasicTicker\",\"id\":\"p1076\",\"attributes\":{\"mantissas\":[1,2,5]}},\"formatter\":{\"type\":\"object\",\"name\":\"BasicTickFormatter\",\"id\":\"p1077\"},\"axis_label\":\"Frequency\",\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"p1078\"}}}],\"below\":[{\"type\":\"object\",\"name\":\"CategoricalAxis\",\"id\":\"p1070\",\"attributes\":{\"ticker\":{\"type\":\"object\",\"name\":\"CategoricalTicker\",\"id\":\"p1071\"},\"formatter\":{\"type\":\"object\",\"name\":\"CategoricalTickFormatter\",\"id\":\"p1072\"},\"axis_label\":\"Verb Form\",\"major_label_orientation\":1.0,\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"p1073\"}}}],\"center\":[{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"p1074\",\"attributes\":{\"axis\":{\"id\":\"p1070\"}}},{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"p1079\",\"attributes\":{\"dimension\":1,\"axis\":{\"id\":\"p1075\"}}},{\"type\":\"object\",\"name\":\"Legend\",\"id\":\"p1103\",\"attributes\":{\"location\":\"top_left\",\"items\":[{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"p1104\",\"attributes\":{\"label\":{\"type\":\"value\",\"value\":\"Direct speech\"},\"renderers\":[{\"id\":\"p1100\"}]}},{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"p1115\",\"attributes\":{\"label\":{\"type\":\"value\",\"value\":\"Narrative\"},\"renderers\":[{\"id\":\"p1112\"}]}}]}},{\"type\":\"object\",\"name\":\"LabelSet\",\"id\":\"p1117\",\"attributes\":{\"source\":{\"id\":\"p1053\"},\"x\":{\"type\":\"field\",\"field\":\"form\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"p1116\",\"attributes\":{\"value\":-0.15,\"range\":{\"id\":\"p1067\"}}}},\"y\":{\"type\":\"field\",\"field\":\"count_direct\"},\"text\":{\"type\":\"field\",\"field\":\"count_direct\"},\"text_align\":{\"type\":\"value\",\"value\":\"center\"}}},{\"type\":\"object\",\"name\":\"LabelSet\",\"id\":\"p1122\",\"attributes\":{\"source\":{\"id\":\"p1053\"},\"x\":{\"type\":\"field\",\"field\":\"form\",\"transform\":{\"type\":\"object\",\"name\":\"Dodge\",\"id\":\"p1121\",\"attributes\":{\"value\":0.15,\"range\":{\"id\":\"p1067\"}}}},\"y\":{\"type\":\"field\",\"field\":\"count_narr\"},\"text\":{\"type\":\"field\",\"field\":\"count_narr\"},\"text_align\":{\"type\":\"value\",\"value\":\"center\"}}}]}}]}};\n",
       "  const render_items = [{\"docid\":\"aacde5bf-9ac1-4522-8293-f33d16e9658e\",\"roots\":{\"p1057\":\"c2de6911-27ff-4572-bdc8-baa562fc7c9c\"},\"root_ids\":[\"p1057\"]}];\n",
       "  void root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n",
       "  }\n",
       "  if (root.Bokeh !== undefined) {\n",
       "    embed_document(root);\n",
       "  } else {\n",
       "    let attempts = 0;\n",
       "    const timer = setInterval(function(root) {\n",
       "      if (root.Bokeh !== undefined) {\n",
       "        clearInterval(timer);\n",
       "        embed_document(root);\n",
       "      } else {\n",
       "        attempts++;\n",
       "        if (attempts > 100) {\n",
       "          clearInterval(timer);\n",
       "          console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n",
       "        }\n",
       "      }\n",
       "    }, 10, root)\n",
       "  }\n",
       "})(window);"
      ],
      "application/vnd.bokehjs_exec.v0+json": ""
     },
     "metadata": {
      "application/vnd.bokehjs_exec.v0+json": {
       "id": "p1057"
      }
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "from bokeh.layouts import column\n",
    "from bokeh.models import ColumnDataSource, Range1d, LabelSet\n",
    "from bokeh.plotting import figure, output_file, show\n",
    "from bokeh.transform import dodge\n",
    "from collections import Counter\n",
    "from bokeh.io import output_notebook\n",
    "\n",
    "# Prepare the Bokeh output to display in the notebook\n",
    "output_notebook()\n",
    "\n",
    "# Prepare data for the grouped bar chart:\n",
    "# Count verb forms for narrative and direct speech\n",
    "verb_form_counts_narr = Counter(F.vt.v(w) for w in verb_words if F.domain.v(L.u(w, \"clause\")[0]) != \"Q\")\n",
    "verb_form_counts_direct = Counter(F.vt.v(w) for w in verb_words if F.domain.v(L.u(w, \"clause\")[0]) == \"Q\")\n",
    "\n",
    "# Define the categories (verb forms) to plot (excluding \"NA\")\n",
    "verb_forms = [vf for vf in set(verb_form_counts_narr.keys()) | set(verb_form_counts_direct.keys()) if vf != \"NA\"]\n",
    "verb_forms.sort()  # sort alphabetically\n",
    "\n",
    "# Create data source for Bokeh\n",
    "data = {\n",
    "    'form': verb_forms,\n",
    "    'count_narr': [verb_form_counts_narr.get(vf, 0) for vf in verb_forms],\n",
    "    'count_direct': [verb_form_counts_direct.get(vf, 0) for vf in verb_forms]\n",
    "}\n",
    "source = ColumnDataSource(data=data)\n",
    "\n",
    "# Compute maximum count for setting the y_range (with a 10% padding)\n",
    "max_count = max(max(data['count_narr']), max(data['count_direct']))\n",
    "y_end = max_count * 1.1\n",
    "\n",
    "# Create a Bokeh figure for the grouped bar chart\n",
    "p = figure(x_range=verb_forms, height=300, width=500,\n",
    "           title=f\"Parasha #{parasha_num}: {parasha_name_trans} - Verb form distribution\",\n",
    "           x_axis_label=\"Verb Form\", y_axis_label=\"Frequency\",\n",
    "           toolbar_location='right',\n",
    "           y_range=Range1d(start=0, end=y_end))\n",
    "\n",
    "# Draw bars for direct speech and narrative using dodge to position them side by side\n",
    "bar_width = 0.3\n",
    "p.vbar(x=dodge('form', -0.15, range=p.x_range), top='count_direct', width=bar_width,\n",
    "       source=source, color=\"#718dbf\", legend_label=\"Direct speech\")\n",
    "p.vbar(x=dodge('form', 0.15, range=p.x_range), top='count_narr', width=bar_width,\n",
    "       source=source, color=\"#c9d9d3\", legend_label=\"Narrative\")\n",
    "\n",
    "# Add count labels on top of each bar (removed render_mode attribute)\n",
    "labels_direct = LabelSet(x=dodge('form', -0.15, range=p.x_range), y='count_direct',\n",
    "                         text='count_direct', source=source,\n",
    "                         text_align='center', text_baseline='bottom')\n",
    "labels_narr = LabelSet(x=dodge('form', 0.15, range=p.x_range), y='count_narr',\n",
    "                       text='count_narr', source=source,\n",
    "                       text_align='center', text_baseline='bottom')\n",
    "p.add_layout(labels_direct)\n",
    "p.add_layout(labels_narr)\n",
    "\n",
    "# Lock the y_range so it cannot be changed by interactions\n",
    "p.y_range.bounds = (0, y_end)\n",
    "\n",
    "# Optionally, disable active drag/scroll tools\n",
    "if p.toolbar:\n",
    "    p.toolbar.active_drag = None\n",
    "    p.toolbar.active_scroll = None\n",
    "\n",
    "# Improve x-axis label readability\n",
    "p.xaxis.major_label_orientation = 1.0\n",
    "p.legend.location = \"top_left\"\n",
    "\n",
    "# Display the plot\n",
    "show(p)\n",
    "\n",
    "# note: save image as 'verbform_distribution.png'"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "02eb4da8-e178-4770-b608-8659faa03e3a",
   "metadata": {},
   "source": [
    "## 4.2 - Ratio of direct speech versus narrative <a class=\"anchor\" id=\"bullet4x2\"></a>\n",
    "\n",
    "Next, let's quantify the portion of the parasha that is direct speech versus narrative description. We can measure this by the number of words in each category. Using the clause text-type (`domain`), we mark each word as belonging to a *Quotation (Q)* or *Non-quotation (N/D)* context. For simplicity, we'll treat both Narrative and Discursive (`N` and `D`) as \"narrative\" here (i.e., not direct speech). \n",
    "\n",
    "We'll calculate the percentage of words in direct speech vs narrative, and display it as a pie chart for a quick overview:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "988f63c4-f93e-4507-9076-c435bcdfc83d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Direct speech word count: 828 (53.1%)\n",
      "Narrative word count: 730 (46.9%)\n"
     ]
    }
   ],
   "source": [
    "# Calculate number of words in direct speech vs narrative\n",
    "words_direct = [w for w in words_in_parasha if F.domain.v(L.u(w, \"clause\")[0]) == \"Q\"]\n",
    "words_narrative = [w for w in words_in_parasha if F.domain.v(L.u(w, \"clause\")[0]) in (\"N\", \"D\")]\n",
    "\n",
    "count_direct = len(words_direct)\n",
    "count_narr = len(words_narrative)\n",
    "total_words = count_direct + count_narr\n",
    "pct_direct = (count_direct / total_words * 100) if total_words else 0\n",
    "pct_narr = (count_narr / total_words * 100) if total_words else 0\n",
    "\n",
    "print(f\"Direct speech word count: {count_direct} ({pct_direct:.1f}%)\")\n",
    "print(f\"Narrative word count: {count_narr} ({pct_narr:.1f}%)\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "03e2e4a7-0235-4030-bec6-479377881451",
   "metadata": {},
   "source": [
    "This prints out the raw counts and percentage. Now, we create a pie chart using Bokeh's wedge glyph. We will also attach a hover tooltip to display the percentages:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "feff5a4a-c097-4793-a3a4-73dd8b8ab6a4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "    <style>\n",
       "        .bk-notebook-logo {\n",
       "            display: block;\n",
       "            width: 20px;\n",
       "            height: 20px;\n",
       "            background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAOkSURBVDiNjZRtaJVlGMd/1/08zzln5zjP1LWcU9N0NkN8m2CYjpgQYQXqSs0I84OLIC0hkEKoPtiH3gmKoiJDU7QpLgoLjLIQCpEsNJ1vqUOdO7ppbuec5+V+rj4ctwzd8IIbbi6u+8f1539dt3A78eXC7QizUF7gyV1fD1Yqg4JWz84yffhm0qkFqBogB9rM8tZdtwVsPUhWhGcFJngGeWrPzHm5oaMmkfEg1usvLFyc8jLRqDOMru7AyC8saQr7GG7f5fvDeH7Ej8CM66nIF+8yngt6HWaKh7k49Soy9nXurCi1o3qUbS3zWfrYeQDTB/Qj6kX6Ybhw4B+bOYoLKCC9H3Nu/leUTZ1JdRWkkn2ldcCamzrcf47KKXdAJllSlxAOkRgyHsGC/zRday5Qld9DyoM4/q/rUoy/CXh3jzOu3bHUVZeU+DEn8FInkPBFlu3+nW3Nw0mk6vCDiWg8CeJaxEwuHS3+z5RgY+YBR6V1Z1nxSOfoaPa4LASWxxdNp+VWTk7+4vzaou8v8PN+xo+KY2xsw6une2frhw05CTYOmQvsEhjhWjn0bmXPjpE1+kplmmkP3suftwTubK9Vq22qKmrBhpY4jvd5afdRA3wGjFAgcnTK2s4hY0/GPNIb0nErGMCRxWOOX64Z8RAC4oCXdklmEvcL8o0BfkNK4lUg9HTl+oPlQxdNo3Mg4Nv175e/1LDGzZen30MEjRUtmXSfiTVu1kK8W4txyV6BMKlbgk3lMwYCiusNy9fVfvvwMxv8Ynl6vxoByANLTWplvuj/nF9m2+PDtt1eiHPBr1oIfhCChQMBw6Aw0UulqTKZdfVvfG7VcfIqLG9bcldL/+pdWTLxLUy8Qq38heUIjh4XlzZxzQm19lLFlr8vdQ97rjZVOLf8nclzckbcD4wxXMidpX30sFd37Fv/GtwwhzhxGVAprjbg0gCAEeIgwCZyTV2Z1REEW8O4py0wsjeloKoMr6iCY6dP92H6Vw/oTyICIthibxjm/DfN9lVz8IqtqKYLUXfoKVMVQVVJOElGjrnnUt9T9wbgp8AyYKaGlqingHZU/uG2NTZSVqwHQTWkx9hxjkpWDaCg6Ckj5qebgBVbT3V3NNXMSiWSDdGV3hrtzla7J+duwPOToIg42ChPQOQjspnSlp1V+Gjdged7+8UN5CRAV7a5EdFNwCjEaBR27b3W890TE7g24NAP/mMDXRWrGoFPQI9ls/MWO2dWFAar/xcOIImbbpA3zgAAAABJRU5ErkJggg==);\n",
       "        }\n",
       "    </style>\n",
       "    <div>\n",
       "        <a href=\"https://bokeh.org\" target=\"_blank\" class=\"bk-notebook-logo\"></a>\n",
       "        <span id=\"fe0b9a89-de8f-4f93-8176-3553b4ddc5a4\">Loading BokehJS ...</span>\n",
       "    </div>\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/javascript": [
       "'use strict';\n",
       "(function(root) {\n",
       "  function now() {\n",
       "    return new Date();\n",
       "  }\n",
       "\n",
       "  const force = true;\n",
       "\n",
       "  if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n",
       "    root._bokeh_onload_callbacks = [];\n",
       "    root._bokeh_is_loading = undefined;\n",
       "  }\n",
       "\n",
       "const JS_MIME_TYPE = 'application/javascript';\n",
       "  const HTML_MIME_TYPE = 'text/html';\n",
       "  const EXEC_MIME_TYPE = 'application/vnd.bokehjs_exec.v0+json';\n",
       "  const CLASS_NAME = 'output_bokeh rendered_html';\n",
       "\n",
       "  /**\n",
       "   * Render data to the DOM node\n",
       "   */\n",
       "  function render(props, node) {\n",
       "    const script = document.createElement(\"script\");\n",
       "    node.appendChild(script);\n",
       "  }\n",
       "\n",
       "  /**\n",
       "   * Handle when an output is cleared or removed\n",
       "   */\n",
       "  function handleClearOutput(event, handle) {\n",
       "    function drop(id) {\n",
       "      const view = Bokeh.index.get_by_id(id)\n",
       "      if (view != null) {\n",
       "        view.model.document.clear()\n",
       "        Bokeh.index.delete(view)\n",
       "      }\n",
       "    }\n",
       "\n",
       "    const cell = handle.cell;\n",
       "\n",
       "    const id = cell.output_area._bokeh_element_id;\n",
       "    const server_id = cell.output_area._bokeh_server_id;\n",
       "\n",
       "    // Clean up Bokeh references\n",
       "    if (id != null) {\n",
       "      drop(id)\n",
       "    }\n",
       "\n",
       "    if (server_id !== undefined) {\n",
       "      // Clean up Bokeh references\n",
       "      const cmd_clean = \"from bokeh.io.state import curstate; print(curstate().uuid_to_server['\" + server_id + \"'].get_sessions()[0].document.roots[0]._id)\";\n",
       "      cell.notebook.kernel.execute(cmd_clean, {\n",
       "        iopub: {\n",
       "          output: function(msg) {\n",
       "            const id = msg.content.text.trim()\n",
       "            drop(id)\n",
       "          }\n",
       "        }\n",
       "      });\n",
       "      // Destroy server and session\n",
       "      const cmd_destroy = \"import bokeh.io.notebook as ion; ion.destroy_server('\" + server_id + \"')\";\n",
       "      cell.notebook.kernel.execute(cmd_destroy);\n",
       "    }\n",
       "  }\n",
       "\n",
       "  /**\n",
       "   * Handle when a new output is added\n",
       "   */\n",
       "  function handleAddOutput(event, handle) {\n",
       "    const output_area = handle.output_area;\n",
       "    const output = handle.output;\n",
       "\n",
       "    // limit handleAddOutput to display_data with EXEC_MIME_TYPE content only\n",
       "    if ((output.output_type != \"display_data\") || (!Object.prototype.hasOwnProperty.call(output.data, EXEC_MIME_TYPE))) {\n",
       "      return\n",
       "    }\n",
       "\n",
       "    const toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n",
       "\n",
       "    if (output.metadata[EXEC_MIME_TYPE][\"id\"] !== undefined) {\n",
       "      toinsert[toinsert.length - 1].firstChild.textContent = output.data[JS_MIME_TYPE];\n",
       "      // store reference to embed id on output_area\n",
       "      output_area._bokeh_element_id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n",
       "    }\n",
       "    if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n",
       "      const bk_div = document.createElement(\"div\");\n",
       "      bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n",
       "      const script_attrs = bk_div.children[0].attributes;\n",
       "      for (let i = 0; i < script_attrs.length; i++) {\n",
       "        toinsert[toinsert.length - 1].firstChild.setAttribute(script_attrs[i].name, script_attrs[i].value);\n",
       "        toinsert[toinsert.length - 1].firstChild.textContent = bk_div.children[0].textContent\n",
       "      }\n",
       "      // store reference to server id on output_area\n",
       "      output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n",
       "    }\n",
       "  }\n",
       "\n",
       "  function register_renderer(events, OutputArea) {\n",
       "\n",
       "    function append_mime(data, metadata, element) {\n",
       "      // create a DOM node to render to\n",
       "      const toinsert = this.create_output_subarea(\n",
       "        metadata,\n",
       "        CLASS_NAME,\n",
       "        EXEC_MIME_TYPE\n",
       "      );\n",
       "      this.keyboard_manager.register_events(toinsert);\n",
       "      // Render to node\n",
       "      const props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n",
       "      render(props, toinsert[toinsert.length - 1]);\n",
       "      element.append(toinsert);\n",
       "      return toinsert\n",
       "    }\n",
       "\n",
       "    /* Handle when an output is cleared or removed */\n",
       "    events.on('clear_output.CodeCell', handleClearOutput);\n",
       "    events.on('delete.Cell', handleClearOutput);\n",
       "\n",
       "    /* Handle when a new output is added */\n",
       "    events.on('output_added.OutputArea', handleAddOutput);\n",
       "\n",
       "    /**\n",
       "     * Register the mime type and append_mime function with output_area\n",
       "     */\n",
       "    OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n",
       "      /* Is output safe? */\n",
       "      safe: true,\n",
       "      /* Index of renderer in `output_area.display_order` */\n",
       "      index: 0\n",
       "    });\n",
       "  }\n",
       "\n",
       "  // register the mime type if in Jupyter Notebook environment and previously unregistered\n",
       "  if (root.Jupyter !== undefined) {\n",
       "    const events = require('base/js/events');\n",
       "    const OutputArea = require('notebook/js/outputarea').OutputArea;\n",
       "\n",
       "    if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n",
       "      register_renderer(events, OutputArea);\n",
       "    }\n",
       "  }\n",
       "  if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n",
       "    root._bokeh_timeout = Date.now() + 5000;\n",
       "    root._bokeh_failed_load = false;\n",
       "  }\n",
       "\n",
       "  const NB_LOAD_WARNING = {'data': {'text/html':\n",
       "     \"<div style='background-color: #fdd'>\\n\"+\n",
       "     \"<p>\\n\"+\n",
       "     \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n",
       "     \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n",
       "     \"</p>\\n\"+\n",
       "     \"<ul>\\n\"+\n",
       "     \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n",
       "     \"<li>use INLINE resources instead, as so:</li>\\n\"+\n",
       "     \"</ul>\\n\"+\n",
       "     \"<code>\\n\"+\n",
       "     \"from bokeh.resources import INLINE\\n\"+\n",
       "     \"output_notebook(resources=INLINE)\\n\"+\n",
       "     \"</code>\\n\"+\n",
       "     \"</div>\"}};\n",
       "\n",
       "  function display_loaded(error = null) {\n",
       "    const el = document.getElementById(\"fe0b9a89-de8f-4f93-8176-3553b4ddc5a4\");\n",
       "    if (el != null) {\n",
       "      const html = (() => {\n",
       "        if (typeof root.Bokeh === \"undefined\") {\n",
       "          if (error == null) {\n",
       "            return \"BokehJS is loading ...\";\n",
       "          } else {\n",
       "            return \"BokehJS failed to load.\";\n",
       "          }\n",
       "        } else {\n",
       "          const prefix = `BokehJS ${root.Bokeh.version}`;\n",
       "          if (error == null) {\n",
       "            return `${prefix} successfully loaded.`;\n",
       "          } else {\n",
       "            return `${prefix} <b>encountered errors</b> while loading and may not function as expected.`;\n",
       "          }\n",
       "        }\n",
       "      })();\n",
       "      el.innerHTML = html;\n",
       "\n",
       "      if (error != null) {\n",
       "        const wrapper = document.createElement(\"div\");\n",
       "        wrapper.style.overflow = \"auto\";\n",
       "        wrapper.style.height = \"5em\";\n",
       "        wrapper.style.resize = \"vertical\";\n",
       "        const content = document.createElement(\"div\");\n",
       "        content.style.fontFamily = \"monospace\";\n",
       "        content.style.whiteSpace = \"pre-wrap\";\n",
       "        content.style.backgroundColor = \"rgb(255, 221, 221)\";\n",
       "        content.textContent = error.stack ?? error.toString();\n",
       "        wrapper.append(content);\n",
       "        el.append(wrapper);\n",
       "      }\n",
       "    } else if (Date.now() < root._bokeh_timeout) {\n",
       "      setTimeout(() => display_loaded(error), 100);\n",
       "    }\n",
       "  }\n",
       "\n",
       "  function run_callbacks() {\n",
       "    try {\n",
       "      root._bokeh_onload_callbacks.forEach(function(callback) {\n",
       "        if (callback != null)\n",
       "          callback();\n",
       "      });\n",
       "    } finally {\n",
       "      delete root._bokeh_onload_callbacks\n",
       "    }\n",
       "    console.debug(\"Bokeh: all callbacks have finished\");\n",
       "  }\n",
       "\n",
       "  function load_libs(css_urls, js_urls, callback) {\n",
       "    if (css_urls == null) css_urls = [];\n",
       "    if (js_urls == null) js_urls = [];\n",
       "\n",
       "    root._bokeh_onload_callbacks.push(callback);\n",
       "    if (root._bokeh_is_loading > 0) {\n",
       "      console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n",
       "      return null;\n",
       "    }\n",
       "    if (js_urls == null || js_urls.length === 0) {\n",
       "      run_callbacks();\n",
       "      return null;\n",
       "    }\n",
       "    console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n",
       "    root._bokeh_is_loading = css_urls.length + js_urls.length;\n",
       "\n",
       "    function on_load() {\n",
       "      root._bokeh_is_loading--;\n",
       "      if (root._bokeh_is_loading === 0) {\n",
       "        console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n",
       "        run_callbacks()\n",
       "      }\n",
       "    }\n",
       "\n",
       "    function on_error(url) {\n",
       "      console.error(\"failed to load \" + url);\n",
       "    }\n",
       "\n",
       "    for (let i = 0; i < css_urls.length; i++) {\n",
       "      const url = css_urls[i];\n",
       "      const element = document.createElement(\"link\");\n",
       "      element.onload = on_load;\n",
       "      element.onerror = on_error.bind(null, url);\n",
       "      element.rel = \"stylesheet\";\n",
       "      element.type = \"text/css\";\n",
       "      element.href = url;\n",
       "      console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n",
       "      document.body.appendChild(element);\n",
       "    }\n",
       "\n",
       "    for (let i = 0; i < js_urls.length; i++) {\n",
       "      const url = js_urls[i];\n",
       "      const element = document.createElement('script');\n",
       "      element.onload = on_load;\n",
       "      element.onerror = on_error.bind(null, url);\n",
       "      element.async = false;\n",
       "      element.src = url;\n",
       "      console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n",
       "      document.head.appendChild(element);\n",
       "    }\n",
       "  };\n",
       "\n",
       "  function inject_raw_css(css) {\n",
       "    const element = document.createElement(\"style\");\n",
       "    element.appendChild(document.createTextNode(css));\n",
       "    document.body.appendChild(element);\n",
       "  }\n",
       "\n",
       "  const js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-3.6.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.6.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.6.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.6.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-3.6.0.min.js\"];\n",
       "  const css_urls = [];\n",
       "\n",
       "  const inline_js = [    function(Bokeh) {\n",
       "      Bokeh.set_log_level(\"info\");\n",
       "    },\n",
       "function(Bokeh) {\n",
       "    }\n",
       "  ];\n",
       "\n",
       "  function run_inline_js() {\n",
       "    if (root.Bokeh !== undefined || force === true) {\n",
       "      try {\n",
       "            for (let i = 0; i < inline_js.length; i++) {\n",
       "      inline_js[i].call(root, root.Bokeh);\n",
       "    }\n",
       "\n",
       "      } catch (error) {display_loaded(error);throw error;\n",
       "      }if (force === true) {\n",
       "        display_loaded();\n",
       "      }} else if (Date.now() < root._bokeh_timeout) {\n",
       "      setTimeout(run_inline_js, 100);\n",
       "    } else if (!root._bokeh_failed_load) {\n",
       "      console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n",
       "      root._bokeh_failed_load = true;\n",
       "    } else if (force !== true) {\n",
       "      const cell = $(document.getElementById(\"fe0b9a89-de8f-4f93-8176-3553b4ddc5a4\")).parents('.cell').data().cell;\n",
       "      cell.output_area.append_execute_result(NB_LOAD_WARNING)\n",
       "    }\n",
       "  }\n",
       "\n",
       "  if (root._bokeh_is_loading === 0) {\n",
       "    console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n",
       "    run_inline_js();\n",
       "  } else {\n",
       "    load_libs(css_urls, js_urls, function() {\n",
       "      console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n",
       "      run_inline_js();\n",
       "    });\n",
       "  }\n",
       "}(window));"
      ],
      "application/vnd.bokehjs_load.v0+json": "'use strict';\n(function(root) {\n  function now() {\n    return new Date();\n  }\n\n  const force = true;\n\n  if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n    root._bokeh_onload_callbacks = [];\n    root._bokeh_is_loading = undefined;\n  }\n\n\n  if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n    root._bokeh_timeout = Date.now() + 5000;\n    root._bokeh_failed_load = false;\n  }\n\n  const NB_LOAD_WARNING = {'data': {'text/html':\n     \"<div style='background-color: #fdd'>\\n\"+\n     \"<p>\\n\"+\n     \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n     \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n     \"</p>\\n\"+\n     \"<ul>\\n\"+\n     \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n     \"<li>use INLINE resources instead, as so:</li>\\n\"+\n     \"</ul>\\n\"+\n     \"<code>\\n\"+\n     \"from bokeh.resources import INLINE\\n\"+\n     \"output_notebook(resources=INLINE)\\n\"+\n     \"</code>\\n\"+\n     \"</div>\"}};\n\n  function display_loaded(error = null) {\n    const el = document.getElementById(\"fe0b9a89-de8f-4f93-8176-3553b4ddc5a4\");\n    if (el != null) {\n      const html = (() => {\n        if (typeof root.Bokeh === \"undefined\") {\n          if (error == null) {\n            return \"BokehJS is loading ...\";\n          } else {\n            return \"BokehJS failed to load.\";\n          }\n        } else {\n          const prefix = `BokehJS ${root.Bokeh.version}`;\n          if (error == null) {\n            return `${prefix} successfully loaded.`;\n          } else {\n            return `${prefix} <b>encountered errors</b> while loading and may not function as expected.`;\n          }\n        }\n      })();\n      el.innerHTML = html;\n\n      if (error != null) {\n        const wrapper = document.createElement(\"div\");\n        wrapper.style.overflow = \"auto\";\n        wrapper.style.height = \"5em\";\n        wrapper.style.resize = \"vertical\";\n        const content = document.createElement(\"div\");\n        content.style.fontFamily = \"monospace\";\n        content.style.whiteSpace = \"pre-wrap\";\n        content.style.backgroundColor = \"rgb(255, 221, 221)\";\n        content.textContent = error.stack ?? error.toString();\n        wrapper.append(content);\n        el.append(wrapper);\n      }\n    } else if (Date.now() < root._bokeh_timeout) {\n      setTimeout(() => display_loaded(error), 100);\n    }\n  }\n\n  function run_callbacks() {\n    try {\n      root._bokeh_onload_callbacks.forEach(function(callback) {\n        if (callback != null)\n          callback();\n      });\n    } finally {\n      delete root._bokeh_onload_callbacks\n    }\n    console.debug(\"Bokeh: all callbacks have finished\");\n  }\n\n  function load_libs(css_urls, js_urls, callback) {\n    if (css_urls == null) css_urls = [];\n    if (js_urls == null) js_urls = [];\n\n    root._bokeh_onload_callbacks.push(callback);\n    if (root._bokeh_is_loading > 0) {\n      console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n      return null;\n    }\n    if (js_urls == null || js_urls.length === 0) {\n      run_callbacks();\n      return null;\n    }\n    console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n    root._bokeh_is_loading = css_urls.length + js_urls.length;\n\n    function on_load() {\n      root._bokeh_is_loading--;\n      if (root._bokeh_is_loading === 0) {\n        console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n        run_callbacks()\n      }\n    }\n\n    function on_error(url) {\n      console.error(\"failed to load \" + url);\n    }\n\n    for (let i = 0; i < css_urls.length; i++) {\n      const url = css_urls[i];\n      const element = document.createElement(\"link\");\n      element.onload = on_load;\n      element.onerror = on_error.bind(null, url);\n      element.rel = \"stylesheet\";\n      element.type = \"text/css\";\n      element.href = url;\n      console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n      document.body.appendChild(element);\n    }\n\n    for (let i = 0; i < js_urls.length; i++) {\n      const url = js_urls[i];\n      const element = document.createElement('script');\n      element.onload = on_load;\n      element.onerror = on_error.bind(null, url);\n      element.async = false;\n      element.src = url;\n      console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n      document.head.appendChild(element);\n    }\n  };\n\n  function inject_raw_css(css) {\n    const element = document.createElement(\"style\");\n    element.appendChild(document.createTextNode(css));\n    document.body.appendChild(element);\n  }\n\n  const js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-3.6.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.6.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.6.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.6.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-3.6.0.min.js\"];\n  const css_urls = [];\n\n  const inline_js = [    function(Bokeh) {\n      Bokeh.set_log_level(\"info\");\n    },\nfunction(Bokeh) {\n    }\n  ];\n\n  function run_inline_js() {\n    if (root.Bokeh !== undefined || force === true) {\n      try {\n            for (let i = 0; i < inline_js.length; i++) {\n      inline_js[i].call(root, root.Bokeh);\n    }\n\n      } catch (error) {display_loaded(error);throw error;\n      }if (force === true) {\n        display_loaded();\n      }} else if (Date.now() < root._bokeh_timeout) {\n      setTimeout(run_inline_js, 100);\n    } else if (!root._bokeh_failed_load) {\n      console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n      root._bokeh_failed_load = true;\n    } else if (force !== true) {\n      const cell = $(document.getElementById(\"fe0b9a89-de8f-4f93-8176-3553b4ddc5a4\")).parents('.cell').data().cell;\n      cell.output_area.append_execute_result(NB_LOAD_WARNING)\n    }\n  }\n\n  if (root._bokeh_is_loading === 0) {\n    console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n    run_inline_js();\n  } else {\n    load_libs(css_urls, js_urls, function() {\n      console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n      run_inline_js();\n    });\n  }\n}(window));"
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "  <div id=\"ec69aec6-9ab2-45f8-9756-60d576b7c663\" data-root-id=\"p1129\" style=\"display: contents;\"></div>\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/javascript": [
       "(function(root) {\n",
       "  function embed_document(root) {\n",
       "  const docs_json = {\"0d06a456-a978-4aee-845a-fcedbfd62de6\":{\"version\":\"3.6.0\",\"title\":\"Bokeh Application\",\"roots\":[{\"type\":\"object\",\"name\":\"Figure\",\"id\":\"p1129\",\"attributes\":{\"width\":400,\"height\":250,\"x_range\":{\"type\":\"object\",\"name\":\"Range1d\",\"id\":\"p1139\",\"attributes\":{\"start\":-0.5}},\"y_range\":{\"type\":\"object\",\"name\":\"DataRange1d\",\"id\":\"p1131\"},\"x_scale\":{\"type\":\"object\",\"name\":\"LinearScale\",\"id\":\"p1140\"},\"y_scale\":{\"type\":\"object\",\"name\":\"LinearScale\",\"id\":\"p1141\"},\"title\":{\"type\":\"object\",\"name\":\"Title\",\"id\":\"p1132\",\"attributes\":{\"text\":\"Parasha #12: Vayechi - Speech vs Narrative Ratio\"}},\"renderers\":[{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"p1174\",\"attributes\":{\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"p1126\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"p1127\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"p1128\"},\"data\":{\"type\":\"map\",\"entries\":[[\"index\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"AAAAAAEAAAA=\"},\"shape\":[2],\"dtype\":\"int32\",\"order\":\"little\"}],[\"category\",{\"type\":\"ndarray\",\"array\":[\"Direct Speech\",\"Narrative\"],\"shape\":[2],\"dtype\":\"object\",\"order\":\"little\"}],[\"count\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"PAMAANoCAAA=\"},\"shape\":[2],\"dtype\":\"int32\",\"order\":\"little\"}],[\"angle\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"RBiox6+2CkDrQeDgRo0HQA==\"},\"shape\":[2],\"dtype\":\"float64\",\"order\":\"little\"}],[\"percentage\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"8Em9QJGSSkAPtkK/bm1HQA==\"},\"shape\":[2],\"dtype\":\"float64\",\"order\":\"little\"}],[\"color\",{\"type\":\"ndarray\",\"array\":[\"#ff7f0e\",\"#1f77b4\"],\"shape\":[2],\"dtype\":\"object\",\"order\":\"little\"}],[\"label\",{\"type\":\"ndarray\",\"array\":[\"828 (53.1%)\",\"730 (46.9%)\"],\"shape\":[2],\"dtype\":\"object\",\"order\":\"little\"}],[\"angle_cumsum\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"RBiox6+2CkAYLURU+yEZQA==\"},\"shape\":[2],\"dtype\":\"float64\",\"order\":\"little\"}],[\"angle_mid\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"RBiox6+2+j+dHAycqT4TQA==\"},\"shape\":[2],\"dtype\":\"float64\",\"order\":\"little\"}],[\"x\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"Pp/7dbJNnr81n/t1sk2ePw==\"},\"shape\":[2],\"dtype\":\"float64\",\"order\":\"little\"}],[\"y\",{\"type\":\"ndarray\",\"array\":{\"type\":\"bytes\",\"data\":\"F9rpNzob0z8X2uk3OhvTvw==\"},\"shape\":[2],\"dtype\":\"float64\",\"order\":\"little\"}]]}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"p1175\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"p1176\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"Wedge\",\"id\":\"p1171\",\"attributes\":{\"x\":{\"type\":\"value\",\"value\":0},\"y\":{\"type\":\"value\",\"value\":0},\"radius\":{\"type\":\"value\",\"value\":0.4},\"start_angle\":{\"type\":\"expr\",\"expr\":{\"type\":\"object\",\"name\":\"CumSum\",\"id\":\"p1166\",\"attributes\":{\"field\":\"angle\",\"include_zero\":true}}},\"end_angle\":{\"type\":\"expr\",\"expr\":{\"type\":\"object\",\"name\":\"CumSum\",\"id\":\"p1167\",\"attributes\":{\"field\":\"angle\"}}},\"line_color\":{\"type\":\"value\",\"value\":\"white\"},\"fill_color\":{\"type\":\"field\",\"field\":\"color\"}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"Wedge\",\"id\":\"p1172\",\"attributes\":{\"x\":{\"type\":\"value\",\"value\":0},\"y\":{\"type\":\"value\",\"value\":0},\"radius\":{\"type\":\"value\",\"value\":0.4},\"start_angle\":{\"type\":\"expr\",\"expr\":{\"id\":\"p1166\"}},\"end_angle\":{\"type\":\"expr\",\"expr\":{\"id\":\"p1167\"}},\"line_color\":{\"type\":\"value\",\"value\":\"white\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"field\",\"field\":\"color\"},\"fill_alpha\":{\"type\":\"value\",\"value\":0.1},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"Wedge\",\"id\":\"p1173\",\"attributes\":{\"x\":{\"type\":\"value\",\"value\":0},\"y\":{\"type\":\"value\",\"value\":0},\"radius\":{\"type\":\"value\",\"value\":0.4},\"start_angle\":{\"type\":\"expr\",\"expr\":{\"id\":\"p1166\"}},\"end_angle\":{\"type\":\"expr\",\"expr\":{\"id\":\"p1167\"}},\"line_color\":{\"type\":\"value\",\"value\":\"white\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"fill_color\":{\"type\":\"field\",\"field\":\"color\"},\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}}}}],\"toolbar\":{\"type\":\"object\",\"name\":\"Toolbar\",\"id\":\"p1138\",\"attributes\":{\"tools\":[{\"type\":\"object\",\"name\":\"PanTool\",\"id\":\"p1152\"},{\"type\":\"object\",\"name\":\"WheelZoomTool\",\"id\":\"p1153\",\"attributes\":{\"renderers\":\"auto\"}},{\"type\":\"object\",\"name\":\"BoxZoomTool\",\"id\":\"p1154\",\"attributes\":{\"overlay\":{\"type\":\"object\",\"name\":\"BoxAnnotation\",\"id\":\"p1155\",\"attributes\":{\"syncable\":false,\"line_color\":\"black\",\"line_alpha\":1.0,\"line_width\":2,\"line_dash\":[4,4],\"fill_color\":\"lightgrey\",\"fill_alpha\":0.5,\"level\":\"overlay\",\"visible\":false,\"left\":{\"type\":\"number\",\"value\":\"nan\"},\"right\":{\"type\":\"number\",\"value\":\"nan\"},\"top\":{\"type\":\"number\",\"value\":\"nan\"},\"bottom\":{\"type\":\"number\",\"value\":\"nan\"},\"left_units\":\"canvas\",\"right_units\":\"canvas\",\"top_units\":\"canvas\",\"bottom_units\":\"canvas\",\"handles\":{\"type\":\"object\",\"name\":\"BoxInteractionHandles\",\"id\":\"p1161\",\"attributes\":{\"all\":{\"type\":\"object\",\"name\":\"AreaVisuals\",\"id\":\"p1160\",\"attributes\":{\"fill_color\":\"white\",\"hover_fill_color\":\"lightgray\"}}}}}}}},{\"type\":\"object\",\"name\":\"SaveTool\",\"id\":\"p1162\"},{\"type\":\"object\",\"name\":\"ResetTool\",\"id\":\"p1163\"},{\"type\":\"object\",\"name\":\"HelpTool\",\"id\":\"p1164\"},{\"type\":\"object\",\"name\":\"HoverTool\",\"id\":\"p1165\",\"attributes\":{\"renderers\":\"auto\",\"tooltips\":\"@category: @count words (@percentage{0.0}%)\"}}]}},\"left\":[{\"type\":\"object\",\"name\":\"LinearAxis\",\"id\":\"p1147\",\"attributes\":{\"visible\":false,\"ticker\":{\"type\":\"object\",\"name\":\"BasicTicker\",\"id\":\"p1148\",\"attributes\":{\"mantissas\":[1,2,5]}},\"formatter\":{\"type\":\"object\",\"name\":\"BasicTickFormatter\",\"id\":\"p1149\"},\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"p1150\"}}}],\"below\":[{\"type\":\"object\",\"name\":\"LinearAxis\",\"id\":\"p1142\",\"attributes\":{\"visible\":false,\"ticker\":{\"type\":\"object\",\"name\":\"BasicTicker\",\"id\":\"p1143\",\"attributes\":{\"mantissas\":[1,2,5]}},\"formatter\":{\"type\":\"object\",\"name\":\"BasicTickFormatter\",\"id\":\"p1144\"},\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"p1145\"}}}],\"center\":[{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"p1146\",\"attributes\":{\"axis\":{\"id\":\"p1142\"},\"grid_line_color\":null}},{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"p1151\",\"attributes\":{\"dimension\":1,\"axis\":{\"id\":\"p1147\"},\"grid_line_color\":null}},{\"type\":\"object\",\"name\":\"Legend\",\"id\":\"p1177\",\"attributes\":{\"label_text_font_size\":\"8pt\",\"items\":[{\"type\":\"object\",\"name\":\"LegendItem\",\"id\":\"p1178\",\"attributes\":{\"label\":{\"type\":\"field\",\"field\":\"category\"},\"renderers\":[{\"id\":\"p1174\"}]}}]}},{\"type\":\"object\",\"name\":\"LabelSet\",\"id\":\"p1179\",\"attributes\":{\"source\":{\"id\":\"p1126\"},\"x\":{\"type\":\"field\",\"field\":\"x\"},\"y\":{\"type\":\"field\",\"field\":\"y\"},\"text\":{\"type\":\"field\",\"field\":\"label\"},\"text_align\":{\"type\":\"value\",\"value\":\"center\"}}}],\"min_border_left\":53}}]}};\n",
       "  const render_items = [{\"docid\":\"0d06a456-a978-4aee-845a-fcedbfd62de6\",\"roots\":{\"p1129\":\"ec69aec6-9ab2-45f8-9756-60d576b7c663\"},\"root_ids\":[\"p1129\"]}];\n",
       "  void root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n",
       "  }\n",
       "  if (root.Bokeh !== undefined) {\n",
       "    embed_document(root);\n",
       "  } else {\n",
       "    let attempts = 0;\n",
       "    const timer = setInterval(function(root) {\n",
       "      if (root.Bokeh !== undefined) {\n",
       "        clearInterval(timer);\n",
       "        embed_document(root);\n",
       "      } else {\n",
       "        attempts++;\n",
       "        if (attempts > 100) {\n",
       "          clearInterval(timer);\n",
       "          console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n",
       "        }\n",
       "      }\n",
       "    }, 10, root)\n",
       "  }\n",
       "})(window);"
      ],
      "application/vnd.bokehjs_exec.v0+json": ""
     },
     "metadata": {
      "application/vnd.bokehjs_exec.v0+json": {
       "id": "p1129"
      }
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "from math import pi\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "from bokeh.io import output_file, output_notebook, show\n",
    "from bokeh.plotting import figure\n",
    "from bokeh.transform import cumsum\n",
    "from bokeh.models import ColumnDataSource, LabelSet\n",
    "\n",
    "# Set up output\n",
    "output_notebook()\n",
    "\n",
    "# Prepare data for the pie chart\n",
    "pie_data = pd.DataFrame({\n",
    "    'category': ['Direct Speech', 'Narrative'],\n",
    "    'count': [count_direct, count_narr]\n",
    "})\n",
    "total_count = pie_data['count'].sum()\n",
    "pie_data['angle'] = pie_data['count'] / total_count * 2 * pi\n",
    "pie_data['percentage'] = pie_data['count'] / total_count * 100  # Compute percentages\n",
    "pie_data['color'] = [\"#ff7f0e\", \"#1f77b4\"]  # Colors for the two categories\n",
    "\n",
    "# Create a label column combining count and percentage\n",
    "pie_data['label'] = pie_data['count'].astype(str) + \" (\" + pie_data['percentage'].round(1).astype(str) + \"%)\"\n",
    "\n",
    "# Calculate cumulative angles to determine the middle angle for each wedge\n",
    "pie_data['angle_cumsum'] = pie_data['angle'].cumsum()\n",
    "pie_data['angle_mid'] = pie_data['angle_cumsum'] - pie_data['angle'] / 2\n",
    "\n",
    "# Calculate label positions (adjust the radius factor as needed)\n",
    "pie_data['x'] = 0.3 * np.cos(pie_data['angle_mid'])\n",
    "pie_data['y'] = 0.3 * np.sin(pie_data['angle_mid'])\n",
    "\n",
    "source_pie = ColumnDataSource(pie_data)\n",
    "\n",
    "# Create pie chart figure\n",
    "p_pie = figure(\n",
    "    height=250, width=400,\n",
    "    title=f\"Parasha #{parasha_num}: {parasha_name_trans} - Speech vs Narrative Ratio\",\n",
    "    tooltips=\"@category: @count words (@percentage{0.0}%)\",\n",
    "    x_range=(-0.5, 1.0), toolbar_location=\"right\"\n",
    ")\n",
    "\n",
    "# Shift the plot area to align with other plots\n",
    "p_pie.min_border_left = 53\n",
    "\n",
    "p_pie.wedge(\n",
    "    x=0, y=0, radius=0.4, \n",
    "    start_angle=cumsum('angle', include_zero=True), end_angle=cumsum('angle'),\n",
    "    line_color=\"white\", fill_color='color', legend_field='category', source=source_pie\n",
    ")\n",
    "\n",
    "# Add labels showing count and percentage inside each wedge\n",
    "labels = LabelSet(x='x', y='y', text='label', source=source_pie, text_align='center')\n",
    "p_pie.add_layout(labels)\n",
    "\n",
    "p_pie.legend.location = \"top_right\"\n",
    "p_pie.legend.label_text_font_size = \"8pt\"\n",
    "p_pie.axis.visible = False  # Hide axes\n",
    "p_pie.grid.grid_line_color = None\n",
    "\n",
    "show(p_pie)\n",
    "\n",
    "# note: save image as 'speech_narrative_ratio.png'"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "901fd0ab-3800-4cc5-b509-5cf5aa660037",
   "metadata": {},
   "source": [
    "## 4.3 - Term frequency (excluding stopwords) <a class=\"anchor\" id=\"bullet4x3\"></a>\n",
    "\n",
    "Now we analyze the vocabulary of the parasha. We want to find the most frequent words (lexemes) and exclude very common \"stop words\" that are not content-rich. In Hebrew, such stopwords include conjunctions (like \"ื•\" = \"and\"), prepositions (\"ื‘/ื›/ืœ\" = \"in/like/to\", etc.), the definite article (\"ื”\" = \"the\"), pronouns, and a few particles like the negative \"ืœื\" or the accusative marker \"ืืช\". \n",
    "\n",
    "The following words with part-of-speech tags (`sp` feature) ([Sp - BHSA](https://etcbc.github.io/bhsa/features/sp/#)), that are constituting our \"stop words\" for this analysis, will be filtered:\n",
    "  - `prep` (preposition),\n",
    "  - `conj` (conjunction),\n",
    "  - `art` (article),\n",
    "  - `prps`/`prde`/`prin` (pronouns: personal, demonstrative, interrogative),\n",
    "  - `nega` (negative),\n",
    "  - `inrg` (interrogative particle),\n",
    "  - `intj` (interjection).\n",
    "\n",
    "Next the remaining lexemse are counted. BHSA provides a `lex` feature (the lexical root form) and `gloss` (an English gloss/translation) for each word. We will count by lexeme so that different inflected forms count together. For display, we'll use the English glosses of the top lexemes for readability, and also show the Hebrew lexeme. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "f44c44bb-0be7-46f7-91ba-16c749fe3fc0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Top 10 frequent content lexemes:\n",
      "  ื™ื•ืกืฃึœ (Joseph): 34\n",
      "  ืืžืจ (say): 32\n",
      "  ืื‘ึœ (father): 32\n",
      "  ื‘ืŸึœ (son): 23\n",
      "  ืืจืฅึœ (earth): 18\n",
      "  ื™ืฉื‚ืจืืœึœ (Israel): 18\n",
      "  ืงื‘ืจ (bury): 14\n",
      "  ืื—ึœ (brother): 12\n",
      "  ืžืฆืจื™ืึœ (Egypt): 11\n",
      "  ื”ื™ื” (be): 11\n"
     ]
    }
   ],
   "source": [
    "# Define parts of speech to treat as stop words (function words)\n",
    "stop_sp = {\"prep\", \"conj\", \"art\", \"prps\", \"prde\", \"prin\", \"nega\", \"inrg\", \"intj\"}\n",
    "\n",
    "# Build a frequency counter of lexemes (excluding stopword POS)\n",
    "lex_counts = Counter()\n",
    "for w in words_in_parasha:\n",
    "    if F.sp.v(w) in stop_sp:\n",
    "        continue\n",
    "    lex_node = L.u(w, 'lex')[0]  # get the lexeme object for this word\n",
    "    lex_counts[lex_node] += 1\n",
    "\n",
    "# Get the 10 most frequent lexemes (excluding stops)\n",
    "top_lexemes = [lex for lex, cnt in lex_counts.most_common(10)]\n",
    "print(\"Top 10 frequent content lexemes:\")\n",
    "for lex in top_lexemes:\n",
    "    gloss = F.gloss.v(lex)  # English gloss of the lexeme\n",
    "    heb = F.lex_utf8.v(lex)  # Hebrew lexeme in Hebrew script\n",
    "    freq = lex_counts[lex]\n",
    "    print(f\"  {heb} ({gloss}): {freq}\")\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d620df0b-a370-45f5-9522-4d9ab5fb4c27",
   "metadata": {},
   "source": [
    "Now let's visualize these frequencies in a bar chart. We'll label each bar with the lexeme's English gloss:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "d83cf672-ca5c-4f11-be1c-53c47067db3a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "    <style>\n",
       "        .bk-notebook-logo {\n",
       "            display: block;\n",
       "            width: 20px;\n",
       "            height: 20px;\n",
       "            background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAOkSURBVDiNjZRtaJVlGMd/1/08zzln5zjP1LWcU9N0NkN8m2CYjpgQYQXqSs0I84OLIC0hkEKoPtiH3gmKoiJDU7QpLgoLjLIQCpEsNJ1vqUOdO7ppbuec5+V+rj4ctwzd8IIbbi6u+8f1539dt3A78eXC7QizUF7gyV1fD1Yqg4JWz84yffhm0qkFqBogB9rM8tZdtwVsPUhWhGcFJngGeWrPzHm5oaMmkfEg1usvLFyc8jLRqDOMru7AyC8saQr7GG7f5fvDeH7Ej8CM66nIF+8yngt6HWaKh7k49Soy9nXurCi1o3qUbS3zWfrYeQDTB/Qj6kX6Ybhw4B+bOYoLKCC9H3Nu/leUTZ1JdRWkkn2ldcCamzrcf47KKXdAJllSlxAOkRgyHsGC/zRday5Qld9DyoM4/q/rUoy/CXh3jzOu3bHUVZeU+DEn8FInkPBFlu3+nW3Nw0mk6vCDiWg8CeJaxEwuHS3+z5RgY+YBR6V1Z1nxSOfoaPa4LASWxxdNp+VWTk7+4vzaou8v8PN+xo+KY2xsw6une2frhw05CTYOmQvsEhjhWjn0bmXPjpE1+kplmmkP3suftwTubK9Vq22qKmrBhpY4jvd5afdRA3wGjFAgcnTK2s4hY0/GPNIb0nErGMCRxWOOX64Z8RAC4oCXdklmEvcL8o0BfkNK4lUg9HTl+oPlQxdNo3Mg4Nv175e/1LDGzZen30MEjRUtmXSfiTVu1kK8W4txyV6BMKlbgk3lMwYCiusNy9fVfvvwMxv8Ynl6vxoByANLTWplvuj/nF9m2+PDtt1eiHPBr1oIfhCChQMBw6Aw0UulqTKZdfVvfG7VcfIqLG9bcldL/+pdWTLxLUy8Qq38heUIjh4XlzZxzQm19lLFlr8vdQ97rjZVOLf8nclzckbcD4wxXMidpX30sFd37Fv/GtwwhzhxGVAprjbg0gCAEeIgwCZyTV2Z1REEW8O4py0wsjeloKoMr6iCY6dP92H6Vw/oTyICIthibxjm/DfN9lVz8IqtqKYLUXfoKVMVQVVJOElGjrnnUt9T9wbgp8AyYKaGlqingHZU/uG2NTZSVqwHQTWkx9hxjkpWDaCg6Ckj5qebgBVbT3V3NNXMSiWSDdGV3hrtzla7J+duwPOToIg42ChPQOQjspnSlp1V+Gjdged7+8UN5CRAV7a5EdFNwCjEaBR27b3W890TE7g24NAP/mMDXRWrGoFPQI9ls/MWO2dWFAar/xcOIImbbpA3zgAAAABJRU5ErkJggg==);\n",
       "        }\n",
       "    </style>\n",
       "    <div>\n",
       "        <a href=\"https://bokeh.org\" target=\"_blank\" class=\"bk-notebook-logo\"></a>\n",
       "        <span id=\"eb5e51bb-6226-4d2c-86d8-d1a64d545693\">Loading BokehJS ...</span>\n",
       "    </div>\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/javascript": [
       "'use strict';\n",
       "(function(root) {\n",
       "  function now() {\n",
       "    return new Date();\n",
       "  }\n",
       "\n",
       "  const force = true;\n",
       "\n",
       "  if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n",
       "    root._bokeh_onload_callbacks = [];\n",
       "    root._bokeh_is_loading = undefined;\n",
       "  }\n",
       "\n",
       "const JS_MIME_TYPE = 'application/javascript';\n",
       "  const HTML_MIME_TYPE = 'text/html';\n",
       "  const EXEC_MIME_TYPE = 'application/vnd.bokehjs_exec.v0+json';\n",
       "  const CLASS_NAME = 'output_bokeh rendered_html';\n",
       "\n",
       "  /**\n",
       "   * Render data to the DOM node\n",
       "   */\n",
       "  function render(props, node) {\n",
       "    const script = document.createElement(\"script\");\n",
       "    node.appendChild(script);\n",
       "  }\n",
       "\n",
       "  /**\n",
       "   * Handle when an output is cleared or removed\n",
       "   */\n",
       "  function handleClearOutput(event, handle) {\n",
       "    function drop(id) {\n",
       "      const view = Bokeh.index.get_by_id(id)\n",
       "      if (view != null) {\n",
       "        view.model.document.clear()\n",
       "        Bokeh.index.delete(view)\n",
       "      }\n",
       "    }\n",
       "\n",
       "    const cell = handle.cell;\n",
       "\n",
       "    const id = cell.output_area._bokeh_element_id;\n",
       "    const server_id = cell.output_area._bokeh_server_id;\n",
       "\n",
       "    // Clean up Bokeh references\n",
       "    if (id != null) {\n",
       "      drop(id)\n",
       "    }\n",
       "\n",
       "    if (server_id !== undefined) {\n",
       "      // Clean up Bokeh references\n",
       "      const cmd_clean = \"from bokeh.io.state import curstate; print(curstate().uuid_to_server['\" + server_id + \"'].get_sessions()[0].document.roots[0]._id)\";\n",
       "      cell.notebook.kernel.execute(cmd_clean, {\n",
       "        iopub: {\n",
       "          output: function(msg) {\n",
       "            const id = msg.content.text.trim()\n",
       "            drop(id)\n",
       "          }\n",
       "        }\n",
       "      });\n",
       "      // Destroy server and session\n",
       "      const cmd_destroy = \"import bokeh.io.notebook as ion; ion.destroy_server('\" + server_id + \"')\";\n",
       "      cell.notebook.kernel.execute(cmd_destroy);\n",
       "    }\n",
       "  }\n",
       "\n",
       "  /**\n",
       "   * Handle when a new output is added\n",
       "   */\n",
       "  function handleAddOutput(event, handle) {\n",
       "    const output_area = handle.output_area;\n",
       "    const output = handle.output;\n",
       "\n",
       "    // limit handleAddOutput to display_data with EXEC_MIME_TYPE content only\n",
       "    if ((output.output_type != \"display_data\") || (!Object.prototype.hasOwnProperty.call(output.data, EXEC_MIME_TYPE))) {\n",
       "      return\n",
       "    }\n",
       "\n",
       "    const toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n",
       "\n",
       "    if (output.metadata[EXEC_MIME_TYPE][\"id\"] !== undefined) {\n",
       "      toinsert[toinsert.length - 1].firstChild.textContent = output.data[JS_MIME_TYPE];\n",
       "      // store reference to embed id on output_area\n",
       "      output_area._bokeh_element_id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n",
       "    }\n",
       "    if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n",
       "      const bk_div = document.createElement(\"div\");\n",
       "      bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n",
       "      const script_attrs = bk_div.children[0].attributes;\n",
       "      for (let i = 0; i < script_attrs.length; i++) {\n",
       "        toinsert[toinsert.length - 1].firstChild.setAttribute(script_attrs[i].name, script_attrs[i].value);\n",
       "        toinsert[toinsert.length - 1].firstChild.textContent = bk_div.children[0].textContent\n",
       "      }\n",
       "      // store reference to server id on output_area\n",
       "      output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n",
       "    }\n",
       "  }\n",
       "\n",
       "  function register_renderer(events, OutputArea) {\n",
       "\n",
       "    function append_mime(data, metadata, element) {\n",
       "      // create a DOM node to render to\n",
       "      const toinsert = this.create_output_subarea(\n",
       "        metadata,\n",
       "        CLASS_NAME,\n",
       "        EXEC_MIME_TYPE\n",
       "      );\n",
       "      this.keyboard_manager.register_events(toinsert);\n",
       "      // Render to node\n",
       "      const props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n",
       "      render(props, toinsert[toinsert.length - 1]);\n",
       "      element.append(toinsert);\n",
       "      return toinsert\n",
       "    }\n",
       "\n",
       "    /* Handle when an output is cleared or removed */\n",
       "    events.on('clear_output.CodeCell', handleClearOutput);\n",
       "    events.on('delete.Cell', handleClearOutput);\n",
       "\n",
       "    /* Handle when a new output is added */\n",
       "    events.on('output_added.OutputArea', handleAddOutput);\n",
       "\n",
       "    /**\n",
       "     * Register the mime type and append_mime function with output_area\n",
       "     */\n",
       "    OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n",
       "      /* Is output safe? */\n",
       "      safe: true,\n",
       "      /* Index of renderer in `output_area.display_order` */\n",
       "      index: 0\n",
       "    });\n",
       "  }\n",
       "\n",
       "  // register the mime type if in Jupyter Notebook environment and previously unregistered\n",
       "  if (root.Jupyter !== undefined) {\n",
       "    const events = require('base/js/events');\n",
       "    const OutputArea = require('notebook/js/outputarea').OutputArea;\n",
       "\n",
       "    if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n",
       "      register_renderer(events, OutputArea);\n",
       "    }\n",
       "  }\n",
       "  if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n",
       "    root._bokeh_timeout = Date.now() + 5000;\n",
       "    root._bokeh_failed_load = false;\n",
       "  }\n",
       "\n",
       "  const NB_LOAD_WARNING = {'data': {'text/html':\n",
       "     \"<div style='background-color: #fdd'>\\n\"+\n",
       "     \"<p>\\n\"+\n",
       "     \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n",
       "     \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n",
       "     \"</p>\\n\"+\n",
       "     \"<ul>\\n\"+\n",
       "     \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n",
       "     \"<li>use INLINE resources instead, as so:</li>\\n\"+\n",
       "     \"</ul>\\n\"+\n",
       "     \"<code>\\n\"+\n",
       "     \"from bokeh.resources import INLINE\\n\"+\n",
       "     \"output_notebook(resources=INLINE)\\n\"+\n",
       "     \"</code>\\n\"+\n",
       "     \"</div>\"}};\n",
       "\n",
       "  function display_loaded(error = null) {\n",
       "    const el = document.getElementById(\"eb5e51bb-6226-4d2c-86d8-d1a64d545693\");\n",
       "    if (el != null) {\n",
       "      const html = (() => {\n",
       "        if (typeof root.Bokeh === \"undefined\") {\n",
       "          if (error == null) {\n",
       "            return \"BokehJS is loading ...\";\n",
       "          } else {\n",
       "            return \"BokehJS failed to load.\";\n",
       "          }\n",
       "        } else {\n",
       "          const prefix = `BokehJS ${root.Bokeh.version}`;\n",
       "          if (error == null) {\n",
       "            return `${prefix} successfully loaded.`;\n",
       "          } else {\n",
       "            return `${prefix} <b>encountered errors</b> while loading and may not function as expected.`;\n",
       "          }\n",
       "        }\n",
       "      })();\n",
       "      el.innerHTML = html;\n",
       "\n",
       "      if (error != null) {\n",
       "        const wrapper = document.createElement(\"div\");\n",
       "        wrapper.style.overflow = \"auto\";\n",
       "        wrapper.style.height = \"5em\";\n",
       "        wrapper.style.resize = \"vertical\";\n",
       "        const content = document.createElement(\"div\");\n",
       "        content.style.fontFamily = \"monospace\";\n",
       "        content.style.whiteSpace = \"pre-wrap\";\n",
       "        content.style.backgroundColor = \"rgb(255, 221, 221)\";\n",
       "        content.textContent = error.stack ?? error.toString();\n",
       "        wrapper.append(content);\n",
       "        el.append(wrapper);\n",
       "      }\n",
       "    } else if (Date.now() < root._bokeh_timeout) {\n",
       "      setTimeout(() => display_loaded(error), 100);\n",
       "    }\n",
       "  }\n",
       "\n",
       "  function run_callbacks() {\n",
       "    try {\n",
       "      root._bokeh_onload_callbacks.forEach(function(callback) {\n",
       "        if (callback != null)\n",
       "          callback();\n",
       "      });\n",
       "    } finally {\n",
       "      delete root._bokeh_onload_callbacks\n",
       "    }\n",
       "    console.debug(\"Bokeh: all callbacks have finished\");\n",
       "  }\n",
       "\n",
       "  function load_libs(css_urls, js_urls, callback) {\n",
       "    if (css_urls == null) css_urls = [];\n",
       "    if (js_urls == null) js_urls = [];\n",
       "\n",
       "    root._bokeh_onload_callbacks.push(callback);\n",
       "    if (root._bokeh_is_loading > 0) {\n",
       "      console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n",
       "      return null;\n",
       "    }\n",
       "    if (js_urls == null || js_urls.length === 0) {\n",
       "      run_callbacks();\n",
       "      return null;\n",
       "    }\n",
       "    console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n",
       "    root._bokeh_is_loading = css_urls.length + js_urls.length;\n",
       "\n",
       "    function on_load() {\n",
       "      root._bokeh_is_loading--;\n",
       "      if (root._bokeh_is_loading === 0) {\n",
       "        console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n",
       "        run_callbacks()\n",
       "      }\n",
       "    }\n",
       "\n",
       "    function on_error(url) {\n",
       "      console.error(\"failed to load \" + url);\n",
       "    }\n",
       "\n",
       "    for (let i = 0; i < css_urls.length; i++) {\n",
       "      const url = css_urls[i];\n",
       "      const element = document.createElement(\"link\");\n",
       "      element.onload = on_load;\n",
       "      element.onerror = on_error.bind(null, url);\n",
       "      element.rel = \"stylesheet\";\n",
       "      element.type = \"text/css\";\n",
       "      element.href = url;\n",
       "      console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n",
       "      document.body.appendChild(element);\n",
       "    }\n",
       "\n",
       "    for (let i = 0; i < js_urls.length; i++) {\n",
       "      const url = js_urls[i];\n",
       "      const element = document.createElement('script');\n",
       "      element.onload = on_load;\n",
       "      element.onerror = on_error.bind(null, url);\n",
       "      element.async = false;\n",
       "      element.src = url;\n",
       "      console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n",
       "      document.head.appendChild(element);\n",
       "    }\n",
       "  };\n",
       "\n",
       "  function inject_raw_css(css) {\n",
       "    const element = document.createElement(\"style\");\n",
       "    element.appendChild(document.createTextNode(css));\n",
       "    document.body.appendChild(element);\n",
       "  }\n",
       "\n",
       "  const js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-3.6.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.6.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.6.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.6.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-3.6.0.min.js\"];\n",
       "  const css_urls = [];\n",
       "\n",
       "  const inline_js = [    function(Bokeh) {\n",
       "      Bokeh.set_log_level(\"info\");\n",
       "    },\n",
       "function(Bokeh) {\n",
       "    }\n",
       "  ];\n",
       "\n",
       "  function run_inline_js() {\n",
       "    if (root.Bokeh !== undefined || force === true) {\n",
       "      try {\n",
       "            for (let i = 0; i < inline_js.length; i++) {\n",
       "      inline_js[i].call(root, root.Bokeh);\n",
       "    }\n",
       "\n",
       "      } catch (error) {display_loaded(error);throw error;\n",
       "      }if (force === true) {\n",
       "        display_loaded();\n",
       "      }} else if (Date.now() < root._bokeh_timeout) {\n",
       "      setTimeout(run_inline_js, 100);\n",
       "    } else if (!root._bokeh_failed_load) {\n",
       "      console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n",
       "      root._bokeh_failed_load = true;\n",
       "    } else if (force !== true) {\n",
       "      const cell = $(document.getElementById(\"eb5e51bb-6226-4d2c-86d8-d1a64d545693\")).parents('.cell').data().cell;\n",
       "      cell.output_area.append_execute_result(NB_LOAD_WARNING)\n",
       "    }\n",
       "  }\n",
       "\n",
       "  if (root._bokeh_is_loading === 0) {\n",
       "    console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n",
       "    run_inline_js();\n",
       "  } else {\n",
       "    load_libs(css_urls, js_urls, function() {\n",
       "      console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n",
       "      run_inline_js();\n",
       "    });\n",
       "  }\n",
       "}(window));"
      ],
      "application/vnd.bokehjs_load.v0+json": "'use strict';\n(function(root) {\n  function now() {\n    return new Date();\n  }\n\n  const force = true;\n\n  if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n    root._bokeh_onload_callbacks = [];\n    root._bokeh_is_loading = undefined;\n  }\n\n\n  if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n    root._bokeh_timeout = Date.now() + 5000;\n    root._bokeh_failed_load = false;\n  }\n\n  const NB_LOAD_WARNING = {'data': {'text/html':\n     \"<div style='background-color: #fdd'>\\n\"+\n     \"<p>\\n\"+\n     \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n     \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n     \"</p>\\n\"+\n     \"<ul>\\n\"+\n     \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n     \"<li>use INLINE resources instead, as so:</li>\\n\"+\n     \"</ul>\\n\"+\n     \"<code>\\n\"+\n     \"from bokeh.resources import INLINE\\n\"+\n     \"output_notebook(resources=INLINE)\\n\"+\n     \"</code>\\n\"+\n     \"</div>\"}};\n\n  function display_loaded(error = null) {\n    const el = document.getElementById(\"eb5e51bb-6226-4d2c-86d8-d1a64d545693\");\n    if (el != null) {\n      const html = (() => {\n        if (typeof root.Bokeh === \"undefined\") {\n          if (error == null) {\n            return \"BokehJS is loading ...\";\n          } else {\n            return \"BokehJS failed to load.\";\n          }\n        } else {\n          const prefix = `BokehJS ${root.Bokeh.version}`;\n          if (error == null) {\n            return `${prefix} successfully loaded.`;\n          } else {\n            return `${prefix} <b>encountered errors</b> while loading and may not function as expected.`;\n          }\n        }\n      })();\n      el.innerHTML = html;\n\n      if (error != null) {\n        const wrapper = document.createElement(\"div\");\n        wrapper.style.overflow = \"auto\";\n        wrapper.style.height = \"5em\";\n        wrapper.style.resize = \"vertical\";\n        const content = document.createElement(\"div\");\n        content.style.fontFamily = \"monospace\";\n        content.style.whiteSpace = \"pre-wrap\";\n        content.style.backgroundColor = \"rgb(255, 221, 221)\";\n        content.textContent = error.stack ?? error.toString();\n        wrapper.append(content);\n        el.append(wrapper);\n      }\n    } else if (Date.now() < root._bokeh_timeout) {\n      setTimeout(() => display_loaded(error), 100);\n    }\n  }\n\n  function run_callbacks() {\n    try {\n      root._bokeh_onload_callbacks.forEach(function(callback) {\n        if (callback != null)\n          callback();\n      });\n    } finally {\n      delete root._bokeh_onload_callbacks\n    }\n    console.debug(\"Bokeh: all callbacks have finished\");\n  }\n\n  function load_libs(css_urls, js_urls, callback) {\n    if (css_urls == null) css_urls = [];\n    if (js_urls == null) js_urls = [];\n\n    root._bokeh_onload_callbacks.push(callback);\n    if (root._bokeh_is_loading > 0) {\n      console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n      return null;\n    }\n    if (js_urls == null || js_urls.length === 0) {\n      run_callbacks();\n      return null;\n    }\n    console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n    root._bokeh_is_loading = css_urls.length + js_urls.length;\n\n    function on_load() {\n      root._bokeh_is_loading--;\n      if (root._bokeh_is_loading === 0) {\n        console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n        run_callbacks()\n      }\n    }\n\n    function on_error(url) {\n      console.error(\"failed to load \" + url);\n    }\n\n    for (let i = 0; i < css_urls.length; i++) {\n      const url = css_urls[i];\n      const element = document.createElement(\"link\");\n      element.onload = on_load;\n      element.onerror = on_error.bind(null, url);\n      element.rel = \"stylesheet\";\n      element.type = \"text/css\";\n      element.href = url;\n      console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n      document.body.appendChild(element);\n    }\n\n    for (let i = 0; i < js_urls.length; i++) {\n      const url = js_urls[i];\n      const element = document.createElement('script');\n      element.onload = on_load;\n      element.onerror = on_error.bind(null, url);\n      element.async = false;\n      element.src = url;\n      console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n      document.head.appendChild(element);\n    }\n  };\n\n  function inject_raw_css(css) {\n    const element = document.createElement(\"style\");\n    element.appendChild(document.createTextNode(css));\n    document.body.appendChild(element);\n  }\n\n  const js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-3.6.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.6.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.6.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.6.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-mathjax-3.6.0.min.js\"];\n  const css_urls = [];\n\n  const inline_js = [    function(Bokeh) {\n      Bokeh.set_log_level(\"info\");\n    },\nfunction(Bokeh) {\n    }\n  ];\n\n  function run_inline_js() {\n    if (root.Bokeh !== undefined || force === true) {\n      try {\n            for (let i = 0; i < inline_js.length; i++) {\n      inline_js[i].call(root, root.Bokeh);\n    }\n\n      } catch (error) {display_loaded(error);throw error;\n      }if (force === true) {\n        display_loaded();\n      }} else if (Date.now() < root._bokeh_timeout) {\n      setTimeout(run_inline_js, 100);\n    } else if (!root._bokeh_failed_load) {\n      console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n      root._bokeh_failed_load = true;\n    } else if (force !== true) {\n      const cell = $(document.getElementById(\"eb5e51bb-6226-4d2c-86d8-d1a64d545693\")).parents('.cell').data().cell;\n      cell.output_area.append_execute_result(NB_LOAD_WARNING)\n    }\n  }\n\n  if (root._bokeh_is_loading === 0) {\n    console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n    run_inline_js();\n  } else {\n    load_libs(css_urls, js_urls, function() {\n      console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n      run_inline_js();\n    });\n  }\n}(window));"
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Lexeme (Hebrew)</th>\n",
       "      <th>Gloss (English)</th>\n",
       "      <th>Frequency</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>ื™ื•ืกืฃึœ</td>\n",
       "      <td>Joseph</td>\n",
       "      <td>34</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>ืืžืจ</td>\n",
       "      <td>say</td>\n",
       "      <td>32</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>ืื‘ึœ</td>\n",
       "      <td>father</td>\n",
       "      <td>32</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>ื‘ืŸึœ</td>\n",
       "      <td>son</td>\n",
       "      <td>23</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>ืืจืฅึœ</td>\n",
       "      <td>earth</td>\n",
       "      <td>18</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>ื™ืฉื‚ืจืืœึœ</td>\n",
       "      <td>Israel</td>\n",
       "      <td>18</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>ืงื‘ืจ</td>\n",
       "      <td>bury</td>\n",
       "      <td>14</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>ืื—ึœ</td>\n",
       "      <td>brother</td>\n",
       "      <td>12</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>ืžืฆืจื™ืึœ</td>\n",
       "      <td>Egypt</td>\n",
       "      <td>11</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>ื”ื™ื”</td>\n",
       "      <td>be</td>\n",
       "      <td>11</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>ื™ื•ืึœ</td>\n",
       "      <td>day</td>\n",
       "      <td>11</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>ืืœื”ื™ืึœ</td>\n",
       "      <td>god(s)</td>\n",
       "      <td>11</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12</th>\n",
       "      <td>ืขืœื”</td>\n",
       "      <td>ascend</td>\n",
       "      <td>11</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13</th>\n",
       "      <td>ื™ืขืงื‘ึœ</td>\n",
       "      <td>Jacob</td>\n",
       "      <td>10</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>14</th>\n",
       "      <td>ืจืื”</td>\n",
       "      <td>see</td>\n",
       "      <td>10</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   Lexeme (Hebrew) Gloss (English)  Frequency\n",
       "0            ื™ื•ืกืฃึœ          Joseph         34\n",
       "1              ืืžืจ             say         32\n",
       "2              ืื‘ึœ          father         32\n",
       "3              ื‘ืŸึœ             son         23\n",
       "4             ืืจืฅึœ           earth         18\n",
       "5          ื™ืฉื‚ืจืืœึœ          Israel         18\n",
       "6              ืงื‘ืจ            bury         14\n",
       "7              ืื—ึœ         brother         12\n",
       "8           ืžืฆืจื™ืึœ           Egypt         11\n",
       "9              ื”ื™ื”              be         11\n",
       "10            ื™ื•ืึœ             day         11\n",
       "11          ืืœื”ื™ืึœ          god(s)         11\n",
       "12             ืขืœื”          ascend         11\n",
       "13           ื™ืขืงื‘ึœ           Jacob         10\n",
       "14             ืจืื”             see         10"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "from bokeh.io import output_notebook\n",
    "\n",
    "# Prepare the Bokeh output to display in the notebook\n",
    "output_notebook()\n",
    "\n",
    "# Prepare data for bar chart of top terms\n",
    "top_lex_nodes = [lex for lex, cnt in lex_counts.most_common(15)]\n",
    "top_lex_heb = [F.lex_utf8.v(lex) for lex in top_lex_nodes]   # Hebrew form\n",
    "top_lex_gloss = [F.gloss.v(lex) or \"\" for lex in top_lex_nodes]  # English gloss (if available)\n",
    "top_lex_freq = [lex_counts[lex] for lex in top_lex_nodes]\n",
    "\n",
    "# Create DataFrame or dict for convenience\n",
    "freq_df = pd.DataFrame({\n",
    "    \"Lexeme (Hebrew)\": top_lex_heb,\n",
    "    \"Gloss (English)\": top_lex_gloss,\n",
    "    \"Frequency\": top_lex_freq\n",
    "})\n",
    "# Display the table of top words\n",
    "display(freq_df)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b02faa1c-dea6-40f1-9e3c-be35e67636c4",
   "metadata": {},
   "source": [
    "This tabular output shows the top 15 content words with their gloss and counts. Now the bar chart using Bokeh:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "214d38d0-3970-4750-a705-73d52097e51c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "  <div id=\"fd6cdecf-f7d0-4008-99ab-845783e7a047\" data-root-id=\"p1192\" style=\"display: contents;\"></div>\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/javascript": [
       "(function(root) {\n",
       "  function embed_document(root) {\n",
       "  const docs_json = {\"70da71d8-b6af-4f19-bc11-2c0763494d1b\":{\"version\":\"3.6.0\",\"title\":\"Bokeh Application\",\"roots\":[{\"type\":\"object\",\"name\":\"Figure\",\"id\":\"p1192\",\"attributes\":{\"width\":500,\"height\":300,\"x_range\":{\"type\":\"object\",\"name\":\"FactorRange\",\"id\":\"p1202\",\"attributes\":{\"factors\":[\"Joseph (\\u05d9\\u05d5\\u05e1\\u05e3\\u059c)\",\"say (\\u05d0\\u05de\\u05e8)\",\"father (\\u05d0\\u05d1\\u059c)\",\"son (\\u05d1\\u05df\\u059c)\",\"earth (\\u05d0\\u05e8\\u05e5\\u059c)\",\"Israel (\\u05d9\\u05e9\\u05c2\\u05e8\\u05d0\\u05dc\\u059c)\",\"bury (\\u05e7\\u05d1\\u05e8)\",\"brother (\\u05d0\\u05d7\\u059c)\",\"Egypt (\\u05de\\u05e6\\u05e8\\u05d9\\u05dd\\u059c)\",\"be (\\u05d4\\u05d9\\u05d4)\",\"day (\\u05d9\\u05d5\\u05dd\\u059c)\",\"god(s) (\\u05d0\\u05dc\\u05d4\\u05d9\\u05dd\\u059c)\",\"ascend (\\u05e2\\u05dc\\u05d4)\",\"Jacob (\\u05d9\\u05e2\\u05e7\\u05d1\\u059c)\",\"see (\\u05e8\\u05d0\\u05d4)\"]}},\"y_range\":{\"type\":\"object\",\"name\":\"Range1d\",\"id\":\"p1191\",\"attributes\":{\"end\":37.400000000000006,\"bounds\":[0,37.400000000000006]}},\"x_scale\":{\"type\":\"object\",\"name\":\"CategoricalScale\",\"id\":\"p1203\"},\"y_scale\":{\"type\":\"object\",\"name\":\"LinearScale\",\"id\":\"p1204\"},\"title\":{\"type\":\"object\",\"name\":\"Title\",\"id\":\"p1195\",\"attributes\":{\"text\":\"Parasha #12: Vayechi - Top terms (excluding stopwords)\"}},\"renderers\":[{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"p1237\",\"attributes\":{\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"p1228\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"p1229\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"p1230\"},\"data\":{\"type\":\"map\",\"entries\":[[\"x\",[\"Joseph (\\u05d9\\u05d5\\u05e1\\u05e3\\u059c)\",\"say (\\u05d0\\u05de\\u05e8)\",\"father (\\u05d0\\u05d1\\u059c)\",\"son (\\u05d1\\u05df\\u059c)\",\"earth (\\u05d0\\u05e8\\u05e5\\u059c)\",\"Israel (\\u05d9\\u05e9\\u05c2\\u05e8\\u05d0\\u05dc\\u059c)\",\"bury (\\u05e7\\u05d1\\u05e8)\",\"brother (\\u05d0\\u05d7\\u059c)\",\"Egypt (\\u05de\\u05e6\\u05e8\\u05d9\\u05dd\\u059c)\",\"be (\\u05d4\\u05d9\\u05d4)\",\"day (\\u05d9\\u05d5\\u05dd\\u059c)\",\"god(s) (\\u05d0\\u05dc\\u05d4\\u05d9\\u05dd\\u059c)\",\"ascend (\\u05e2\\u05dc\\u05d4)\",\"Jacob (\\u05d9\\u05e2\\u05e7\\u05d1\\u059c)\",\"see (\\u05e8\\u05d0\\u05d4)\"]],[\"top\",[34,32,32,23,18,18,14,12,11,11,11,11,11,10,10]]]}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"p1238\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"p1239\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"p1234\",\"attributes\":{\"x\":{\"type\":\"field\",\"field\":\"x\"},\"width\":{\"type\":\"value\",\"value\":0.8},\"top\":{\"type\":\"field\",\"field\":\"top\"},\"line_color\":{\"type\":\"value\",\"value\":\"#2ca02c\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#2ca02c\"},\"hatch_color\":{\"type\":\"value\",\"value\":\"#2ca02c\"}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"p1235\",\"attributes\":{\"x\":{\"type\":\"field\",\"field\":\"x\"},\"width\":{\"type\":\"value\",\"value\":0.8},\"top\":{\"type\":\"field\",\"field\":\"top\"},\"line_color\":{\"type\":\"value\",\"value\":\"#2ca02c\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"#2ca02c\"},\"fill_alpha\":{\"type\":\"value\",\"value\":0.1},\"hatch_color\":{\"type\":\"value\",\"value\":\"#2ca02c\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"p1236\",\"attributes\":{\"x\":{\"type\":\"field\",\"field\":\"x\"},\"width\":{\"type\":\"value\",\"value\":0.8},\"top\":{\"type\":\"field\",\"field\":\"top\"},\"line_color\":{\"type\":\"value\",\"value\":\"#2ca02c\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"fill_color\":{\"type\":\"value\",\"value\":\"#2ca02c\"},\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"hatch_color\":{\"type\":\"value\",\"value\":\"#2ca02c\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}}}}],\"toolbar\":{\"type\":\"object\",\"name\":\"Toolbar\",\"id\":\"p1201\",\"attributes\":{\"tools\":[{\"type\":\"object\",\"name\":\"PanTool\",\"id\":\"p1215\"},{\"type\":\"object\",\"name\":\"WheelZoomTool\",\"id\":\"p1216\",\"attributes\":{\"renderers\":\"auto\"}},{\"type\":\"object\",\"name\":\"BoxZoomTool\",\"id\":\"p1217\",\"attributes\":{\"overlay\":{\"type\":\"object\",\"name\":\"BoxAnnotation\",\"id\":\"p1218\",\"attributes\":{\"syncable\":false,\"line_color\":\"black\",\"line_alpha\":1.0,\"line_width\":2,\"line_dash\":[4,4],\"fill_color\":\"lightgrey\",\"fill_alpha\":0.5,\"level\":\"overlay\",\"visible\":false,\"left\":{\"type\":\"number\",\"value\":\"nan\"},\"right\":{\"type\":\"number\",\"value\":\"nan\"},\"top\":{\"type\":\"number\",\"value\":\"nan\"},\"bottom\":{\"type\":\"number\",\"value\":\"nan\"},\"left_units\":\"canvas\",\"right_units\":\"canvas\",\"top_units\":\"canvas\",\"bottom_units\":\"canvas\",\"handles\":{\"type\":\"object\",\"name\":\"BoxInteractionHandles\",\"id\":\"p1224\",\"attributes\":{\"all\":{\"type\":\"object\",\"name\":\"AreaVisuals\",\"id\":\"p1223\",\"attributes\":{\"fill_color\":\"white\",\"hover_fill_color\":\"lightgray\"}}}}}}}},{\"type\":\"object\",\"name\":\"SaveTool\",\"id\":\"p1225\"},{\"type\":\"object\",\"name\":\"ResetTool\",\"id\":\"p1226\"},{\"type\":\"object\",\"name\":\"HelpTool\",\"id\":\"p1227\"}],\"active_drag\":null,\"active_scroll\":null}},\"left\":[{\"type\":\"object\",\"name\":\"LinearAxis\",\"id\":\"p1210\",\"attributes\":{\"ticker\":{\"type\":\"object\",\"name\":\"BasicTicker\",\"id\":\"p1211\",\"attributes\":{\"mantissas\":[1,2,5]}},\"formatter\":{\"type\":\"object\",\"name\":\"BasicTickFormatter\",\"id\":\"p1212\"},\"axis_label\":\"Frequency\",\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"p1213\"}}}],\"below\":[{\"type\":\"object\",\"name\":\"CategoricalAxis\",\"id\":\"p1205\",\"attributes\":{\"ticker\":{\"type\":\"object\",\"name\":\"CategoricalTicker\",\"id\":\"p1206\"},\"formatter\":{\"type\":\"object\",\"name\":\"CategoricalTickFormatter\",\"id\":\"p1207\"},\"axis_label\":\"Lexeme\",\"major_label_orientation\":0.9,\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"p1208\"},\"major_label_text_font_size\":\"8pt\"}}],\"center\":[{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"p1209\",\"attributes\":{\"axis\":{\"id\":\"p1205\"}}},{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"p1214\",\"attributes\":{\"dimension\":1,\"axis\":{\"id\":\"p1210\"}}},{\"type\":\"object\",\"name\":\"LabelSet\",\"id\":\"p1240\",\"attributes\":{\"level\":\"glyph\",\"source\":{\"id\":\"p1228\"},\"x\":{\"type\":\"field\",\"field\":\"x\"},\"y\":{\"type\":\"field\",\"field\":\"top\"},\"text\":{\"type\":\"field\",\"field\":\"top\"},\"x_offset\":{\"type\":\"value\",\"value\":-10},\"y_offset\":{\"type\":\"value\",\"value\":1}}}]}}]}};\n",
       "  const render_items = [{\"docid\":\"70da71d8-b6af-4f19-bc11-2c0763494d1b\",\"roots\":{\"p1192\":\"fd6cdecf-f7d0-4008-99ab-845783e7a047\"},\"root_ids\":[\"p1192\"]}];\n",
       "  void root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n",
       "  }\n",
       "  if (root.Bokeh !== undefined) {\n",
       "    embed_document(root);\n",
       "  } else {\n",
       "    let attempts = 0;\n",
       "    const timer = setInterval(function(root) {\n",
       "      if (root.Bokeh !== undefined) {\n",
       "        clearInterval(timer);\n",
       "        embed_document(root);\n",
       "      } else {\n",
       "        attempts++;\n",
       "        if (attempts > 100) {\n",
       "          clearInterval(timer);\n",
       "          console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n",
       "        }\n",
       "      }\n",
       "    }, 10, root)\n",
       "  }\n",
       "})(window);"
      ],
      "application/vnd.bokehjs_exec.v0+json": ""
     },
     "metadata": {
      "application/vnd.bokehjs_exec.v0+json": {
       "id": "p1192"
      }
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "\n",
    "from bokeh.models import Range1d, HoverTool, ColumnDataSource, LabelSet\n",
    "from bokeh.plotting import figure, output_file, show\n",
    "from bokeh.io import export_svgs\n",
    "from bokeh.embed import components\n",
    "from bokeh.models import Div\n",
    "\n",
    "# Create the list of terms, combining gloss and Hebrew as needed\n",
    "terms = [f\"{gloss} ({heb})\" if gloss else heb for gloss, heb in zip(top_lex_gloss, top_lex_heb)]\n",
    "\n",
    "# Compute the maximum frequency and add padding (e.g., 10%)\n",
    "max_freq = max(top_lex_freq)\n",
    "y_end = max_freq * 1.1\n",
    "\n",
    "# Create the figure with a fixed y_range\n",
    "p_terms = figure(x_range=terms, height=300, width=500,\n",
    "                 title=f\"Parasha #{parasha_num}: {parasha_name_trans} - Top terms (excluding stopwords)\",\n",
    "                 x_axis_label=\"Lexeme\", y_axis_label=\"Frequency\",\n",
    "                 toolbar_location=\"right\",\n",
    "                 y_range=Range1d(start=0, end=y_end))\n",
    "\n",
    "# Create a ColumnDataSource to hold the data\n",
    "source = ColumnDataSource(data=dict(x=terms, top=top_lex_freq))\n",
    "\n",
    "# Draw the bars\n",
    "p_terms.vbar(x='x', top='top', width=0.8, color=\"#2ca02c\", source=source)\n",
    "\n",
    "# Lock the y_range to prevent zooming or panning\n",
    "p_terms.y_range.bounds = (0, y_end)\n",
    "\n",
    "# If a toolbar exists, ensure no active drag or scroll tools are set\n",
    "if p_terms.toolbar:\n",
    "    p_terms.toolbar.active_drag = None\n",
    "    p_terms.toolbar.active_scroll = None\n",
    "\n",
    "# Rotate x-axis labels and adjust font size to prevent overlap\n",
    "p_terms.xaxis.major_label_orientation = 0.9\n",
    "p_terms.xaxis.major_label_text_font_size = \"8pt\"\n",
    "\n",
    "# Add labels above each bar\n",
    "labels = LabelSet(x='x', y='top', text='top', level='glyph', x_offset=-10, y_offset=1, source=source)\n",
    "p_terms.add_layout(labels)\n",
    "\n",
    "# Display the plot\n",
    "show(p_terms)\n",
    "\n",
    "# note: save image as 'top_terms.png'"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6a509809-2d8b-41b4-a462-d6e9a83277cf",
   "metadata": {},
   "source": [
    "## 4.4 - Clause types and phrase functions <a class=\"anchor\" id=\"bullet4x4\"></a>\n",
    "\n",
    "Finally, we consider some syntactic patterns and markers in the parasha. The BHSA dataset provides detailed syntactic analysis:\n",
    "- *Clause types:* Each clause is classified by its structure and leading element. For example, a clause beginning with a *wayyiqtol* verb is labeled as `Wayyiqtol-X clause (WayX)` if it has an explicit subject, or `Wayyiqtol-0 clause (Way0)` if no subject is explicitly present ([Typ - BHSA](https://etcbc.github.io/bhsa/features/typ/#)). There are many such codes (e.g., clauses starting with *weqatal*, infinitives, participles, etc., as listed in BHSA documentation ([Typ - BHSA](https://etcbc.github.io/bhsa/features/typ/#)) ([Typ - BHSA](https://etcbc.github.io/bhsa/features/typ/#))). These clause type patterns often correlate with narrative structure (Wayyiqtol chains for narrative sequence, X-qatal for past background, etc.).\n",
    "- *Phrase functions:* Each phrase in the syntax tree has a grammatical function, such as Subject (Subj), Object (Objc), Predicate (Pred), Adjunct (Adju), etc. ([Function - BHSA](https://etcbc.github.io/bhsa/features/function/#)) ([Function - BHSA](https://etcbc.github.io/bhsa/features/function/#)). This tells us the role a phrase plays in the clause.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "26ce7f52-18ce-45b1-a5cd-7c2465df25ea",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Most common phrase functions:\n",
      "  Pred: 228\n",
      "  Conj: 181\n",
      "  Cmpl: 133\n",
      "  Subj: 131\n",
      "  Objc: 95\n",
      "  PreC: 66\n",
      "  Loca: 26\n",
      "  PreO: 26\n",
      "  Rela: 24\n",
      "  Adju: 21\n"
     ]
    }
   ],
   "source": [
    "# Count phrase functions in the parasha\n",
    "function_counts = Counter(F.function.v(ph) for ph in phrases_in_parasha if F.function.v(ph))\n",
    "# Exclude Unknown or None\n",
    "if None in function_counts: \n",
    "    del function_counts[None]\n",
    "if \"Unkn\" in function_counts: \n",
    "    del function_counts[\"Unkn\"]\n",
    "\n",
    "# Get the most frequent functions\n",
    "common_funcs = function_counts.most_common(10)\n",
    "print(\"Most common phrase functions:\")\n",
    "for func, count in common_funcs:\n",
    "    print(f\"  {func}: {count}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "87984c34-aca0-4057-88d5-5493770bce43",
   "metadata": {},
   "source": [
    "Let's visualize this in a bar chart:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "19a33478-6fb7-473b-bf62-914a4af6725a",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "  <div id=\"b388ebe0-561d-498f-9b21-74d8c47f9787\" data-root-id=\"p1245\" style=\"display: contents;\"></div>\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/javascript": [
       "(function(root) {\n",
       "  function embed_document(root) {\n",
       "  const docs_json = {\"a90c8e02-3277-440b-b4b3-a2b2ff1c2c1e\":{\"version\":\"3.6.0\",\"title\":\"Bokeh Application\",\"roots\":[{\"type\":\"object\",\"name\":\"Figure\",\"id\":\"p1245\",\"attributes\":{\"width\":400,\"height\":300,\"x_range\":{\"type\":\"object\",\"name\":\"FactorRange\",\"id\":\"p1255\",\"attributes\":{\"factors\":[\"Pred\",\"Conj\",\"Cmpl\",\"Subj\",\"Objc\",\"PreC\",\"Loca\",\"PreO\",\"Rela\",\"Adju\"]}},\"y_range\":{\"type\":\"object\",\"name\":\"Range1d\",\"id\":\"p1244\",\"attributes\":{\"end\":250.8,\"bounds\":[0,250.8]}},\"x_scale\":{\"type\":\"object\",\"name\":\"CategoricalScale\",\"id\":\"p1256\"},\"y_scale\":{\"type\":\"object\",\"name\":\"LinearScale\",\"id\":\"p1257\"},\"title\":{\"type\":\"object\",\"name\":\"Title\",\"id\":\"p1248\",\"attributes\":{\"text\":\"Parasha 12: Vayechi - Phrase function distribution\"}},\"renderers\":[{\"type\":\"object\",\"name\":\"GlyphRenderer\",\"id\":\"p1287\",\"attributes\":{\"data_source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"p1281\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"p1282\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"p1283\"},\"data\":{\"type\":\"map\",\"entries\":[[\"x\",[\"Pred\",\"Conj\",\"Cmpl\",\"Subj\",\"Objc\",\"PreC\",\"Loca\",\"PreO\",\"Rela\",\"Adju\"]],[\"top\",[228,181,133,131,95,66,26,26,24,21]]]}}},\"view\":{\"type\":\"object\",\"name\":\"CDSView\",\"id\":\"p1288\",\"attributes\":{\"filter\":{\"type\":\"object\",\"name\":\"AllIndices\",\"id\":\"p1289\"}}},\"glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"p1284\",\"attributes\":{\"x\":{\"type\":\"field\",\"field\":\"x\"},\"width\":{\"type\":\"value\",\"value\":0.6},\"top\":{\"type\":\"field\",\"field\":\"top\"},\"line_color\":{\"type\":\"value\",\"value\":\"#8c564b\"},\"fill_color\":{\"type\":\"value\",\"value\":\"#8c564b\"},\"hatch_color\":{\"type\":\"value\",\"value\":\"#8c564b\"}}},\"nonselection_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"p1285\",\"attributes\":{\"x\":{\"type\":\"field\",\"field\":\"x\"},\"width\":{\"type\":\"value\",\"value\":0.6},\"top\":{\"type\":\"field\",\"field\":\"top\"},\"line_color\":{\"type\":\"value\",\"value\":\"#8c564b\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.1},\"fill_color\":{\"type\":\"value\",\"value\":\"#8c564b\"},\"fill_alpha\":{\"type\":\"value\",\"value\":0.1},\"hatch_color\":{\"type\":\"value\",\"value\":\"#8c564b\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.1}}},\"muted_glyph\":{\"type\":\"object\",\"name\":\"VBar\",\"id\":\"p1286\",\"attributes\":{\"x\":{\"type\":\"field\",\"field\":\"x\"},\"width\":{\"type\":\"value\",\"value\":0.6},\"top\":{\"type\":\"field\",\"field\":\"top\"},\"line_color\":{\"type\":\"value\",\"value\":\"#8c564b\"},\"line_alpha\":{\"type\":\"value\",\"value\":0.2},\"fill_color\":{\"type\":\"value\",\"value\":\"#8c564b\"},\"fill_alpha\":{\"type\":\"value\",\"value\":0.2},\"hatch_color\":{\"type\":\"value\",\"value\":\"#8c564b\"},\"hatch_alpha\":{\"type\":\"value\",\"value\":0.2}}}}}],\"toolbar\":{\"type\":\"object\",\"name\":\"Toolbar\",\"id\":\"p1254\",\"attributes\":{\"tools\":[{\"type\":\"object\",\"name\":\"PanTool\",\"id\":\"p1268\"},{\"type\":\"object\",\"name\":\"WheelZoomTool\",\"id\":\"p1269\",\"attributes\":{\"renderers\":\"auto\"}},{\"type\":\"object\",\"name\":\"BoxZoomTool\",\"id\":\"p1270\",\"attributes\":{\"overlay\":{\"type\":\"object\",\"name\":\"BoxAnnotation\",\"id\":\"p1271\",\"attributes\":{\"syncable\":false,\"line_color\":\"black\",\"line_alpha\":1.0,\"line_width\":2,\"line_dash\":[4,4],\"fill_color\":\"lightgrey\",\"fill_alpha\":0.5,\"level\":\"overlay\",\"visible\":false,\"left\":{\"type\":\"number\",\"value\":\"nan\"},\"right\":{\"type\":\"number\",\"value\":\"nan\"},\"top\":{\"type\":\"number\",\"value\":\"nan\"},\"bottom\":{\"type\":\"number\",\"value\":\"nan\"},\"left_units\":\"canvas\",\"right_units\":\"canvas\",\"top_units\":\"canvas\",\"bottom_units\":\"canvas\",\"handles\":{\"type\":\"object\",\"name\":\"BoxInteractionHandles\",\"id\":\"p1277\",\"attributes\":{\"all\":{\"type\":\"object\",\"name\":\"AreaVisuals\",\"id\":\"p1276\",\"attributes\":{\"fill_color\":\"white\",\"hover_fill_color\":\"lightgray\"}}}}}}}},{\"type\":\"object\",\"name\":\"SaveTool\",\"id\":\"p1278\"},{\"type\":\"object\",\"name\":\"ResetTool\",\"id\":\"p1279\"},{\"type\":\"object\",\"name\":\"HelpTool\",\"id\":\"p1280\"}],\"active_drag\":null,\"active_scroll\":null}},\"left\":[{\"type\":\"object\",\"name\":\"LinearAxis\",\"id\":\"p1263\",\"attributes\":{\"ticker\":{\"type\":\"object\",\"name\":\"BasicTicker\",\"id\":\"p1264\",\"attributes\":{\"mantissas\":[1,2,5]}},\"formatter\":{\"type\":\"object\",\"name\":\"BasicTickFormatter\",\"id\":\"p1265\"},\"axis_label\":\"Count\",\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"p1266\"}}}],\"below\":[{\"type\":\"object\",\"name\":\"CategoricalAxis\",\"id\":\"p1258\",\"attributes\":{\"ticker\":{\"type\":\"object\",\"name\":\"CategoricalTicker\",\"id\":\"p1259\"},\"formatter\":{\"type\":\"object\",\"name\":\"CategoricalTickFormatter\",\"id\":\"p1260\"},\"axis_label\":\"Phrase Function\",\"major_label_policy\":{\"type\":\"object\",\"name\":\"AllLabels\",\"id\":\"p1261\"}}}],\"center\":[{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"p1262\",\"attributes\":{\"axis\":{\"id\":\"p1258\"}}},{\"type\":\"object\",\"name\":\"Grid\",\"id\":\"p1267\",\"attributes\":{\"dimension\":1,\"axis\":{\"id\":\"p1263\"}}},{\"type\":\"object\",\"name\":\"LabelSet\",\"id\":\"p1293\",\"attributes\":{\"level\":\"glyph\",\"source\":{\"type\":\"object\",\"name\":\"ColumnDataSource\",\"id\":\"p1290\",\"attributes\":{\"selected\":{\"type\":\"object\",\"name\":\"Selection\",\"id\":\"p1291\",\"attributes\":{\"indices\":[],\"line_indices\":[]}},\"selection_policy\":{\"type\":\"object\",\"name\":\"UnionRenderers\",\"id\":\"p1292\"},\"data\":{\"type\":\"map\",\"entries\":[[\"func\",[\"Pred\",\"Conj\",\"Cmpl\",\"Subj\",\"Objc\",\"PreC\",\"Loca\",\"PreO\",\"Rela\",\"Adju\"]],[\"count\",[228,181,133,131,95,66,26,26,24,21]],[\"pos\",[228,181,133,131,95,66,26,26,24,21]]]}}},\"x\":{\"type\":\"field\",\"field\":\"func\"},\"y\":{\"type\":\"field\",\"field\":\"pos\"},\"text\":{\"type\":\"field\",\"field\":\"count\"},\"x_offset\":{\"type\":\"value\",\"value\":-13},\"y_offset\":{\"type\":\"value\",\"value\":3}}}]}}]}};\n",
       "  const render_items = [{\"docid\":\"a90c8e02-3277-440b-b4b3-a2b2ff1c2c1e\",\"roots\":{\"p1245\":\"b388ebe0-561d-498f-9b21-74d8c47f9787\"},\"root_ids\":[\"p1245\"]}];\n",
       "  void root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n",
       "  }\n",
       "  if (root.Bokeh !== undefined) {\n",
       "    embed_document(root);\n",
       "  } else {\n",
       "    let attempts = 0;\n",
       "    const timer = setInterval(function(root) {\n",
       "      if (root.Bokeh !== undefined) {\n",
       "        clearInterval(timer);\n",
       "        embed_document(root);\n",
       "      } else {\n",
       "        attempts++;\n",
       "        if (attempts > 100) {\n",
       "          clearInterval(timer);\n",
       "          console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n",
       "        }\n",
       "      }\n",
       "    }, 10, root)\n",
       "  }\n",
       "})(window);"
      ],
      "application/vnd.bokehjs_exec.v0+json": ""
     },
     "metadata": {
      "application/vnd.bokehjs_exec.v0+json": {
       "id": "p1245"
      }
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "from bokeh.layouts import column\n",
    "from bokeh.models import Range1d, LabelSet, ColumnDataSource\n",
    "from bokeh.plotting import figure, output_file, show\n",
    "\n",
    "# Prepare data for phrase function chart\n",
    "func_labels = [func for func, cnt in common_funcs]\n",
    "func_counts = [cnt for func, cnt in common_funcs]\n",
    "\n",
    "# Compute maximum count and add a little padding (e.g., 10%)\n",
    "max_count = max(func_counts)\n",
    "y_end = max_count * 1.1\n",
    "\n",
    "# Create the figure with a fixed y_range\n",
    "p_funcs = figure(x_range=func_labels, height=300, width=400,\n",
    "                 title=f\"Parasha {parasha_num}: {parasha_name_trans} - Phrase function distribution\",\n",
    "                 x_axis_label=\"Phrase Function\", y_axis_label=\"Count\",\n",
    "                 toolbar_location='right',\n",
    "                 y_range=Range1d(start=0, end=y_end))\n",
    "\n",
    "p_funcs.vbar(x=func_labels, top=func_counts, width=0.6, color=\"#8c564b\")\n",
    "\n",
    "# Lock the y_range to prevent any zooming/panning adjustments\n",
    "p_funcs.y_range.bounds = (0, y_end)\n",
    "\n",
    "# If a toolbar exists, deactivate any active drag or scroll tools\n",
    "if p_funcs.toolbar:\n",
    "    p_funcs.toolbar.active_drag = None\n",
    "    p_funcs.toolbar.active_scroll = None\n",
    "\n",
    "# Add labels above bars (optional)\n",
    "func_source = ColumnDataSource(data={'func': func_labels, 'count': func_counts, 'pos': func_counts})\n",
    "labels = LabelSet(x='func', y='pos', text='count', level='glyph', x_offset=-13, y_offset=3, source=func_source)\n",
    "p_funcs.add_layout(labels)\n",
    "\n",
    "show(p_funcs)\n",
    "\n",
    "# note: save image as 'phrase_function_distribution.png'"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f39a9e96-1486-4bf8-8fde-4c4ae2f2cf77",
   "metadata": {},
   "source": [
    "# 5 - References <a class=\"anchor\" id=\"bullet5\"></a>\n",
    "\n",
    "For more details on the BHSA dataset and features, see the [ETCBC BHSA documentation](https://etcbc.github.io/bhsa/).\n",
    "\n",
    "The BHSaddons repository  ([GitHub - tonyjurg/BHSaddons](https://tonyjurg.github.io/BHSaddons/)) provides a list of the parasha specific features we use.\n",
    "\n",
    "Additionally, the BHSA feature documentation covers morphological and syntactic features, e.g.:\n",
    " - the `vt` codes for verb tense ([Vt - BHSA](https://etcbc.github.io/bhsa/features/vt/)),\n",
    " - the `domain` clause text-type codes ([Domain - BHSA](https://etcbc.github.io/bhsa/features/domain/)),\n",
    " - the `function` codes for phrase roles ([Function - BHSA](https://etcbc.github.io/bhsa/features/function/)).\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0475f4a9-5e70-40f5-81e7-c04ed8ccdca3",
   "metadata": {},
   "source": [
    "# 6 - Notebook version details<a class=\"anchor\" id=\"bullet6\"></a>\n",
    "##### [Back to ToC](#TOC)\n",
    "\n",
    "<div style=\"float: left;\">\n",
    "  <table>\n",
    "    <tr>\n",
    "      <td><strong>Author</strong></td>\n",
    "      <td>Tony Jurg</td>\n",
    "    </tr>\n",
    "    <tr>\n",
    "      <td><strong>Version</strong></td>\n",
    "      <td>1.0</td>\n",
    "    </tr>\n",
    "    <tr>\n",
    "      <td><strong>Date</strong></td>\n",
    "      <td>26 March 2025</td>\n",
    "    </tr>\n",
    "  </table>\n",
    "</div>"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "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.12.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}