<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.3.4">Jekyll</generator><link href="https://oriolcolomefont.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://oriolcolomefont.github.io/" rel="alternate" type="text/html" /><updated>2026-06-09T15:41:07+00:00</updated><id>https://oriolcolomefont.github.io/feed.xml</id><title type="html">Oriol Colomé Font</title><subtitle>Music tech generalist: all things music. Growth lead &amp; product owner at My Sheet Music Transcriptions. Bridging the gap between artistic vision and technical implementation.</subtitle><author><name>Oriol Colomé Font</name></author><entry><title type="html">Tech elites and music creativity</title><link href="https://oriolcolomefont.github.io/blog/tech-elites-music-creativity/" rel="alternate" type="text/html" title="Tech elites and music creativity" /><published>2025-11-06T00:00:00+00:00</published><updated>2025-11-06T00:00:00+00:00</updated><id>https://oriolcolomefont.github.io/blog/tech-elites-music-creativity</id><content type="html" xml:base="https://oriolcolomefont.github.io/blog/tech-elites-music-creativity/"><![CDATA[<p>Art and culture emerge from the complexities of the human experience.  I believe we must promote and protect them, because no one —absolutely no one — from the tech elite will lift a finger for it: AI is marketed as empowering and democratizing creativity, yet this rhetoric can mask underlying market control and stimulate a false consciousness. The entertainment industry is undergoing a significant transformation driven by advances in artificial intelligence, which presents fundamental challenges to human culture and creativity. Tech elites and VC-backed initiatives are aggressively pushing this narrative into the industry, framing “AI”—that omnipotent, omnipresent, all-seeing big brother algorithm with more computing power than curiosity, equal parts digital oracle and algorithmic helicopter parent—as an inevitable and beneficial force.</p>

<p>Unlike AI’s ability to replicate and optimize processes, human beings possess a unique capacity for symbolism, allowing us to communicate and construct shared meanings that define our cultural identity. However, as AI increasingly plays a role in content creation and ideation, there is a growing concern that it may dilute human artistic expression.</p>

<p>One key concern is the evolving relationship between AI and creative thought. As automated processes take over traditionally human-led domains, we risk shifting creativity into a digital infosphere where AI-driven systems manage and control symbolic content. Without thoughtful governance, this shift could challenge the very development of human intelligence.</p>

<p>Symbolic culture reflects our shared identity and is the foundation of human dignity. The unique, irreplaceable essence of artistic and intellectual creation must be safeguarded. The unpredictability, imperfection, and organic evolution of creativity make cultural production truly valuable. If AI merely replaces human creativity, rather than enhancing it, we risk losing the richness and depth that define artistic expression.</p>

<p>The responsible development of AI must focus on augmenting, not substituting, human creativity. This requires a deliberate approach to align AI with cultural and artistic objectives. Without such a framework, we risk the erosion of creative communities and the broader cultural ecosystem, as economic and efficiency-driven incentives often fail to prioritize the preservation of artistic and intellectual values. These incentives are largely shaped by tech elites and VC-backed companies that prioritize market control and scalability over cultural preservation.</p>

<p>Don’t get me wrong: I am an optimist, and I believe the current momentum in differentiable programming can be a force for good. My coding journey has soared as it has been supercharged by LLM-powered tools and agentic assistants. However, there is no single correct line of thought that should be followed—least of all the opportunistic initiatives that seek to capitalize on this momentum without genuine commitment to cultural and artistic values. I believe that “no control, no revolution”, as we believe that fine-grained interactivity is the only way forward.</p>

<p>Addressing this challenge requires more than principles and declarations—it demands action: governmental organizations should play a central role in ensuring that AI does not monopolize cultural capital for purely technological or commercial interests. This is especially critical as tech elites and VC-backed initiatives continue to enforce their vision of AI-driven creativity into the industry. Safeguarding public access to art and cultural heritage must be a global priority, ensuring that innovation remains a force for creative empowerment rather than displacement.</p>

<p>By portraying the so-called “AI breakthrough” as a friendly, inevitable partner in music’s evolution, companies shape how communities discuss creativity, even as users still reclaim agency. This narrative is systematically enforced by tech elites and VC-backed initiatives that have the resources and platform to dominate industry discourse. By protecting the complexities of the human experience, we can create a future where human and artificial intelligence coexist in a way that enriches rather than diminishes cultural expression: no technological convenience should ever outweigh all the humanity, stories, and history being stripped away from our lives to make things faster or cheaper — we risk forgetting who we are.</p>

<p>This means building and shipping with human meaning in mind, not just efficiency. Effort, seams, and time are not inherently bad; they gain value when infused with intention and purpose. In human-centered design, the goal shouldn’t be to eliminate effort, but to transform it into something meaningful. We should avoid defaulting to effortlessness, seamlessness, or productivity as design objectives. Instead, we should ask ourselves: what meaningful experience does this enable? The difference between saving time and depriving someone of a fulfilling experience lies in how we define meaning, not the speed or smoothness of the product.</p>

<hr />

<p><em>This post reflects my personal observations and experiences working at the intersection of music technology and the industry. The views expressed are my own and do not necessarily represent those of my current or past employers.</em></p>

<p><strong>Tags</strong>: #MusicIndustry #Technology #Creativity #Innovation #Culture #MusicTech</p>]]></content><author><name>Oriol Colomé Font</name></author><category term="Music Technology" /><category term="Industry Insights" /><category term="music industry" /><category term="technology" /><category term="creativity" /><category term="innovation" /><category term="culture" /><category term="AI" /><category term="artificial intelligence" /><summary type="html"><![CDATA[A critical examination of how tech elites and VC-backed initiatives are reshaping music creation through AI, arguing that we must protect human artistic expression from commodification while advocating for AI that augments rather than replaces the irreplaceable complexities of human creativity.]]></summary></entry><entry><title type="html">Analyzing Musical Scores and Identifying Motifs: A Computational Approach</title><link href="https://oriolcolomefont.github.io/blog/musical-score-motif-analysis/" rel="alternate" type="text/html" title="Analyzing Musical Scores and Identifying Motifs: A Computational Approach" /><published>2025-01-11T00:00:00+00:00</published><updated>2025-01-11T00:00:00+00:00</updated><id>https://oriolcolomefont.github.io/blog/musical-score-motif-analysis</id><content type="html" xml:base="https://oriolcolomefont.github.io/blog/musical-score-motif-analysis/"><![CDATA[<h2 id="introduction">Introduction</h2>

<p>Musical motifs—short, recurring melodic patterns—are fundamental building blocks of musical composition. From classical sonatas to traditional folk music, motifs serve as the DNA of musical works, creating coherence, development, and narrative structure. In computational musicology, identifying and analyzing these motifs programmatically opens up new possibilities for understanding musical structure, style, and evolution.</p>

<p>In this post, we’ll explore a comprehensive approach to analyzing musical scores and identifying motifs using Python and the <code class="language-plaintext highlighter-rouge">music21</code> library. This methodology forms the foundation of research into Arab-Andalusian music patterns, but the techniques are broadly applicable to any musical tradition.</p>

<h2 id="understanding-motifs-in-music">Understanding Motifs in Music</h2>

<p>Before diving into the code, let’s clarify what we mean by “motifs” in a computational context:</p>

<ul>
  <li><strong>Melodic Motifs</strong>: Sequences of pitches that recur throughout a piece</li>
  <li><strong>Rhythmic Motifs</strong>: Patterns of note durations</li>
  <li><strong>Contour Motifs</strong>: Patterns of pitch direction (up, down, same)</li>
</ul>

<p>For this analysis, we focus on <strong>melodic motifs</strong>—sequences of pitches that appear multiple times, potentially in different octaves or with slight variations. These patterns can reveal:</p>
<ul>
  <li>Structural organization of a piece</li>
  <li>Thematic development and variation</li>
  <li>Stylistic characteristics of a musical tradition</li>
  <li>Relationships between different sections or movements</li>
</ul>

<h2 id="the-analysis-pipeline">The Analysis Pipeline</h2>

<p>Our approach follows a clear pipeline:</p>

<ol>
  <li><strong>Load the Score</strong>: Parse MusicXML files into a structured format</li>
  <li><strong>Extract the Melody</strong>: Isolate the melodic line from the full score</li>
  <li><strong>Identify Motifs</strong>: Find recurring patterns of specified lengths</li>
  <li><strong>Visualize Results</strong>: Create plots showing motif occurrences</li>
</ol>

<p>Let’s examine each step in detail.</p>

<h2 id="function-1-loading-musical-scores">Function 1: Loading Musical Scores</h2>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">load_score</span><span class="p">(</span><span class="n">file_path</span><span class="p">:</span> <span class="n">Path</span> <span class="o">|</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">music21</span><span class="p">.</span><span class="n">stream</span><span class="p">.</span><span class="n">Score</span><span class="p">:</span>
    <span class="n">logger</span><span class="p">.</span><span class="nf">info</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="s">Loading score from </span><span class="si">{</span><span class="n">file_path</span><span class="si">}</span><span class="sh">"</span><span class="p">)</span>
    <span class="k">try</span><span class="p">:</span>
        <span class="n">score</span> <span class="o">=</span> <span class="n">music21</span><span class="p">.</span><span class="n">converter</span><span class="p">.</span><span class="nf">parse</span><span class="p">(</span><span class="nf">str</span><span class="p">(</span><span class="n">file_path</span><span class="p">))</span>
        <span class="n">logger</span><span class="p">.</span><span class="nf">info</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="s">Successfully loaded score with </span><span class="si">{</span><span class="nf">len</span><span class="p">(</span><span class="n">score</span><span class="p">.</span><span class="n">parts</span><span class="p">)</span><span class="si">}</span><span class="s"> parts</span><span class="sh">"</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">score</span>
    <span class="k">except</span> <span class="nb">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
        <span class="n">logger</span><span class="p">.</span><span class="nf">error</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="s">Failed to load score: </span><span class="si">{</span><span class="nf">str</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="si">}</span><span class="sh">"</span><span class="p">)</span>
        <span class="k">raise</span>
</code></pre></div></div>

<h3 id="what-this-function-does">What This Function Does</h3>

<p>The <code class="language-plaintext highlighter-rouge">load_score</code> function is our entry point into the musical score. It takes a file path (either a <code class="language-plaintext highlighter-rouge">Path</code> object or string) and returns a <code class="language-plaintext highlighter-rouge">music21.stream.Score</code> object—a rich data structure representing the entire musical work.</p>

<h3 id="key-concepts">Key Concepts</h3>

<p><strong>MusicXML</strong> is a standard format for representing musical notation in XML. It’s widely supported by music notation software (Finale, Sibelius, MuseScore) and provides a structured way to encode:</p>
<ul>
  <li>Notes and their pitches</li>
  <li>Rhythmic values</li>
  <li>Dynamics and articulations</li>
  <li>Structural elements (measures, parts, etc.)</li>
</ul>

<p><strong>music21</strong> is a powerful Python toolkit for computer-aided musicology. It can parse MusicXML, MIDI, ABC notation, and other formats, providing a unified interface for musical analysis.</p>

<h3 id="why-logging-matters">Why Logging Matters</h3>

<p>Notice the logging statements throughout the function. In computational musicology workflows, you might process hundreds of scores. Logging helps you:</p>
<ul>
  <li>Track progress through large datasets</li>
  <li>Debug issues with specific files</li>
  <li>Understand the structure of loaded scores (number of parts, measures, etc.)</li>
</ul>

<h3 id="error-handling">Error Handling</h3>

<p>The function uses try-except blocks to handle common issues:</p>
<ul>
  <li><strong>FileNotFoundError</strong>: The file doesn’t exist at the specified path</li>
  <li><strong>Music21Exception</strong>: The file exists but isn’t valid MusicXML</li>
  <li><strong>Parsing errors</strong>: The file is corrupted or in an unexpected format</li>
</ul>

<p>Proper error handling is crucial when working with real-world data, which may be inconsistent or incomplete.</p>

<h2 id="function-2-extracting-the-melody">Function 2: Extracting the Melody</h2>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">extract_melody</span><span class="p">(</span><span class="n">score</span><span class="p">:</span> <span class="n">music21</span><span class="p">.</span><span class="n">stream</span><span class="p">.</span><span class="n">Score</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">music21</span><span class="p">.</span><span class="n">stream</span><span class="p">.</span><span class="n">Part</span><span class="p">:</span>
    <span class="n">logger</span><span class="p">.</span><span class="nf">info</span><span class="p">(</span><span class="sh">"</span><span class="s">Extracting melody from score</span><span class="sh">"</span><span class="p">)</span>
    <span class="k">try</span><span class="p">:</span>
        <span class="n">melody_part</span> <span class="o">=</span> <span class="n">score</span><span class="p">.</span><span class="n">parts</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
        <span class="n">n_notes</span> <span class="o">=</span> <span class="nf">len</span><span class="p">(</span><span class="n">melody_part</span><span class="p">.</span><span class="nf">recurse</span><span class="p">().</span><span class="n">notes</span><span class="p">)</span>
        <span class="n">logger</span><span class="p">.</span><span class="nf">info</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="s">Successfully extracted melody with </span><span class="si">{</span><span class="n">n_notes</span><span class="si">}</span><span class="s"> notes</span><span class="sh">"</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">melody_part</span>
    <span class="k">except</span> <span class="nb">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
        <span class="n">logger</span><span class="p">.</span><span class="nf">error</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="s">Failed to extract melody: </span><span class="si">{</span><span class="nf">str</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="si">}</span><span class="sh">"</span><span class="p">)</span>
        <span class="k">raise</span>
</code></pre></div></div>

<h3 id="understanding-musical-structure">Understanding Musical Structure</h3>

<p>A musical score typically contains multiple <strong>parts</strong> (instruments or voices). For motif analysis, we often focus on a single melodic line—usually the first part, which commonly contains the main melody in many musical traditions.</p>

<h3 id="the-recurse-method">The <code class="language-plaintext highlighter-rouge">recurse()</code> Method</h3>

<p>The <code class="language-plaintext highlighter-rouge">recurse()</code> method is a powerful feature of music21 that allows you to traverse the hierarchical structure of a musical score:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Score
  └── Part (Voice/Instrument)
      └── Measure
          └── Note/Rest
</code></pre></div></div>

<p>By calling <code class="language-plaintext highlighter-rouge">melody_part.recurse().notes</code>, we flatten this hierarchy and get all notes in sequence, regardless of which measure they’re in. This is essential for motif identification, which operates on linear sequences of pitches.</p>

<h3 id="why-extract-just-the-melody">Why Extract Just the Melody?</h3>

<p>While a full score contains rich information, focusing on a single melodic line simplifies motif analysis:</p>
<ul>
  <li><strong>Reduces complexity</strong>: One-dimensional pitch sequences are easier to analyze</li>
  <li><strong>Focuses on melodic patterns</strong>: Many musical traditions emphasize melodic development</li>
  <li><strong>Enables comparison</strong>: Single-line analysis allows direct comparison across pieces</li>
</ul>

<p>For more advanced analysis, you could extend this to:</p>
<ul>
  <li>Analyze multiple parts simultaneously</li>
  <li>Identify harmonic motifs (chord progressions)</li>
  <li>Track motifs across different voices</li>
</ul>

<h2 id="function-3-identifying-motifs">Function 3: Identifying Motifs</h2>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">identify_motifs</span><span class="p">(</span>
    <span class="n">melody</span><span class="p">:</span> <span class="n">music21</span><span class="p">.</span><span class="n">stream</span><span class="p">.</span><span class="n">Part</span><span class="p">,</span> <span class="n">min_length</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">max_length</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">8</span>
<span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">List</span><span class="p">[</span><span class="n">music21</span><span class="p">.</span><span class="n">note</span><span class="p">.</span><span class="n">Note</span><span class="p">]]:</span>
    <span class="k">if</span> <span class="n">min_length</span> <span class="o">&gt;</span> <span class="n">max_length</span><span class="p">:</span>
        <span class="k">raise</span> <span class="nc">ValueError</span><span class="p">(</span><span class="sh">"</span><span class="s">min_length must be less than or equal to max_length</span><span class="sh">"</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">min_length</span> <span class="o">&lt;</span> <span class="mi">1</span> <span class="ow">or</span> <span class="n">max_length</span> <span class="o">&lt;</span> <span class="mi">1</span><span class="p">:</span>
        <span class="k">raise</span> <span class="nc">ValueError</span><span class="p">(</span><span class="sh">"</span><span class="s">Length parameters must be positive</span><span class="sh">"</span><span class="p">)</span>

    <span class="n">logger</span><span class="p">.</span><span class="nf">info</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="s">Identifying motifs (length </span><span class="si">{</span><span class="n">min_length</span><span class="si">}</span><span class="s">-</span><span class="si">{</span><span class="n">max_length</span><span class="si">}</span><span class="s">)</span><span class="sh">"</span><span class="p">)</span>
    <span class="k">try</span><span class="p">:</span>
        <span class="n">notes</span> <span class="o">=</span> <span class="p">[</span><span class="n">n</span> <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">melody</span><span class="p">.</span><span class="nf">recurse</span><span class="p">().</span><span class="n">notes</span><span class="p">]</span>
        <span class="n">motifs</span> <span class="o">=</span> <span class="p">[]</span>

        <span class="k">for</span> <span class="n">length</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">min_length</span><span class="p">,</span> <span class="n">max_length</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
            <span class="n">logger</span><span class="p">.</span><span class="nf">debug</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="s">Processing motifs of length </span><span class="si">{</span><span class="n">length</span><span class="si">}</span><span class="sh">"</span><span class="p">)</span>
            <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="nf">len</span><span class="p">(</span><span class="n">notes</span><span class="p">)</span> <span class="o">-</span> <span class="n">length</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
                <span class="n">motif</span> <span class="o">=</span> <span class="n">notes</span><span class="p">[</span><span class="n">i</span> <span class="p">:</span> <span class="n">i</span> <span class="o">+</span> <span class="n">length</span><span class="p">]</span>
                <span class="n">motifs</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="n">motif</span><span class="p">)</span>

        <span class="n">logger</span><span class="p">.</span><span class="nf">info</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="s">Found </span><span class="si">{</span><span class="nf">len</span><span class="p">(</span><span class="n">motifs</span><span class="p">)</span><span class="si">}</span><span class="s"> potential motifs</span><span class="sh">"</span><span class="p">)</span>
        <span class="k">return</span> <span class="n">motifs</span>
    <span class="k">except</span> <span class="nb">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
        <span class="n">logger</span><span class="p">.</span><span class="nf">error</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="s">Failed to identify motifs: </span><span class="si">{</span><span class="nf">str</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="si">}</span><span class="sh">"</span><span class="p">)</span>
        <span class="k">raise</span>
</code></pre></div></div>

<h3 id="the-sliding-window-approach">The Sliding Window Approach</h3>

<p>This function uses a <strong>sliding window</strong> technique to extract all possible sequences of notes within the specified length range. For a melody with notes <code class="language-plaintext highlighter-rouge">[A, B, C, D, E]</code> and <code class="language-plaintext highlighter-rouge">min_length=3, max_length=4</code>, it would extract:</p>

<p><strong>Length 3:</strong></p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">[A, B, C]</code></li>
  <li><code class="language-plaintext highlighter-rouge">[B, C, D]</code></li>
  <li><code class="language-plaintext highlighter-rouge">[C, D, E]</code></li>
</ul>

<p><strong>Length 4:</strong></p>
<ul>
  <li><code class="language-plaintext highlighter-rouge">[A, B, C, D]</code></li>
  <li><code class="language-plaintext highlighter-rouge">[B, C, D, E]</code></li>
</ul>

<h3 id="why-multiple-lengths">Why Multiple Lengths?</h3>

<p>Musical motifs can vary in length:</p>
<ul>
  <li><strong>Short motifs (3-4 notes)</strong>: Often serve as building blocks, appearing frequently</li>
  <li><strong>Medium motifs (5-6 notes)</strong>: May represent thematic material</li>
  <li><strong>Long motifs (7-8+ notes)</strong>: Could be complete phrases or themes</li>
</ul>

<p>By searching across a range, we capture motifs at different structural levels.</p>

<h3 id="current-limitations">Current Limitations</h3>

<p>The current implementation extracts <strong>all possible sequences</strong> but doesn’t yet:</p>
<ul>
  <li><strong>Filter duplicates</strong>: The same motif appearing multiple times is stored separately</li>
  <li><strong>Normalize octaves</strong>: A motif in different octaves is treated as different</li>
  <li><strong>Handle transpositions</strong>: A motif transposed to a different key is treated as different</li>
</ul>

<p>These are important considerations for real-world analysis. For example, in Arab-Andalusian music research, we might want to:</p>
<ul>
  <li>Count occurrences of the same pitch-class sequence regardless of octave</li>
  <li>Identify motifs that appear in different keys (transpositional equivalence)</li>
  <li>Group similar but not identical motifs (allowing for slight variations)</li>
</ul>

<h3 id="extending-the-function">Extending the Function</h3>

<p>Here’s how you might extend this to find <strong>unique motifs</strong> and count their occurrences:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">identify_unique_motifs</span><span class="p">(</span>
    <span class="n">melody</span><span class="p">:</span> <span class="n">music21</span><span class="p">.</span><span class="n">stream</span><span class="p">.</span><span class="n">Part</span><span class="p">,</span> 
    <span class="n">min_length</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> 
    <span class="n">max_length</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">8</span><span class="p">,</span>
    <span class="n">normalize_octave</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="bp">True</span>
<span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">dict</span><span class="p">:</span>
    <span class="n">notes</span> <span class="o">=</span> <span class="p">[</span><span class="n">n</span> <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">melody</span><span class="p">.</span><span class="nf">recurse</span><span class="p">().</span><span class="n">notes</span><span class="p">]</span>
    <span class="n">motif_counts</span> <span class="o">=</span> <span class="nf">defaultdict</span><span class="p">(</span><span class="nb">int</span><span class="p">)</span>
    
    <span class="k">for</span> <span class="n">length</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">min_length</span><span class="p">,</span> <span class="n">max_length</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
        <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="nf">len</span><span class="p">(</span><span class="n">notes</span><span class="p">)</span> <span class="o">-</span> <span class="n">length</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
            <span class="n">motif_notes</span> <span class="o">=</span> <span class="n">notes</span><span class="p">[</span><span class="n">i</span> <span class="p">:</span> <span class="n">i</span> <span class="o">+</span> <span class="n">length</span><span class="p">]</span>
            
            <span class="k">if</span> <span class="n">normalize_octave</span><span class="p">:</span>
                <span class="c1"># Use pitch class names (C, D, E, etc.) instead of full pitch names
</span>                <span class="n">motif</span> <span class="o">=</span> <span class="nf">tuple</span><span class="p">(</span><span class="n">note</span><span class="p">.</span><span class="n">pitch</span><span class="p">.</span><span class="n">name</span> <span class="k">for</span> <span class="n">note</span> <span class="ow">in</span> <span class="n">motif_notes</span><span class="p">)</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="c1"># Use full pitch names (C4, D5, etc.)
</span>                <span class="n">motif</span> <span class="o">=</span> <span class="nf">tuple</span><span class="p">(</span><span class="n">note</span><span class="p">.</span><span class="n">pitch</span><span class="p">.</span><span class="n">nameWithOctave</span> <span class="k">for</span> <span class="n">note</span> <span class="ow">in</span> <span class="n">motif_notes</span><span class="p">)</span>
            
            <span class="n">motif_counts</span><span class="p">[</span><span class="n">motif</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span>
    
    <span class="k">return</span> <span class="nf">dict</span><span class="p">(</span><span class="n">motif_counts</span><span class="p">)</span>
</code></pre></div></div>

<h2 id="function-4-visualizing-motif-occurrences">Function 4: Visualizing Motif Occurrences</h2>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">plot_motif_occurrences</span><span class="p">(</span>
    <span class="n">score</span><span class="p">:</span> <span class="n">music21</span><span class="p">.</span><span class="n">stream</span><span class="p">.</span><span class="n">Score</span><span class="p">,</span>
    <span class="n">motifs</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">List</span><span class="p">[</span><span class="n">music21</span><span class="p">.</span><span class="n">note</span><span class="p">.</span><span class="n">Note</span><span class="p">]],</span>
    <span class="n">output_path</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span>
<span class="p">)</span> <span class="o">-&gt;</span> <span class="bp">None</span><span class="p">:</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">motifs</span><span class="p">:</span>
        <span class="k">raise</span> <span class="nc">ValueError</span><span class="p">(</span><span class="sh">"</span><span class="s">Motifs list cannot be empty</span><span class="sh">"</span><span class="p">)</span>

    <span class="n">logger</span><span class="p">.</span><span class="nf">info</span><span class="p">(</span><span class="sh">"</span><span class="s">Plotting motif occurrences</span><span class="sh">"</span><span class="p">)</span>
    <span class="k">try</span><span class="p">:</span>
        <span class="n">plt</span><span class="p">.</span><span class="nf">figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">12</span><span class="p">,</span> <span class="mi">6</span><span class="p">))</span>
        <span class="c1"># Implementation details would depend on how you want to visualize the motifs
</span>        <span class="c1"># This is a placeholder for the actual visualization logic
</span>
        <span class="k">if</span> <span class="n">output_path</span><span class="p">:</span>
            <span class="n">plt</span><span class="p">.</span><span class="nf">savefig</span><span class="p">(</span><span class="n">output_path</span><span class="p">)</span>
            <span class="n">logger</span><span class="p">.</span><span class="nf">info</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="s">Saved plot to </span><span class="si">{</span><span class="n">output_path</span><span class="si">}</span><span class="sh">"</span><span class="p">)</span>
        <span class="n">plt</span><span class="p">.</span><span class="nf">close</span><span class="p">()</span>
    <span class="k">except</span> <span class="nb">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
        <span class="n">logger</span><span class="p">.</span><span class="nf">error</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="s">Failed to plot motif occurrences: </span><span class="si">{</span><span class="nf">str</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="si">}</span><span class="sh">"</span><span class="p">)</span>
        <span class="k">raise</span>
</code></pre></div></div>

<h3 id="visualization-strategies">Visualization Strategies</h3>

<p>While the function is a placeholder, here are effective visualization approaches for motif analysis:</p>

<h4 id="1-temporal-distribution-plot">1. <strong>Temporal Distribution Plot</strong></h4>
<p>Show where motifs appear across the timeline of the piece:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">plot_motif_timeline</span><span class="p">(</span><span class="n">score</span><span class="p">,</span> <span class="n">motif_counts</span><span class="p">,</span> <span class="n">motif_of_interest</span><span class="p">):</span>
    <span class="sh">"""</span><span class="s">Plot when a specific motif appears in the score.</span><span class="sh">"""</span>
    <span class="n">measures</span> <span class="o">=</span> <span class="n">score</span><span class="p">.</span><span class="n">parts</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nf">getElementsByClass</span><span class="p">(</span><span class="sh">'</span><span class="s">Measure</span><span class="sh">'</span><span class="p">)</span>
    <span class="n">occurrences</span> <span class="o">=</span> <span class="p">[]</span>
    
    <span class="k">for</span> <span class="n">measure_num</span><span class="p">,</span> <span class="n">measure</span> <span class="ow">in</span> <span class="nf">enumerate</span><span class="p">(</span><span class="n">measures</span><span class="p">):</span>
        <span class="c1"># Count occurrences of motif in this measure
</span>        <span class="n">count</span> <span class="o">=</span> <span class="nf">count_motif_in_measure</span><span class="p">(</span><span class="n">measure</span><span class="p">,</span> <span class="n">motif_of_interest</span><span class="p">)</span>
        <span class="n">occurrences</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="n">count</span><span class="p">)</span>
    
    <span class="n">plt</span><span class="p">.</span><span class="nf">figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">14</span><span class="p">,</span> <span class="mi">4</span><span class="p">))</span>
    <span class="n">plt</span><span class="p">.</span><span class="nf">bar</span><span class="p">(</span><span class="nf">range</span><span class="p">(</span><span class="nf">len</span><span class="p">(</span><span class="n">occurrences</span><span class="p">)),</span> <span class="n">occurrences</span><span class="p">)</span>
    <span class="n">plt</span><span class="p">.</span><span class="nf">xlabel</span><span class="p">(</span><span class="sh">'</span><span class="s">Measure Number</span><span class="sh">'</span><span class="p">)</span>
    <span class="n">plt</span><span class="p">.</span><span class="nf">ylabel</span><span class="p">(</span><span class="sh">'</span><span class="s">Motif Occurrences</span><span class="sh">'</span><span class="p">)</span>
    <span class="n">plt</span><span class="p">.</span><span class="nf">title</span><span class="p">(</span><span class="sa">f</span><span class="sh">'</span><span class="s">Occurrences of </span><span class="si">{</span><span class="n">motif_of_interest</span><span class="si">}</span><span class="s"> across the score</span><span class="sh">'</span><span class="p">)</span>
    <span class="n">plt</span><span class="p">.</span><span class="nf">show</span><span class="p">()</span>
</code></pre></div></div>

<h4 id="2-heatmap-of-all-motifs">2. <strong>Heatmap of All Motifs</strong></h4>
<p>Visualize the distribution of multiple motifs simultaneously:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">plot_motif_heatmap</span><span class="p">(</span><span class="n">score</span><span class="p">,</span> <span class="n">motif_counts</span><span class="p">):</span>
    <span class="sh">"""</span><span class="s">Create a heatmap showing all motifs across measures.</span><span class="sh">"""</span>
    <span class="n">measures</span> <span class="o">=</span> <span class="n">score</span><span class="p">.</span><span class="n">parts</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nf">getElementsByClass</span><span class="p">(</span><span class="sh">'</span><span class="s">Measure</span><span class="sh">'</span><span class="p">)</span>
    <span class="n">unique_motifs</span> <span class="o">=</span> <span class="nf">list</span><span class="p">(</span><span class="n">motif_counts</span><span class="p">.</span><span class="nf">keys</span><span class="p">())[:</span><span class="mi">10</span><span class="p">]</span>  <span class="c1"># Top 10 motifs
</span>    
    <span class="c1"># Create matrix: rows = motifs, columns = measures
</span>    <span class="n">matrix</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="nf">zeros</span><span class="p">((</span><span class="nf">len</span><span class="p">(</span><span class="n">unique_motifs</span><span class="p">),</span> <span class="nf">len</span><span class="p">(</span><span class="n">measures</span><span class="p">)))</span>
    
    <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">motif</span> <span class="ow">in</span> <span class="nf">enumerate</span><span class="p">(</span><span class="n">unique_motifs</span><span class="p">):</span>
        <span class="k">for</span> <span class="n">j</span><span class="p">,</span> <span class="n">measure</span> <span class="ow">in</span> <span class="nf">enumerate</span><span class="p">(</span><span class="n">measures</span><span class="p">):</span>
            <span class="n">matrix</span><span class="p">[</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="nf">count_motif_in_measure</span><span class="p">(</span><span class="n">measure</span><span class="p">,</span> <span class="n">motif</span><span class="p">)</span>
    
    <span class="n">plt</span><span class="p">.</span><span class="nf">figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">16</span><span class="p">,</span> <span class="mi">8</span><span class="p">))</span>
    <span class="n">sns</span><span class="p">.</span><span class="nf">heatmap</span><span class="p">(</span><span class="n">matrix</span><span class="p">,</span> 
                <span class="n">xticklabels</span><span class="o">=</span><span class="nf">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="nf">len</span><span class="p">(</span><span class="n">measures</span><span class="p">)</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span> <span class="mi">20</span><span class="p">),</span>
                <span class="n">yticklabels</span><span class="o">=</span><span class="p">[</span><span class="nf">str</span><span class="p">(</span><span class="n">m</span><span class="p">)</span> <span class="k">for</span> <span class="n">m</span> <span class="ow">in</span> <span class="n">unique_motifs</span><span class="p">],</span>
                <span class="n">cmap</span><span class="o">=</span><span class="sh">'</span><span class="s">YlOrRd</span><span class="sh">'</span><span class="p">)</span>
    <span class="n">plt</span><span class="p">.</span><span class="nf">xlabel</span><span class="p">(</span><span class="sh">'</span><span class="s">Measure Number</span><span class="sh">'</span><span class="p">)</span>
    <span class="n">plt</span><span class="p">.</span><span class="nf">ylabel</span><span class="p">(</span><span class="sh">'</span><span class="s">Motif</span><span class="sh">'</span><span class="p">)</span>
    <span class="n">plt</span><span class="p">.</span><span class="nf">title</span><span class="p">(</span><span class="sh">'</span><span class="s">Motif Distribution Across Score</span><span class="sh">'</span><span class="p">)</span>
    <span class="n">plt</span><span class="p">.</span><span class="nf">tight_layout</span><span class="p">()</span>
    <span class="n">plt</span><span class="p">.</span><span class="nf">show</span><span class="p">()</span>
</code></pre></div></div>

<h4 id="3-motif-frequency-bar-chart">3. <strong>Motif Frequency Bar Chart</strong></h4>
<p>Show which motifs appear most frequently:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">plot_motif_frequencies</span><span class="p">(</span><span class="n">motif_counts</span><span class="p">,</span> <span class="n">top_n</span><span class="o">=</span><span class="mi">15</span><span class="p">):</span>
    <span class="sh">"""</span><span class="s">Plot the most frequent motifs.</span><span class="sh">"""</span>
    <span class="n">sorted_motifs</span> <span class="o">=</span> <span class="nf">sorted</span><span class="p">(</span><span class="n">motif_counts</span><span class="p">.</span><span class="nf">items</span><span class="p">(),</span> 
                          <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> 
                          <span class="n">reverse</span><span class="o">=</span><span class="bp">True</span><span class="p">)[:</span><span class="n">top_n</span><span class="p">]</span>
    
    <span class="n">motifs</span><span class="p">,</span> <span class="n">counts</span> <span class="o">=</span> <span class="nf">zip</span><span class="p">(</span><span class="o">*</span><span class="n">sorted_motifs</span><span class="p">)</span>
    
    <span class="n">plt</span><span class="p">.</span><span class="nf">figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">12</span><span class="p">,</span> <span class="mi">6</span><span class="p">))</span>
    <span class="n">plt</span><span class="p">.</span><span class="nf">barh</span><span class="p">(</span><span class="nf">range</span><span class="p">(</span><span class="nf">len</span><span class="p">(</span><span class="n">motifs</span><span class="p">)),</span> <span class="n">counts</span><span class="p">)</span>
    <span class="n">plt</span><span class="p">.</span><span class="nf">yticks</span><span class="p">(</span><span class="nf">range</span><span class="p">(</span><span class="nf">len</span><span class="p">(</span><span class="n">motifs</span><span class="p">)),</span> <span class="p">[</span><span class="nf">str</span><span class="p">(</span><span class="n">m</span><span class="p">)</span> <span class="k">for</span> <span class="n">m</span> <span class="ow">in</span> <span class="n">motifs</span><span class="p">])</span>
    <span class="n">plt</span><span class="p">.</span><span class="nf">xlabel</span><span class="p">(</span><span class="sh">'</span><span class="s">Occurrence Count</span><span class="sh">'</span><span class="p">)</span>
    <span class="n">plt</span><span class="p">.</span><span class="nf">title</span><span class="p">(</span><span class="sa">f</span><span class="sh">'</span><span class="s">Top </span><span class="si">{</span><span class="n">top_n</span><span class="si">}</span><span class="s"> Most Frequent Motifs</span><span class="sh">'</span><span class="p">)</span>
    <span class="n">plt</span><span class="p">.</span><span class="nf">gca</span><span class="p">().</span><span class="nf">invert_yaxis</span><span class="p">()</span>
    <span class="n">plt</span><span class="p">.</span><span class="nf">tight_layout</span><span class="p">()</span>
    <span class="n">plt</span><span class="p">.</span><span class="nf">show</span><span class="p">()</span>
</code></pre></div></div>

<h2 id="putting-it-all-together-a-complete-example">Putting It All Together: A Complete Example</h2>

<p>Here’s how you might use these functions in a complete workflow:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="n">pathlib</span> <span class="kn">import</span> <span class="n">Path</span>
<span class="kn">import</span> <span class="n">matplotlib.pyplot</span> <span class="k">as</span> <span class="n">plt</span>

<span class="c1"># 1. Load the score
</span><span class="n">score_path</span> <span class="o">=</span> <span class="nc">Path</span><span class="p">(</span><span class="sh">"</span><span class="s">data/Btaihi_Iraq_Ajam.mxl</span><span class="sh">"</span><span class="p">)</span>
<span class="n">score</span> <span class="o">=</span> <span class="nf">load_score</span><span class="p">(</span><span class="n">score_path</span><span class="p">)</span>

<span class="c1"># 2. Extract the melody
</span><span class="n">melody</span> <span class="o">=</span> <span class="nf">extract_melody</span><span class="p">(</span><span class="n">score</span><span class="p">)</span>

<span class="c1"># 3. Identify motifs
</span><span class="n">motifs</span> <span class="o">=</span> <span class="nf">identify_motifs</span><span class="p">(</span><span class="n">melody</span><span class="p">,</span> <span class="n">min_length</span><span class="o">=</span><span class="mi">3</span><span class="p">,</span> <span class="n">max_length</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span>

<span class="c1"># 4. Analyze and visualize
# (Implementation of analysis and visualization would go here)
</span>
<span class="nf">print</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="s">Analyzed </span><span class="si">{</span><span class="nf">len</span><span class="p">(</span><span class="n">score</span><span class="p">.</span><span class="n">parts</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nf">getElementsByClass</span><span class="p">(</span><span class="sh">'</span><span class="s">Measure</span><span class="sh">'</span><span class="p">))</span><span class="si">}</span><span class="s"> measures</span><span class="sh">"</span><span class="p">)</span>
<span class="nf">print</span><span class="p">(</span><span class="sa">f</span><span class="sh">"</span><span class="s">Found </span><span class="si">{</span><span class="nf">len</span><span class="p">(</span><span class="n">motifs</span><span class="p">)</span><span class="si">}</span><span class="s"> potential motifs</span><span class="sh">"</span><span class="p">)</span>
</code></pre></div></div>

<h2 id="applications-in-music-research">Applications in Music Research</h2>

<p>This methodology has been applied to:</p>

<h3 id="1-arab-andalusian-music-analysis">1. <strong>Arab-Andalusian Music Analysis</strong></h3>
<p>In my research on Arab-Andalusian motif development, this approach revealed:</p>
<ul>
  <li>Systematic patterns in traditional Iraqi Ajam repertoire</li>
  <li>The distribution of melodic centos (motifs) across different sections</li>
  <li>Relationships between structural markers (like “Tawchiya”, “Mshalia”) and motif usage</li>
</ul>

<h3 id="2-style-analysis">2. <strong>Style Analysis</strong></h3>
<p>By comparing motifs across different pieces or composers, you can:</p>
<ul>
  <li>Identify characteristic patterns of a musical style</li>
  <li>Track the evolution of motifs over time</li>
  <li>Compare different interpretations or arrangements</li>
</ul>

<h3 id="3-music-information-retrieval">3. <strong>Music Information Retrieval</strong></h3>
<p>Motif analysis supports:</p>
<ul>
  <li><strong>Music similarity</strong>: Pieces with similar motifs may be related</li>
  <li><strong>Genre classification</strong>: Different genres may have characteristic motifs</li>
  <li><strong>Cover detection</strong>: Versions of the same piece share core motifs</li>
</ul>

<h2 id="challenges-and-considerations">Challenges and Considerations</h2>

<h3 id="1-octave-equivalence">1. <strong>Octave Equivalence</strong></h3>
<p>Should <code class="language-plaintext highlighter-rouge">C4-D4-E4</code> be considered the same as <code class="language-plaintext highlighter-rouge">C5-D5-E5</code>? In many analyses, yes—we care about the <strong>interval structure</strong>, not absolute pitch. The code can be extended to normalize octaves.</p>

<h3 id="2-transpositional-equivalence">2. <strong>Transpositional Equivalence</strong></h3>
<p>A motif in C major might be the same as one in G major (transposed). For some analyses, you might want to identify these as equivalent.</p>

<h3 id="3-rhythmic-variation">3. <strong>Rhythmic Variation</strong></h3>
<p>The current code focuses on pitch sequences. Adding rhythmic information would make motif identification more precise but also more complex.</p>

<h3 id="4-computational-complexity">4. <strong>Computational Complexity</strong></h3>
<p>For long pieces, the number of potential motifs grows quickly. A 1000-note melody with motifs of length 3-8 generates thousands of sequences. Efficient algorithms and data structures become important at scale.</p>

<h2 id="extending-the-analysis">Extending the Analysis</h2>

<p>Here are directions for further development:</p>

<h3 id="1-add-rhythmic-information">1. <strong>Add Rhythmic Information</strong></h3>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">identify_motifs_with_rhythm</span><span class="p">(</span><span class="n">melody</span><span class="p">,</span> <span class="n">min_length</span><span class="o">=</span><span class="mi">3</span><span class="p">,</span> <span class="n">max_length</span><span class="o">=</span><span class="mi">8</span><span class="p">):</span>
    <span class="sh">"""</span><span class="s">Identify motifs including both pitch and rhythm.</span><span class="sh">"""</span>
    <span class="n">notes</span> <span class="o">=</span> <span class="p">[</span><span class="n">n</span> <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">melody</span><span class="p">.</span><span class="nf">recurse</span><span class="p">().</span><span class="n">notes</span><span class="p">]</span>
    <span class="n">motifs</span> <span class="o">=</span> <span class="p">[]</span>
    
    <span class="k">for</span> <span class="n">length</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">min_length</span><span class="p">,</span> <span class="n">max_length</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
        <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="nf">len</span><span class="p">(</span><span class="n">notes</span><span class="p">)</span> <span class="o">-</span> <span class="n">length</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
            <span class="n">motif_notes</span> <span class="o">=</span> <span class="n">notes</span><span class="p">[</span><span class="n">i</span> <span class="p">:</span> <span class="n">i</span> <span class="o">+</span> <span class="n">length</span><span class="p">]</span>
            <span class="n">motif</span> <span class="o">=</span> <span class="p">{</span>
                <span class="sh">'</span><span class="s">pitches</span><span class="sh">'</span><span class="p">:</span> <span class="p">[</span><span class="n">n</span><span class="p">.</span><span class="n">pitch</span><span class="p">.</span><span class="n">name</span> <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">motif_notes</span><span class="p">],</span>
                <span class="sh">'</span><span class="s">rhythms</span><span class="sh">'</span><span class="p">:</span> <span class="p">[</span><span class="n">n</span><span class="p">.</span><span class="n">quarterLength</span> <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">motif_notes</span><span class="p">],</span>
                <span class="sh">'</span><span class="s">intervals</span><span class="sh">'</span><span class="p">:</span> <span class="p">[</span><span class="n">music21</span><span class="p">.</span><span class="n">interval</span><span class="p">.</span><span class="nc">Interval</span><span class="p">(</span><span class="n">n1</span><span class="p">,</span> <span class="n">n2</span><span class="p">)</span> 
                            <span class="k">for</span> <span class="n">n1</span><span class="p">,</span> <span class="n">n2</span> <span class="ow">in</span> <span class="nf">zip</span><span class="p">(</span><span class="n">motif_notes</span><span class="p">[:</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span> <span class="n">motif_notes</span><span class="p">[</span><span class="mi">1</span><span class="p">:])]</span>
            <span class="p">}</span>
            <span class="n">motifs</span><span class="p">.</span><span class="nf">append</span><span class="p">(</span><span class="n">motif</span><span class="p">)</span>
    
    <span class="k">return</span> <span class="n">motifs</span>
</code></pre></div></div>

<h3 id="2-fuzzy-matching">2. <strong>Fuzzy Matching</strong></h3>
<p>Allow for slight variations in motifs:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">find_similar_motifs</span><span class="p">(</span><span class="n">motif</span><span class="p">,</span> <span class="n">all_motifs</span><span class="p">,</span> <span class="n">similarity_threshold</span><span class="o">=</span><span class="mf">0.8</span><span class="p">):</span>
    <span class="sh">"""</span><span class="s">Find motifs similar to a given motif using edit distance or other metrics.</span><span class="sh">"""</span>
    <span class="c1"># Implementation using sequence alignment or other similarity measures
</span>    <span class="k">pass</span>
</code></pre></div></div>

<h3 id="3-hierarchical-analysis">3. <strong>Hierarchical Analysis</strong></h3>
<p>Identify motifs at different structural levels:</p>
<ul>
  <li><strong>Note-level</strong>: Individual pitch sequences</li>
  <li><strong>Measure-level</strong>: Patterns across measures</li>
  <li><strong>Section-level</strong>: Recurring sections or phrases</li>
</ul>

<h2 id="conclusion">Conclusion</h2>

<p>Computational motif analysis opens powerful avenues for understanding musical structure. The functions we’ve explored provide a foundation for:</p>
<ul>
  <li>Systematic pattern discovery in musical scores</li>
  <li>Quantitative analysis of musical traditions</li>
  <li>Comparative studies across pieces, styles, or time periods</li>
</ul>

<p>While the current implementation is a starting point, the techniques can be extended to handle more complex scenarios: rhythmic patterns, harmonic progressions, multi-voice analysis, and fuzzy matching for variations.</p>

<p>For a complete implementation with visualizations and analysis of Arab-Andalusian music, see the <a href="/notebooks/arab-andal-motif-dev-main/">interactive notebook</a> and the <a href="https://github.com/oriolcolomefont/arab-andal-motif-dev">GitHub repository</a>.</p>

<h2 id="further-reading">Further Reading</h2>

<ul>
  <li><a href="https://web.mit.edu/music21/doc/">music21 Documentation</a></li>
  <li><a href="https://github.com/topics/computational-musicology">Computational Musicology Resources</a></li>
  <li><a href="https://ismir.net/">Pattern Recognition in Music</a></li>
</ul>

<hr />

<p><em>This post is part of a series on computational musicology and music information retrieval. For more on music technology and analysis, check out the <a href="/blog/">blog</a> and <a href="/portfolio/">portfolio</a>.</em></p>]]></content><author><name>Oriol Colomé Font</name></author><category term="Music Information Retrieval" /><category term="Computational Musicology" /><category term="python" /><category term="music21" /><category term="music-analysis" /><category term="pattern-recognition" /><category term="motifs" /><category term="computational-musicology" /><category term="music-technology" /><summary type="html"><![CDATA[A deep dive into computational methods for analyzing musical scores and identifying melodic motifs using Python and music21. Learn how to extract patterns from musical notation and visualize motif occurrences.]]></summary></entry><entry><title type="html">Visualizing Musical Analysis Results: Plotting Motif Distributions and Timelines</title><link href="https://oriolcolomefont.github.io/blog/visualizing-musical-motifs/" rel="alternate" type="text/html" title="Visualizing Musical Analysis Results: Plotting Motif Distributions and Timelines" /><published>2025-01-11T00:00:00+00:00</published><updated>2025-01-11T00:00:00+00:00</updated><id>https://oriolcolomefont.github.io/blog/visualizing-musical-motifs</id><content type="html" xml:base="https://oriolcolomefont.github.io/blog/visualizing-musical-motifs/"><![CDATA[<h2 id="introduction">Introduction</h2>

<p>Once you’ve identified motifs in a musical score, the next crucial step is <strong>visualization</strong>. Effective visualizations transform raw data into insights, revealing patterns, distributions, and relationships that might not be apparent from numbers alone.</p>

<p>In computational musicology, visualization serves multiple purposes:</p>
<ul>
  <li><strong>Exploratory analysis</strong>: Understanding the structure of your data</li>
  <li><strong>Pattern discovery</strong>: Identifying recurring motifs and their characteristics</li>
  <li><strong>Communication</strong>: Presenting findings to other researchers or musicians</li>
  <li><strong>Validation</strong>: Verifying that your analysis methods are working correctly</li>
</ul>

<p>This post explores visualization techniques for musical motif analysis, building on the <a href="/blog/musical-score-motif-analysis/">motif identification methods</a> we discussed previously.</p>

<h2 id="the-visualization-toolkit">The Visualization Toolkit</h2>

<p>Our visualization approach uses three key functions:</p>
<ol>
  <li><strong>Distribution plots</strong>: Understanding motif length patterns</li>
  <li><strong>Timeline visualizations</strong>: Seeing when and where motifs occur</li>
  <li><strong>Color mapping</strong>: Distinguishing different motifs visually</li>
</ol>

<p>Let’s examine each in detail.</p>

<h2 id="function-1-plotting-motif-distributions">Function 1: Plotting Motif Distributions</h2>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">plot_motif_distribution</span><span class="p">(</span>
    <span class="n">motifs</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">Any</span><span class="p">],</span>
    <span class="n">title</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="sh">"</span><span class="s">Motif Distribution</span><span class="sh">"</span><span class="p">,</span>
    <span class="n">output_path</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span>
<span class="p">)</span> <span class="o">-&gt;</span> <span class="bp">None</span><span class="p">:</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">motifs</span><span class="p">:</span>
        <span class="k">raise</span> <span class="nc">ValueError</span><span class="p">(</span><span class="sh">"</span><span class="s">Motifs list cannot be empty</span><span class="sh">"</span><span class="p">)</span>

    <span class="n">lengths</span> <span class="o">=</span> <span class="p">[</span><span class="nf">len</span><span class="p">(</span><span class="n">m</span><span class="p">)</span> <span class="k">for</span> <span class="n">m</span> <span class="ow">in</span> <span class="n">motifs</span><span class="p">]</span>

    <span class="n">plt</span><span class="p">.</span><span class="nf">figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">6</span><span class="p">))</span>
    <span class="n">plt</span><span class="p">.</span><span class="nf">hist</span><span class="p">(</span><span class="n">lengths</span><span class="p">,</span> <span class="n">bins</span><span class="o">=</span><span class="sh">"</span><span class="s">auto</span><span class="sh">"</span><span class="p">)</span>
    <span class="n">plt</span><span class="p">.</span><span class="nf">title</span><span class="p">(</span><span class="n">title</span><span class="p">)</span>
    <span class="n">plt</span><span class="p">.</span><span class="nf">xlabel</span><span class="p">(</span><span class="sh">"</span><span class="s">Motif Length</span><span class="sh">"</span><span class="p">)</span>
    <span class="n">plt</span><span class="p">.</span><span class="nf">ylabel</span><span class="p">(</span><span class="sh">"</span><span class="s">Frequency</span><span class="sh">"</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">output_path</span><span class="p">:</span>
        <span class="n">plt</span><span class="p">.</span><span class="nf">savefig</span><span class="p">(</span><span class="n">output_path</span><span class="p">)</span>
    <span class="n">plt</span><span class="p">.</span><span class="nf">close</span><span class="p">()</span>
</code></pre></div></div>

<h3 id="what-this-function-does">What This Function Does</h3>

<p>The <code class="language-plaintext highlighter-rouge">plot_motif_distribution</code> function creates a histogram showing how many motifs exist at each length. This simple visualization reveals important characteristics:</p>

<ul>
  <li><strong>Most common motif length</strong>: Which length appears most frequently?</li>
  <li><strong>Length diversity</strong>: Does the piece use motifs of many different lengths, or focus on a few?</li>
  <li><strong>Distribution shape</strong>: Are motifs evenly distributed, or clustered around certain lengths?</li>
</ul>

<h3 id="understanding-the-output">Understanding the Output</h3>

<p>A typical distribution plot might show:</p>
<ul>
  <li>A peak at length 3-4: Short motifs are building blocks</li>
  <li>Fewer longer motifs: Longer sequences are less common</li>
  <li>Tails at both ends: Very short (2 notes) or very long (8+ notes) motifs are rare</li>
</ul>

<h3 id="enhanced-version">Enhanced Version</h3>

<p>Here’s an enhanced version with more detail:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">plot_motif_distribution_enhanced</span><span class="p">(</span>
    <span class="n">motifs</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">Any</span><span class="p">],</span>
    <span class="n">title</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="sh">"</span><span class="s">Motif Distribution</span><span class="sh">"</span><span class="p">,</span>
    <span class="n">output_path</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span>
    <span class="n">show_stats</span><span class="p">:</span> <span class="nb">bool</span> <span class="o">=</span> <span class="bp">True</span><span class="p">,</span>
<span class="p">)</span> <span class="o">-&gt;</span> <span class="bp">None</span><span class="p">:</span>
    <span class="sh">"""</span><span class="s">Enhanced version with statistics and styling.</span><span class="sh">"""</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">motifs</span><span class="p">:</span>
        <span class="k">raise</span> <span class="nc">ValueError</span><span class="p">(</span><span class="sh">"</span><span class="s">Motifs list cannot be empty</span><span class="sh">"</span><span class="p">)</span>

    <span class="n">lengths</span> <span class="o">=</span> <span class="p">[</span><span class="nf">len</span><span class="p">(</span><span class="n">m</span><span class="p">)</span> <span class="k">for</span> <span class="n">m</span> <span class="ow">in</span> <span class="n">motifs</span><span class="p">]</span>
    
    <span class="n">fig</span><span class="p">,</span> <span class="n">ax</span> <span class="o">=</span> <span class="n">plt</span><span class="p">.</span><span class="nf">subplots</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">12</span><span class="p">,</span> <span class="mi">6</span><span class="p">))</span>
    
    <span class="c1"># Create histogram
</span>    <span class="n">n</span><span class="p">,</span> <span class="n">bins</span><span class="p">,</span> <span class="n">patches</span> <span class="o">=</span> <span class="n">ax</span><span class="p">.</span><span class="nf">hist</span><span class="p">(</span><span class="n">lengths</span><span class="p">,</span> <span class="n">bins</span><span class="o">=</span><span class="sh">"</span><span class="s">auto</span><span class="sh">"</span><span class="p">,</span> <span class="n">edgecolor</span><span class="o">=</span><span class="sh">'</span><span class="s">black</span><span class="sh">'</span><span class="p">,</span> <span class="n">alpha</span><span class="o">=</span><span class="mf">0.7</span><span class="p">)</span>
    
    <span class="c1"># Color bars by frequency
</span>    <span class="n">max_freq</span> <span class="o">=</span> <span class="nf">max</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="p">(</span><span class="n">bar</span><span class="p">,</span> <span class="n">freq</span><span class="p">)</span> <span class="ow">in</span> <span class="nf">enumerate</span><span class="p">(</span><span class="nf">zip</span><span class="p">(</span><span class="n">patches</span><span class="p">,</span> <span class="n">n</span><span class="p">)):</span>
        <span class="n">bar</span><span class="p">.</span><span class="nf">set_facecolor</span><span class="p">(</span><span class="n">plt</span><span class="p">.</span><span class="n">cm</span><span class="p">.</span><span class="nf">viridis</span><span class="p">(</span><span class="n">freq</span> <span class="o">/</span> <span class="n">max_freq</span><span class="p">))</span>
    
    <span class="c1"># Add statistics
</span>    <span class="k">if</span> <span class="n">show_stats</span><span class="p">:</span>
        <span class="n">mean_len</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="nf">mean</span><span class="p">(</span><span class="n">lengths</span><span class="p">)</span>
        <span class="n">median_len</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="nf">median</span><span class="p">(</span><span class="n">lengths</span><span class="p">)</span>
        <span class="n">ax</span><span class="p">.</span><span class="nf">axvline</span><span class="p">(</span><span class="n">mean_len</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="sh">'</span><span class="s">red</span><span class="sh">'</span><span class="p">,</span> <span class="n">linestyle</span><span class="o">=</span><span class="sh">'</span><span class="s">--</span><span class="sh">'</span><span class="p">,</span> <span class="n">linewidth</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">label</span><span class="o">=</span><span class="sa">f</span><span class="sh">'</span><span class="s">Mean: </span><span class="si">{</span><span class="n">mean_len</span><span class="si">:</span><span class="p">.</span><span class="mi">2</span><span class="n">f</span><span class="si">}</span><span class="sh">'</span><span class="p">)</span>
        <span class="n">ax</span><span class="p">.</span><span class="nf">axvline</span><span class="p">(</span><span class="n">median_len</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="sh">'</span><span class="s">blue</span><span class="sh">'</span><span class="p">,</span> <span class="n">linestyle</span><span class="o">=</span><span class="sh">'</span><span class="s">--</span><span class="sh">'</span><span class="p">,</span> <span class="n">linewidth</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">label</span><span class="o">=</span><span class="sa">f</span><span class="sh">'</span><span class="s">Median: </span><span class="si">{</span><span class="n">median_len</span><span class="si">:</span><span class="p">.</span><span class="mi">2</span><span class="n">f</span><span class="si">}</span><span class="sh">'</span><span class="p">)</span>
        <span class="n">ax</span><span class="p">.</span><span class="nf">legend</span><span class="p">()</span>
    
    <span class="n">ax</span><span class="p">.</span><span class="nf">set_title</span><span class="p">(</span><span class="n">title</span><span class="p">,</span> <span class="n">fontsize</span><span class="o">=</span><span class="mi">14</span><span class="p">,</span> <span class="n">fontweight</span><span class="o">=</span><span class="sh">'</span><span class="s">bold</span><span class="sh">'</span><span class="p">)</span>
    <span class="n">ax</span><span class="p">.</span><span class="nf">set_xlabel</span><span class="p">(</span><span class="sh">"</span><span class="s">Motif Length (number of notes)</span><span class="sh">"</span><span class="p">,</span> <span class="n">fontsize</span><span class="o">=</span><span class="mi">12</span><span class="p">)</span>
    <span class="n">ax</span><span class="p">.</span><span class="nf">set_ylabel</span><span class="p">(</span><span class="sh">"</span><span class="s">Frequency</span><span class="sh">"</span><span class="p">,</span> <span class="n">fontsize</span><span class="o">=</span><span class="mi">12</span><span class="p">)</span>
    <span class="n">ax</span><span class="p">.</span><span class="nf">grid</span><span class="p">(</span><span class="n">axis</span><span class="o">=</span><span class="sh">'</span><span class="s">y</span><span class="sh">'</span><span class="p">,</span> <span class="n">alpha</span><span class="o">=</span><span class="mf">0.3</span><span class="p">)</span>
    
    <span class="n">plt</span><span class="p">.</span><span class="nf">tight_layout</span><span class="p">()</span>
    
    <span class="k">if</span> <span class="n">output_path</span><span class="p">:</span>
        <span class="n">plt</span><span class="p">.</span><span class="nf">savefig</span><span class="p">(</span><span class="n">output_path</span><span class="p">,</span> <span class="n">dpi</span><span class="o">=</span><span class="mi">300</span><span class="p">,</span> <span class="n">bbox_inches</span><span class="o">=</span><span class="sh">'</span><span class="s">tight</span><span class="sh">'</span><span class="p">)</span>
    <span class="n">plt</span><span class="p">.</span><span class="nf">close</span><span class="p">()</span>
</code></pre></div></div>

<h2 id="function-2-plotting-motif-timelines">Function 2: Plotting Motif Timelines</h2>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">plot_motif_timeline</span><span class="p">(</span>
    <span class="n">score</span><span class="p">:</span> <span class="n">music21</span><span class="p">.</span><span class="n">stream</span><span class="p">.</span><span class="n">Score</span><span class="p">,</span>
    <span class="n">motifs</span><span class="p">:</span> <span class="n">List</span><span class="p">[</span><span class="n">List</span><span class="p">[</span><span class="n">music21</span><span class="p">.</span><span class="n">note</span><span class="p">.</span><span class="n">Note</span><span class="p">]],</span>
    <span class="n">output_path</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span>
<span class="p">)</span> <span class="o">-&gt;</span> <span class="bp">None</span><span class="p">:</span>

    <span class="k">if</span> <span class="ow">not</span> <span class="n">motifs</span><span class="p">:</span>
        <span class="k">raise</span> <span class="nc">ValueError</span><span class="p">(</span><span class="sh">"</span><span class="s">Motifs list cannot be empty</span><span class="sh">"</span><span class="p">)</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">score</span><span class="p">.</span><span class="n">parts</span><span class="p">:</span>
        <span class="k">raise</span> <span class="nc">ValueError</span><span class="p">(</span><span class="sh">"</span><span class="s">Score must have at least one part</span><span class="sh">"</span><span class="p">)</span>

    <span class="n">plt</span><span class="p">.</span><span class="nf">figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">15</span><span class="p">,</span> <span class="mi">8</span><span class="p">))</span>
    <span class="c1"># Implementation would depend on how you want to visualize the timeline
</span>    <span class="c1"># This is a placeholder for the actual visualization logic
</span>
    <span class="k">if</span> <span class="n">output_path</span><span class="p">:</span>
        <span class="n">plt</span><span class="p">.</span><span class="nf">savefig</span><span class="p">(</span><span class="n">output_path</span><span class="p">)</span>
    <span class="n">plt</span><span class="p">.</span><span class="nf">close</span><span class="p">()</span>
</code></pre></div></div>

<h3 id="why-timeline-visualization-matters">Why Timeline Visualization Matters</h3>

<p>Timeline visualizations answer critical questions:</p>
<ul>
  <li><strong>When do motifs appear?</strong> Are they clustered at the beginning, end, or distributed throughout?</li>
  <li><strong>How do motifs relate to structure?</strong> Do they align with section markers (like “Tawchiya”, “Mshalia” in Arab-Andalusian music)?</li>
  <li><strong>Are there patterns?</strong> Do certain motifs always appear together or in sequence?</li>
</ul>

<h3 id="complete-implementation">Complete Implementation</h3>

<p>Here’s a complete implementation based on the Arab-Andalusian music analysis:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">plot_motif_timeline</span><span class="p">(</span>
    <span class="n">score</span><span class="p">:</span> <span class="n">music21</span><span class="p">.</span><span class="n">stream</span><span class="p">.</span><span class="n">Score</span><span class="p">,</span>
    <span class="n">motif_counts</span><span class="p">:</span> <span class="nb">dict</span><span class="p">,</span>
    <span class="n">text_expressions</span><span class="p">:</span> <span class="nb">dict</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span>
    <span class="n">filename</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="sh">""</span><span class="p">,</span>
    <span class="n">output_path</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span>
<span class="p">)</span> <span class="o">-&gt;</span> <span class="bp">None</span><span class="p">:</span>

    <span class="k">if</span> <span class="ow">not</span> <span class="n">motif_counts</span><span class="p">:</span>
        <span class="k">raise</span> <span class="nc">ValueError</span><span class="p">(</span><span class="sh">"</span><span class="s">Motif counts dictionary cannot be empty</span><span class="sh">"</span><span class="p">)</span>
    
    <span class="n">measures</span> <span class="o">=</span> <span class="n">score</span><span class="p">.</span><span class="n">parts</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nf">getElementsByClass</span><span class="p">(</span><span class="sh">'</span><span class="s">Measure</span><span class="sh">'</span><span class="p">)</span>
    <span class="n">total_measures</span> <span class="o">=</span> <span class="nf">len</span><span class="p">(</span><span class="n">measures</span><span class="p">)</span>
    <span class="n">unique_motifs</span> <span class="o">=</span> <span class="nf">list</span><span class="p">(</span><span class="n">motif_counts</span><span class="p">.</span><span class="nf">keys</span><span class="p">())</span>
    
    <span class="c1"># Calculate max count for consistent y-axis
</span>    <span class="n">max_count</span> <span class="o">=</span> <span class="nf">max</span><span class="p">(</span><span class="nf">max</span><span class="p">(</span><span class="n">counts</span><span class="p">.</span><span class="nf">values</span><span class="p">())</span> <span class="k">if</span> <span class="nf">isinstance</span><span class="p">(</span><span class="n">counts</span><span class="p">,</span> <span class="nb">dict</span><span class="p">)</span> <span class="k">else</span> <span class="mi">0</span> 
                    <span class="k">for</span> <span class="n">counts</span> <span class="ow">in</span> <span class="n">motif_counts</span><span class="p">.</span><span class="nf">values</span><span class="p">())</span>
    
    <span class="c1"># Create subplots for each motif
</span>    <span class="n">n_motifs</span> <span class="o">=</span> <span class="nf">len</span><span class="p">(</span><span class="n">unique_motifs</span><span class="p">)</span>
    <span class="n">fig</span><span class="p">,</span> <span class="n">axs</span> <span class="o">=</span> <span class="n">plt</span><span class="p">.</span><span class="nf">subplots</span><span class="p">(</span><span class="n">n_motifs</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">14</span><span class="p">,</span> <span class="mi">3</span> <span class="o">*</span> <span class="n">n_motifs</span><span class="p">),</span> <span class="n">sharex</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
    
    <span class="k">if</span> <span class="n">n_motifs</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
        <span class="n">axs</span> <span class="o">=</span> <span class="p">[</span><span class="n">axs</span><span class="p">]</span>
    
    <span class="n">palette</span> <span class="o">=</span> <span class="n">plt</span><span class="p">.</span><span class="n">cm</span><span class="p">.</span><span class="n">Pastel2</span><span class="p">.</span><span class="n">colors</span>
    
    <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="p">(</span><span class="n">motif</span><span class="p">,</span> <span class="n">counts</span><span class="p">)</span> <span class="ow">in</span> <span class="nf">enumerate</span><span class="p">(</span><span class="n">motif_counts</span><span class="p">.</span><span class="nf">items</span><span class="p">()):</span>
        <span class="c1"># Create measure-by-measure count array
</span>        <span class="n">measure_counts</span> <span class="o">=</span> <span class="p">[</span><span class="n">counts</span><span class="p">.</span><span class="nf">get</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="k">for</span> <span class="n">m</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">total_measures</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)]</span>
        
        <span class="c1"># Plot as bar chart
</span>        <span class="n">axs</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="nf">bar</span><span class="p">(</span><span class="nf">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">total_measures</span> <span class="o">+</span> <span class="mi">1</span><span class="p">),</span> <span class="n">measure_counts</span><span class="p">,</span> 
                   <span class="n">color</span><span class="o">=</span><span class="n">palette</span><span class="p">[</span><span class="n">i</span> <span class="o">%</span> <span class="nf">len</span><span class="p">(</span><span class="n">palette</span><span class="p">)],</span> <span class="n">width</span><span class="o">=</span><span class="mf">1.0</span><span class="p">)</span>
        
        <span class="c1"># Add section markers if provided
</span>        <span class="k">if</span> <span class="n">text_expressions</span><span class="p">:</span>
            <span class="k">for</span> <span class="n">measure_num</span><span class="p">,</span> <span class="n">label</span> <span class="ow">in</span> <span class="n">text_expressions</span><span class="p">.</span><span class="nf">items</span><span class="p">():</span>
                <span class="n">axs</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="nf">axvline</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="n">measure_num</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="sh">'</span><span class="s">black</span><span class="sh">'</span><span class="p">,</span> 
                              <span class="n">linestyle</span><span class="o">=</span><span class="sh">'</span><span class="s">--</span><span class="sh">'</span><span class="p">,</span> <span class="n">linewidth</span><span class="o">=</span><span class="mf">0.75</span><span class="p">,</span> <span class="n">alpha</span><span class="o">=</span><span class="mf">0.7</span><span class="p">)</span>
        
        <span class="c1"># Styling
</span>        <span class="n">axs</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="nf">set_title</span><span class="p">(</span><span class="sa">f</span><span class="sh">'</span><span class="s">Cento: </span><span class="si">{</span><span class="n">motif</span><span class="si">}</span><span class="sh">'</span><span class="p">,</span> <span class="n">fontsize</span><span class="o">=</span><span class="mi">11</span><span class="p">,</span> <span class="n">fontweight</span><span class="o">=</span><span class="sh">'</span><span class="s">bold</span><span class="sh">'</span><span class="p">)</span>
        <span class="n">axs</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="nf">set_ylabel</span><span class="p">(</span><span class="sh">'</span><span class="s">Counts</span><span class="sh">'</span><span class="p">,</span> <span class="n">fontsize</span><span class="o">=</span><span class="mi">10</span><span class="p">)</span>
        <span class="n">axs</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="nf">set_ylim</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">max_count</span><span class="p">)</span>
        <span class="n">axs</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="nf">set_yticks</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="nf">arange</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">max_count</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">))</span>
        <span class="n">axs</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="nf">grid</span><span class="p">(</span><span class="n">axis</span><span class="o">=</span><span class="sh">'</span><span class="s">y</span><span class="sh">'</span><span class="p">,</span> <span class="n">linestyle</span><span class="o">=</span><span class="sh">'</span><span class="s">--</span><span class="sh">'</span><span class="p">,</span> <span class="n">alpha</span><span class="o">=</span><span class="mf">0.5</span><span class="p">)</span>
        <span class="n">axs</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="nf">set_xticks</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="nf">arange</span><span class="p">(</span><span class="mi">20</span><span class="p">,</span> <span class="n">total_measures</span><span class="p">,</span> <span class="mi">20</span><span class="p">))</span>
    
    <span class="c1"># Common x-axis label
</span>    <span class="n">axs</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">].</span><span class="nf">set_xlabel</span><span class="p">(</span><span class="sh">'</span><span class="s">Measure Number</span><span class="sh">'</span><span class="p">,</span> <span class="n">fontsize</span><span class="o">=</span><span class="mi">12</span><span class="p">)</span>
    
    <span class="c1"># Overall title
</span>    <span class="n">plt</span><span class="p">.</span><span class="nf">suptitle</span><span class="p">(</span><span class="sa">f</span><span class="sh">'</span><span class="s">Distribution of Centos across </span><span class="si">{</span><span class="n">filename</span><span class="si">}</span><span class="sh">'</span><span class="p">,</span> 
                 <span class="n">fontsize</span><span class="o">=</span><span class="mi">14</span><span class="p">,</span> <span class="n">fontweight</span><span class="o">=</span><span class="sh">'</span><span class="s">bold</span><span class="sh">'</span><span class="p">,</span> <span class="n">y</span><span class="o">=</span><span class="mf">0.995</span><span class="p">)</span>
    
    <span class="n">plt</span><span class="p">.</span><span class="nf">tight_layout</span><span class="p">(</span><span class="n">rect</span><span class="o">=</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mf">0.98</span><span class="p">])</span>
    
    <span class="k">if</span> <span class="n">output_path</span><span class="p">:</span>
        <span class="n">plt</span><span class="p">.</span><span class="nf">savefig</span><span class="p">(</span><span class="n">output_path</span><span class="p">,</span> <span class="n">dpi</span><span class="o">=</span><span class="mi">300</span><span class="p">,</span> <span class="n">bbox_inches</span><span class="o">=</span><span class="sh">'</span><span class="s">tight</span><span class="sh">'</span><span class="p">)</span>
    <span class="n">plt</span><span class="p">.</span><span class="nf">close</span><span class="p">()</span>
</code></pre></div></div>

<h3 id="real-world-example">Real-World Example</h3>

<p>In the Arab-Andalusian motif analysis, this visualization revealed:</p>

<p><img src="/assets/images/arab-andal-motif-dev-main/plots/Btaihi_Iraq_Ajam.png" alt="Motif Distribution - Btaihi Iraq Ajam" /></p>

<p>This plot shows:</p>
<ul>
  <li><strong>Five different centos</strong> (motifs) being tracked</li>
  <li><strong>Vertical dashed lines</strong> marking structural sections (Tawchiya, Mshalia, Futintu, etc.)</li>
  <li><strong>Bar heights</strong> indicating how many times each motif appears in each measure</li>
  <li><strong>Patterns</strong>: Some motifs cluster around certain sections, others are more evenly distributed</li>
</ul>

<p>The visualization makes it immediately clear that:</p>
<ul>
  <li>The <code class="language-plaintext highlighter-rouge">(B, A, G)</code> cento appears most frequently (91 occurrences total)</li>
  <li>Motifs are distributed throughout the piece, not just at the beginning</li>
  <li>Section markers often align with changes in motif density</li>
</ul>

<h2 id="function-3-creating-color-maps">Function 3: Creating Color Maps</h2>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">create_colormap</span><span class="p">(</span><span class="n">n_motifs</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">np</span><span class="p">.</span><span class="n">ndarray</span><span class="p">:</span>

    <span class="k">if</span> <span class="n">n_motifs</span> <span class="o">&lt;</span> <span class="mi">1</span><span class="p">:</span>
        <span class="k">raise</span> <span class="nc">ValueError</span><span class="p">(</span><span class="sh">"</span><span class="s">Number of motifs must be positive</span><span class="sh">"</span><span class="p">)</span>

    <span class="k">return</span> <span class="n">plt</span><span class="p">.</span><span class="n">cm</span><span class="p">.</span><span class="nf">viridis</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="nf">linspace</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">n_motifs</span><span class="p">))</span>
</code></pre></div></div>

<h3 id="why-color-mapping-matters">Why Color Mapping Matters</h3>

<p>When visualizing multiple motifs simultaneously, color helps:</p>
<ul>
  <li><strong>Distinguish patterns</strong>: Each motif gets a unique, distinguishable color</li>
  <li><strong>Maintain consistency</strong>: The same motif always uses the same color across visualizations</li>
  <li><strong>Improve readability</strong>: Good color choices make complex plots easier to interpret</li>
</ul>

<h3 id="choosing-the-right-colormap">Choosing the Right Colormap</h3>

<p>Different colormaps serve different purposes:</p>

<h4 id="1-categorical-colormaps-for-distinct-motifs">1. <strong>Categorical Colormaps</strong> (for distinct motifs)</h4>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">create_categorical_colormap</span><span class="p">(</span><span class="n">n_motifs</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">np</span><span class="p">.</span><span class="n">ndarray</span><span class="p">:</span>
    <span class="sh">"""</span><span class="s">Use distinct colors for each motif.</span><span class="sh">"""</span>
    <span class="k">if</span> <span class="n">n_motifs</span> <span class="o">&lt;=</span> <span class="mi">10</span><span class="p">:</span>
        <span class="c1"># Use qualitative colormap for small numbers
</span>        <span class="k">return</span> <span class="n">plt</span><span class="p">.</span><span class="n">cm</span><span class="p">.</span><span class="nf">tab10</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="nf">linspace</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">n_motifs</span><span class="p">))</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="c1"># Use Set3 for more colors
</span>        <span class="k">return</span> <span class="n">plt</span><span class="p">.</span><span class="n">cm</span><span class="p">.</span><span class="nc">Set3</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="nf">linspace</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">n_motifs</span><span class="p">))</span>
</code></pre></div></div>

<h4 id="2-sequential-colormaps-for-ordered-data">2. <strong>Sequential Colormaps</strong> (for ordered data)</h4>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">create_sequential_colormap</span><span class="p">(</span><span class="n">n_motifs</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">np</span><span class="p">.</span><span class="n">ndarray</span><span class="p">:</span>
    <span class="sh">"""</span><span class="s">Use sequential colors if motifs have an inherent order.</span><span class="sh">"""</span>
    <span class="k">return</span> <span class="n">plt</span><span class="p">.</span><span class="n">cm</span><span class="p">.</span><span class="nf">viridis</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="nf">linspace</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">n_motifs</span><span class="p">))</span>
</code></pre></div></div>

<h4 id="3-custom-color-schemes">3. <strong>Custom Color Schemes</strong></h4>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">create_musical_colormap</span><span class="p">(</span><span class="n">n_motifs</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">np</span><span class="p">.</span><span class="n">ndarray</span><span class="p">:</span>
    <span class="sh">"""</span><span class="s">Create a custom color scheme for musical visualization.</span><span class="sh">"""</span>
    <span class="c1"># Define a palette that works well for music
</span>    <span class="n">musical_colors</span> <span class="o">=</span> <span class="p">[</span>
        <span class="sh">'</span><span class="s">#1f77b4</span><span class="sh">'</span><span class="p">,</span>  <span class="c1"># Blue
</span>        <span class="sh">'</span><span class="s">#ff7f0e</span><span class="sh">'</span><span class="p">,</span>  <span class="c1"># Orange
</span>        <span class="sh">'</span><span class="s">#2ca02c</span><span class="sh">'</span><span class="p">,</span>  <span class="c1"># Green
</span>        <span class="sh">'</span><span class="s">#d62728</span><span class="sh">'</span><span class="p">,</span>  <span class="c1"># Red
</span>        <span class="sh">'</span><span class="s">#9467bd</span><span class="sh">'</span><span class="p">,</span>  <span class="c1"># Purple
</span>        <span class="sh">'</span><span class="s">#8c564b</span><span class="sh">'</span><span class="p">,</span>  <span class="c1"># Brown
</span>        <span class="sh">'</span><span class="s">#e377c2</span><span class="sh">'</span><span class="p">,</span>  <span class="c1"># Pink
</span>        <span class="sh">'</span><span class="s">#7f7f7f</span><span class="sh">'</span><span class="p">,</span>  <span class="c1"># Gray
</span>        <span class="sh">'</span><span class="s">#bcbd22</span><span class="sh">'</span><span class="p">,</span>  <span class="c1"># Olive
</span>        <span class="sh">'</span><span class="s">#17becf</span><span class="sh">'</span><span class="p">,</span>  <span class="c1"># Cyan
</span>    <span class="p">]</span>
    
    <span class="k">if</span> <span class="n">n_motifs</span> <span class="o">&lt;=</span> <span class="nf">len</span><span class="p">(</span><span class="n">musical_colors</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">np</span><span class="p">.</span><span class="nf">array</span><span class="p">([</span><span class="n">plt</span><span class="p">.</span><span class="n">colors</span><span class="p">.</span><span class="nf">to_rgba</span><span class="p">(</span><span class="n">c</span><span class="p">)</span> <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">musical_colors</span><span class="p">[:</span><span class="n">n_motifs</span><span class="p">]])</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="c1"># Interpolate for more motifs
</span>        <span class="k">return</span> <span class="n">plt</span><span class="p">.</span><span class="n">cm</span><span class="p">.</span><span class="nf">tab20</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="nf">linspace</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">n_motifs</span><span class="p">))</span>
</code></pre></div></div>

<h3 id="accessibility-considerations">Accessibility Considerations</h3>

<p>When choosing colors, consider:</p>
<ul>
  <li><strong>Colorblind-friendly palettes</strong>: Use tools like <a href="https://colorbrewer2.org/">ColorBrewer</a> or matplotlib’s built-in accessible colormaps</li>
  <li><strong>Contrast</strong>: Ensure colors are distinguishable even in grayscale</li>
  <li><strong>Cultural associations</strong>: Be aware that colors may have different meanings in different contexts</li>
</ul>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">create_accessible_colormap</span><span class="p">(</span><span class="n">n_motifs</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">np</span><span class="p">.</span><span class="n">ndarray</span><span class="p">:</span>
    <span class="sh">"""</span><span class="s">Create a colorblind-friendly colormap.</span><span class="sh">"""</span>
    <span class="c1"># Use ColorBrewer qualitative palette
</span>    <span class="n">accessible_colors</span> <span class="o">=</span> <span class="p">[</span>
        <span class="sh">'</span><span class="s">#a6cee3</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">#1f78b4</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">#b2df8a</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">#33a02c</span><span class="sh">'</span><span class="p">,</span>
        <span class="sh">'</span><span class="s">#fb9a99</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">#e31a1c</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">#fdbf6f</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">#ff7f00</span><span class="sh">'</span><span class="p">,</span>
        <span class="sh">'</span><span class="s">#cab2d6</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">#6a3d9a</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">#ffff99</span><span class="sh">'</span><span class="p">,</span> <span class="sh">'</span><span class="s">#b15928</span><span class="sh">'</span>
    <span class="p">]</span>
    
    <span class="k">if</span> <span class="n">n_motifs</span> <span class="o">&lt;=</span> <span class="nf">len</span><span class="p">(</span><span class="n">accessible_colors</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">np</span><span class="p">.</span><span class="nf">array</span><span class="p">([</span><span class="n">plt</span><span class="p">.</span><span class="n">colors</span><span class="p">.</span><span class="nf">to_rgba</span><span class="p">(</span><span class="n">c</span><span class="p">)</span> <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">accessible_colors</span><span class="p">[:</span><span class="n">n_motifs</span><span class="p">]])</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="c1"># Fall back to Set3 which is generally accessible
</span>        <span class="k">return</span> <span class="n">plt</span><span class="p">.</span><span class="n">cm</span><span class="p">.</span><span class="nc">Set3</span><span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="nf">linspace</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">n_motifs</span><span class="p">))</span>
</code></pre></div></div>

<h2 id="advanced-visualization-techniques">Advanced Visualization Techniques</h2>

<h3 id="1-heatmaps-for-multiple-motifs">1. Heatmaps for Multiple Motifs</h3>

<p>Instead of separate subplots, you can visualize all motifs in a single heatmap:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">plot_motif_heatmap</span><span class="p">(</span>
    <span class="n">score</span><span class="p">:</span> <span class="n">music21</span><span class="p">.</span><span class="n">stream</span><span class="p">.</span><span class="n">Score</span><span class="p">,</span>
    <span class="n">motif_counts</span><span class="p">:</span> <span class="nb">dict</span><span class="p">,</span>
    <span class="n">text_expressions</span><span class="p">:</span> <span class="nb">dict</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span>
    <span class="n">output_path</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span>
<span class="p">)</span> <span class="o">-&gt;</span> <span class="bp">None</span><span class="p">:</span>
    <span class="sh">"""</span><span class="s">Create a heatmap showing all motifs across measures.</span><span class="sh">"""</span>
    <span class="kn">import</span> <span class="n">seaborn</span> <span class="k">as</span> <span class="n">sns</span>
    
    <span class="n">measures</span> <span class="o">=</span> <span class="n">score</span><span class="p">.</span><span class="n">parts</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nf">getElementsByClass</span><span class="p">(</span><span class="sh">'</span><span class="s">Measure</span><span class="sh">'</span><span class="p">)</span>
    <span class="n">total_measures</span> <span class="o">=</span> <span class="nf">len</span><span class="p">(</span><span class="n">measures</span><span class="p">)</span>
    <span class="n">unique_motifs</span> <span class="o">=</span> <span class="nf">list</span><span class="p">(</span><span class="n">motif_counts</span><span class="p">.</span><span class="nf">keys</span><span class="p">())</span>
    
    <span class="c1"># Create matrix: rows = motifs, columns = measures
</span>    <span class="n">matrix</span> <span class="o">=</span> <span class="n">np</span><span class="p">.</span><span class="nf">zeros</span><span class="p">((</span><span class="nf">len</span><span class="p">(</span><span class="n">unique_motifs</span><span class="p">),</span> <span class="n">total_measures</span><span class="p">))</span>
    
    <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">motif</span> <span class="ow">in</span> <span class="nf">enumerate</span><span class="p">(</span><span class="n">unique_motifs</span><span class="p">):</span>
        <span class="n">counts</span> <span class="o">=</span> <span class="n">motif_counts</span><span class="p">[</span><span class="n">motif</span><span class="p">]</span>
        <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="n">total_measures</span><span class="p">):</span>
            <span class="n">matrix</span><span class="p">[</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">counts</span><span class="p">.</span><span class="nf">get</span><span class="p">(</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
    
    <span class="c1"># Create heatmap
</span>    <span class="n">plt</span><span class="p">.</span><span class="nf">figure</span><span class="p">(</span><span class="n">figsize</span><span class="o">=</span><span class="p">(</span><span class="mi">16</span><span class="p">,</span> <span class="nf">max</span><span class="p">(</span><span class="mi">6</span><span class="p">,</span> <span class="nf">len</span><span class="p">(</span><span class="n">unique_motifs</span><span class="p">)</span> <span class="o">*</span> <span class="mf">0.8</span><span class="p">)))</span>
    <span class="n">sns</span><span class="p">.</span><span class="nf">heatmap</span><span class="p">(</span><span class="n">matrix</span><span class="p">,</span>
                <span class="n">xticklabels</span><span class="o">=</span><span class="nf">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">total_measures</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">20</span><span class="p">),</span>
                <span class="n">yticklabels</span><span class="o">=</span><span class="p">[</span><span class="nf">str</span><span class="p">(</span><span class="n">m</span><span class="p">)</span> <span class="k">for</span> <span class="n">m</span> <span class="ow">in</span> <span class="n">unique_motifs</span><span class="p">],</span>
                <span class="n">cmap</span><span class="o">=</span><span class="sh">'</span><span class="s">YlOrRd</span><span class="sh">'</span><span class="p">,</span>
                <span class="n">cbar_kws</span><span class="o">=</span><span class="p">{</span><span class="sh">'</span><span class="s">label</span><span class="sh">'</span><span class="p">:</span> <span class="sh">'</span><span class="s">Occurrences</span><span class="sh">'</span><span class="p">})</span>
    
    <span class="n">plt</span><span class="p">.</span><span class="nf">xlabel</span><span class="p">(</span><span class="sh">'</span><span class="s">Measure Number</span><span class="sh">'</span><span class="p">,</span> <span class="n">fontsize</span><span class="o">=</span><span class="mi">12</span><span class="p">)</span>
    <span class="n">plt</span><span class="p">.</span><span class="nf">ylabel</span><span class="p">(</span><span class="sh">'</span><span class="s">Motif</span><span class="sh">'</span><span class="p">,</span> <span class="n">fontsize</span><span class="o">=</span><span class="mi">12</span><span class="p">)</span>
    <span class="n">plt</span><span class="p">.</span><span class="nf">title</span><span class="p">(</span><span class="sh">'</span><span class="s">Motif Distribution Heatmap</span><span class="sh">'</span><span class="p">,</span> <span class="n">fontsize</span><span class="o">=</span><span class="mi">14</span><span class="p">,</span> <span class="n">fontweight</span><span class="o">=</span><span class="sh">'</span><span class="s">bold</span><span class="sh">'</span><span class="p">)</span>
    <span class="n">plt</span><span class="p">.</span><span class="nf">tight_layout</span><span class="p">()</span>
    
    <span class="k">if</span> <span class="n">output_path</span><span class="p">:</span>
        <span class="n">plt</span><span class="p">.</span><span class="nf">savefig</span><span class="p">(</span><span class="n">output_path</span><span class="p">,</span> <span class="n">dpi</span><span class="o">=</span><span class="mi">300</span><span class="p">,</span> <span class="n">bbox_inches</span><span class="o">=</span><span class="sh">'</span><span class="s">tight</span><span class="sh">'</span><span class="p">)</span>
    <span class="n">plt</span><span class="p">.</span><span class="nf">close</span><span class="p">()</span>
</code></pre></div></div>

<h3 id="2-interactive-visualizations">2. Interactive Visualizations</h3>

<p>For web-based exploration, consider interactive libraries:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Example using plotly (requires: pip install plotly)
</span><span class="k">def</span> <span class="nf">plot_motif_timeline_interactive</span><span class="p">(</span>
    <span class="n">score</span><span class="p">:</span> <span class="n">music21</span><span class="p">.</span><span class="n">stream</span><span class="p">.</span><span class="n">Score</span><span class="p">,</span>
    <span class="n">motif_counts</span><span class="p">:</span> <span class="nb">dict</span><span class="p">,</span>
    <span class="n">output_path</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span>
<span class="p">)</span> <span class="o">-&gt;</span> <span class="bp">None</span><span class="p">:</span>
    <span class="sh">"""</span><span class="s">Create an interactive timeline using plotly.</span><span class="sh">"""</span>
    <span class="kn">import</span> <span class="n">plotly.graph_objects</span> <span class="k">as</span> <span class="n">go</span>
    <span class="kn">from</span> <span class="n">plotly.subplots</span> <span class="kn">import</span> <span class="n">make_subplots</span>
    
    <span class="n">measures</span> <span class="o">=</span> <span class="n">score</span><span class="p">.</span><span class="n">parts</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nf">getElementsByClass</span><span class="p">(</span><span class="sh">'</span><span class="s">Measure</span><span class="sh">'</span><span class="p">)</span>
    <span class="n">total_measures</span> <span class="o">=</span> <span class="nf">len</span><span class="p">(</span><span class="n">measures</span><span class="p">)</span>
    
    <span class="n">fig</span> <span class="o">=</span> <span class="nf">make_subplots</span><span class="p">(</span>
        <span class="n">rows</span><span class="o">=</span><span class="nf">len</span><span class="p">(</span><span class="n">motif_counts</span><span class="p">),</span>
        <span class="n">cols</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span>
        <span class="n">shared_xaxes</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span>
        <span class="n">vertical_spacing</span><span class="o">=</span><span class="mf">0.05</span>
    <span class="p">)</span>
    
    <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="p">(</span><span class="n">motif</span><span class="p">,</span> <span class="n">counts</span><span class="p">)</span> <span class="ow">in</span> <span class="nf">enumerate</span><span class="p">(</span><span class="n">motif_counts</span><span class="p">.</span><span class="nf">items</span><span class="p">(),</span> <span class="mi">1</span><span class="p">):</span>
        <span class="n">measure_counts</span> <span class="o">=</span> <span class="p">[</span><span class="n">counts</span><span class="p">.</span><span class="nf">get</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="k">for</span> <span class="n">m</span> <span class="ow">in</span> <span class="nf">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">total_measures</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)]</span>
        <span class="n">fig</span><span class="p">.</span><span class="nf">add_trace</span><span class="p">(</span>
            <span class="n">go</span><span class="p">.</span><span class="nc">Bar</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="nf">list</span><span class="p">(</span><span class="nf">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">total_measures</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)),</span>
                   <span class="n">y</span><span class="o">=</span><span class="n">measure_counts</span><span class="p">,</span>
                   <span class="n">name</span><span class="o">=</span><span class="nf">str</span><span class="p">(</span><span class="n">motif</span><span class="p">)),</span>
            <span class="n">row</span><span class="o">=</span><span class="n">i</span><span class="p">,</span> <span class="n">col</span><span class="o">=</span><span class="mi">1</span>
        <span class="p">)</span>
    
    <span class="n">fig</span><span class="p">.</span><span class="nf">update_layout</span><span class="p">(</span><span class="n">height</span><span class="o">=</span><span class="mi">300</span> <span class="o">*</span> <span class="nf">len</span><span class="p">(</span><span class="n">motif_counts</span><span class="p">),</span>
                     <span class="n">title_text</span><span class="o">=</span><span class="sh">"</span><span class="s">Interactive Motif Timeline</span><span class="sh">"</span><span class="p">)</span>
    
    <span class="k">if</span> <span class="n">output_path</span><span class="p">:</span>
        <span class="n">fig</span><span class="p">.</span><span class="nf">write_html</span><span class="p">(</span><span class="n">output_path</span><span class="p">)</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">fig</span><span class="p">.</span><span class="nf">show</span><span class="p">()</span>
</code></pre></div></div>

<h2 id="real-world-examples-from-research">Real-World Examples from Research</h2>

<p>Let’s look at actual visualizations from the Arab-Andalusian motif analysis:</p>

<h3 id="example-1-btaihi-iraq-ajam">Example 1: Btaihi Iraq Ajam</h3>

<p><img src="/assets/images/arab-andal-motif-dev-main/plots/Btaihi_Iraq_Ajam.png" alt="Btaihi Iraq Ajam Motif Distribution" /></p>

<p>This visualization shows the distribution of five melodic centos across 979 measures. Key observations:</p>
<ul>
  <li><strong>Cento (B, A, G)</strong> appears most frequently (91 times)</li>
  <li><strong>Cento (F, E, D)</strong> is nearly as common (88 times)</li>
  <li>Motifs are distributed throughout, with some clustering around section markers</li>
  <li>The longer cento (G, F#, E, D) appears less frequently (16 times), as expected</li>
</ul>

<h3 id="example-2-bassit-iraq-ajam">Example 2: Bassit Iraq Ajam</h3>

<p><img src="/assets/images/arab-andal-motif-dev-main/plots/Bassit_Iraq_Ajam.png" alt="Bassit Iraq Ajam Motif Distribution" /></p>

<p>This score shows a different pattern:</p>
<ul>
  <li>Similar centos but with different frequencies</li>
  <li>Different structural markers (visible as vertical lines)</li>
  <li>Variations in how motifs cluster around sections</li>
</ul>

<h3 id="example-3-multiple-quddam-versions">Example 3: Multiple Quddam Versions</h3>

<p><img src="/assets/images/arab-andal-motif-dev-main/plots/Quddam_Iraq_Ajam.png" alt="Quddam Iraq Ajam" /></p>

<p>Comparing different versions of the same piece (Quddam) reveals:</p>
<ul>
  <li><strong>Consistency</strong>: Same centos appear across versions</li>
  <li><strong>Variation</strong>: Different frequencies and distributions</li>
  <li><strong>Structure</strong>: How the same musical material is organized differently</li>
</ul>

<h2 id="best-practices-for-musical-visualization">Best Practices for Musical Visualization</h2>

<h3 id="1-choose-appropriate-scales">1. <strong>Choose Appropriate Scales</strong></h3>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># For timeline plots, use measure numbers, not time
# This aligns with how musicians think about structure
</span><span class="n">ax</span><span class="p">.</span><span class="nf">set_xlabel</span><span class="p">(</span><span class="sh">'</span><span class="s">Measure Number</span><span class="sh">'</span><span class="p">)</span>  <span class="c1"># ✅ Good
</span><span class="n">ax</span><span class="p">.</span><span class="nf">set_xlabel</span><span class="p">(</span><span class="sh">'</span><span class="s">Time (seconds)</span><span class="sh">'</span><span class="p">)</span>   <span class="c1"># ❌ Less useful for structural analysis
</span></code></pre></div></div>

<h3 id="2-include-contextual-markers">2. <strong>Include Contextual Markers</strong></h3>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Add section markers, key changes, tempo markings
</span><span class="k">for</span> <span class="n">section</span><span class="p">,</span> <span class="n">measure</span> <span class="ow">in</span> <span class="n">text_expressions</span><span class="p">.</span><span class="nf">items</span><span class="p">():</span>
    <span class="n">ax</span><span class="p">.</span><span class="nf">axvline</span><span class="p">(</span><span class="n">x</span><span class="o">=</span><span class="n">measure</span><span class="p">,</span> <span class="n">color</span><span class="o">=</span><span class="sh">'</span><span class="s">black</span><span class="sh">'</span><span class="p">,</span> <span class="n">linestyle</span><span class="o">=</span><span class="sh">'</span><span class="s">--</span><span class="sh">'</span><span class="p">,</span> 
              <span class="n">label</span><span class="o">=</span><span class="n">section</span><span class="p">,</span> <span class="n">alpha</span><span class="o">=</span><span class="mf">0.5</span><span class="p">)</span>
</code></pre></div></div>

<h3 id="3-make-plots-reproducible">3. <strong>Make Plots Reproducible</strong></h3>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Set random seed for any stochastic elements
</span><span class="n">np</span><span class="p">.</span><span class="n">random</span><span class="p">.</span><span class="nf">seed</span><span class="p">(</span><span class="mi">42</span><span class="p">)</span>

<span class="c1"># Use consistent styling
</span><span class="n">plt</span><span class="p">.</span><span class="n">style</span><span class="p">.</span><span class="nf">use</span><span class="p">(</span><span class="sh">'</span><span class="s">seaborn-v0_8-whitegrid</span><span class="sh">'</span><span class="p">)</span>  <span class="c1"># or your preferred style
</span></code></pre></div></div>

<h3 id="4-export-at-high-resolution">4. <strong>Export at High Resolution</strong></h3>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># For publications, use high DPI
</span><span class="n">plt</span><span class="p">.</span><span class="nf">savefig</span><span class="p">(</span><span class="n">output_path</span><span class="p">,</span> <span class="n">dpi</span><span class="o">=</span><span class="mi">300</span><span class="p">,</span> <span class="n">bbox_inches</span><span class="o">=</span><span class="sh">'</span><span class="s">tight</span><span class="sh">'</span><span class="p">)</span>
</code></pre></div></div>

<h3 id="5-consider-your-audience">5. <strong>Consider Your Audience</strong></h3>

<ul>
  <li><strong>Musicians</strong>: Focus on measure numbers, section labels, musical terminology</li>
  <li><strong>Researchers</strong>: Include statistical measures, confidence intervals, error bars</li>
  <li><strong>General audience</strong>: Simplify, add explanations, use intuitive color schemes</li>
</ul>

<h2 id="common-pitfalls-and-solutions">Common Pitfalls and Solutions</h2>

<h3 id="problem-overlapping-elements">Problem: Overlapping Elements</h3>

<p><strong>Solution</strong>: Use transparency and adjust spacing</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">ax</span><span class="p">.</span><span class="nf">bar</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">alpha</span><span class="o">=</span><span class="mf">0.7</span><span class="p">,</span> <span class="n">width</span><span class="o">=</span><span class="mf">0.8</span><span class="p">)</span>  <span class="c1"># Transparency helps
</span><span class="n">plt</span><span class="p">.</span><span class="nf">tight_layout</span><span class="p">()</span>  <span class="c1"># Adjust spacing automatically
</span></code></pre></div></div>

<h3 id="problem-too-many-motifs">Problem: Too Many Motifs</h3>

<p><strong>Solution</strong>: Group or filter</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># Show only top N motifs
</span><span class="n">top_motifs</span> <span class="o">=</span> <span class="nf">sorted</span><span class="p">(</span><span class="n">motif_counts</span><span class="p">.</span><span class="nf">items</span><span class="p">(),</span> 
                   <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="nf">sum</span><span class="p">(</span><span class="n">x</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="nf">values</span><span class="p">()),</span> 
                   <span class="n">reverse</span><span class="o">=</span><span class="bp">True</span><span class="p">)[:</span><span class="mi">5</span><span class="p">]</span>
</code></pre></div></div>

<h3 id="problem-inconsistent-colors">Problem: Inconsistent Colors</h3>

<p><strong>Solution</strong>: Create a color mapping dictionary</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">motif_colors</span> <span class="o">=</span> <span class="p">{</span><span class="n">motif</span><span class="p">:</span> <span class="n">color</span> <span class="k">for</span> <span class="n">motif</span><span class="p">,</span> <span class="n">color</span> <span class="ow">in</span> 
                <span class="nf">zip</span><span class="p">(</span><span class="n">unique_motifs</span><span class="p">,</span> <span class="nf">create_colormap</span><span class="p">(</span><span class="nf">len</span><span class="p">(</span><span class="n">unique_motifs</span><span class="p">)))}</span>
<span class="c1"># Use motif_colors[motif] consistently across all plots
</span></code></pre></div></div>

<h2 id="integration-with-analysis-pipeline">Integration with Analysis Pipeline</h2>

<p>Here’s how visualization fits into a complete analysis workflow:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># 1. Load and analyze
</span><span class="n">score</span> <span class="o">=</span> <span class="nf">load_score</span><span class="p">(</span><span class="sh">"</span><span class="s">Btaihi_Iraq_Ajam.mxl</span><span class="sh">"</span><span class="p">)</span>
<span class="n">melody</span> <span class="o">=</span> <span class="nf">extract_melody</span><span class="p">(</span><span class="n">score</span><span class="p">)</span>
<span class="n">motifs</span> <span class="o">=</span> <span class="nf">identify_motifs</span><span class="p">(</span><span class="n">melody</span><span class="p">,</span> <span class="n">min_length</span><span class="o">=</span><span class="mi">3</span><span class="p">,</span> <span class="n">max_length</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span>

<span class="c1"># 2. Process and count
</span><span class="n">motif_counts</span> <span class="o">=</span> <span class="nf">identify_unique_motifs</span><span class="p">(</span><span class="n">melody</span><span class="p">,</span> <span class="n">normalize_octave</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="n">text_expressions</span> <span class="o">=</span> <span class="nf">extract_text_expressions</span><span class="p">(</span><span class="n">score</span><span class="p">)</span>

<span class="c1"># 3. Visualize
</span><span class="nf">plot_motif_distribution</span><span class="p">(</span><span class="n">motifs</span><span class="p">,</span> 
                       <span class="n">title</span><span class="o">=</span><span class="sh">"</span><span class="s">Motif Length Distribution</span><span class="sh">"</span><span class="p">,</span>
                       <span class="n">output_path</span><span class="o">=</span><span class="sh">"</span><span class="s">plots/distribution.png</span><span class="sh">"</span><span class="p">)</span>

<span class="nf">plot_motif_timeline</span><span class="p">(</span><span class="n">score</span><span class="p">,</span> <span class="n">motif_counts</span><span class="p">,</span> <span class="n">text_expressions</span><span class="p">,</span>
                    <span class="n">filename</span><span class="o">=</span><span class="sh">"</span><span class="s">Btaihi_Iraq_Ajam</span><span class="sh">"</span><span class="p">,</span>
                    <span class="n">output_path</span><span class="o">=</span><span class="sh">"</span><span class="s">plots/timeline.png</span><span class="sh">"</span><span class="p">)</span>
</code></pre></div></div>

<h2 id="conclusion">Conclusion</h2>

<p>Effective visualization is essential for computational musicology research. The functions we’ve explored provide:</p>

<ul>
  <li><strong>Distribution analysis</strong>: Understanding motif characteristics</li>
  <li><strong>Temporal visualization</strong>: Seeing patterns across time/structure</li>
  <li><strong>Color mapping</strong>: Distinguishing multiple motifs clearly</li>
</ul>

<p>These visualizations transform raw motif data into insights about musical structure, style, and development. Combined with the <a href="/blog/musical-score-motif-analysis/">motif identification methods</a> from the previous post, you have a complete toolkit for computational motif analysis.</p>

<p>For complete implementations and interactive notebooks, see the <a href="/notebooks/arab-andal-motif-dev-main/">Arab-Andalusian Motif Development Analysis</a> and the <a href="https://github.com/oriolcolomefont/arab-andal-motif-dev">GitHub repository</a>.</p>

<h2 id="further-reading">Further Reading</h2>

<ul>
  <li><a href="https://matplotlib.org/stable/contents.html">Matplotlib Documentation</a></li>
  <li><a href="https://seaborn.pydata.org/">Seaborn Statistical Visualization</a></li>
  <li><a href="https://colorbrewer2.org/">ColorBrewer: Color Advice for Maps</a></li>
  <li><a href="https://plotly.com/python/">Plotly Interactive Visualization</a></li>
</ul>

<hr />

<p><em>This post is part of a series on computational musicology and music information retrieval. Read the <a href="/blog/musical-score-motif-analysis/">previous post on motif identification</a> and explore the <a href="/notebooks/arab-andal-motif-dev-main/">interactive notebook</a> for hands-on examples.</em></p>]]></content><author><name>Oriol Colomé Font</name></author><category term="Music Information Retrieval" /><category term="Computational Musicology" /><category term="Data Visualization" /><category term="python" /><category term="matplotlib" /><category term="music21" /><category term="data-visualization" /><category term="motifs" /><category term="music-analysis" /><category term="computational-musicology" /><summary type="html"><![CDATA[Learn how to create effective visualizations for musical motif analysis, including distribution plots, timeline visualizations, and color mapping strategies for computational musicology research.]]></summary></entry><entry><title type="html">Deep Learning Ramp-Up: Starting My Journey from Linear Regression to GPT-2 Scale</title><link href="https://oriolcolomefont.github.io/blog/deep-learning-ramp-up-intro/" rel="alternate" type="text/html" title="Deep Learning Ramp-Up: Starting My Journey from Linear Regression to GPT-2 Scale" /><published>2025-01-08T00:00:00+00:00</published><updated>2025-01-08T00:00:00+00:00</updated><id>https://oriolcolomefont.github.io/blog/deep-learning-ramp-up-intro</id><content type="html" xml:base="https://oriolcolomefont.github.io/blog/deep-learning-ramp-up-intro/"><![CDATA[<h2 id="embarking-on-a-deep-learning-journey">Embarking on a Deep Learning Journey</h2>

<p>After successfully working through Sebastian Raschka’s LLM series, I’m excited to dive into another comprehensive learning journey: <strong>Jacob Buckman’s Deep Learning Ramp-Up curriculum</strong>. This structured approach will take me from the fundamentals of linear regression all the way to training GPT-2 scale models on multiple GPUs.</p>

<h2 id="why-this-curriculum">Why This Curriculum?</h2>

<p>Jacob Buckman’s ramp-up is particularly appealing because it:</p>

<ul>
  <li><strong>Builds from first principles</strong>: Starting with manual backpropagation in NumPy</li>
  <li><strong>Progressive complexity</strong>: Each exercise builds naturally on the previous one</li>
  <li><strong>Real-world applications</strong>: Moving from synthetic data to MNIST, ImageNet, and Shakespeare</li>
  <li><strong>Performance focus</strong>: GPU optimization and scaling considerations</li>
  <li><strong>Comprehensive coverage</strong>: From basic regression to state-of-the-art architectures</li>
</ul>

<h2 id="the-18-exercise-roadmap">The 18-Exercise Roadmap</h2>

<p>The curriculum is structured into three main phases:</p>

<h3 id="phase-1-foundations-exercises-1-6">Phase 1: Foundations (Exercises 1-6)</h3>
<p>Starting with synthetic data and building core understanding:</p>
<ol>
  <li><strong>Linear regression with NumPy</strong> - Manual backpropagation</li>
  <li><strong>Linear regression with PyTorch</strong> - Automatic differentiation</li>
  <li><strong>Vector input regression</strong> - Scaling to higher dimensions</li>
  <li><strong>Classification with softmax</strong> - Categorical outputs</li>
  <li><strong>Single feedforward layer</strong> - First neural networks</li>
  <li><strong>Deep feedforward networks</strong> - Multiple hidden layers</li>
</ol>

<h3 id="phase-2-real-data--advanced-architectures-exercises-7-13">Phase 2: Real Data &amp; Advanced Architectures (Exercises 7-13)</h3>
<p>Moving to real datasets and sophisticated models:</p>
<ol>
  <li><strong>MNIST classification</strong> - Image recognition</li>
  <li><strong>Adam optimizer</strong> - Advanced optimization</li>
  <li><strong>Convolutional networks</strong> - Spatial feature learning</li>
  <li><strong>ResNet architecture</strong> - Residual connections</li>
  <li><strong>Shakespeare feedforward</strong> - Sequence modeling</li>
  <li><strong>Autoregressive sampling</strong> - Text generation</li>
  <li><strong>Causal transformer</strong> - Attention mechanisms</li>
</ol>

<h3 id="phase-3-scale--performance-exercises-14-18">Phase 3: Scale &amp; Performance (Exercises 14-18)</h3>
<p>GPU optimization and large-scale training:</p>
<ol>
  <li><strong>GPU optimization</strong> - Performance tuning</li>
  <li><strong>ImageNet ResNet</strong> - Large-scale image classification</li>
  <li><strong>GPU transformer</strong> - Accelerated sequence modeling</li>
  <li><strong>Multi-GPU training</strong> - Distributed computing</li>
  <li><strong>GPT-2 scale training</strong> - Large language models</li>
</ol>

<h2 id="my-approach">My Approach</h2>

<p>As with my LLM series, I’ll be documenting this journey with:</p>

<h3 id="-music-technology-connections">🎵 Music Technology Connections</h3>
<p>Drawing parallels between neural networks and audio processing techniques I’ve used in MIR research.</p>

<h3 id="-deep-experiments">🔬 Deep Experiments</h3>
<p>Going beyond the basic exercises to explore:</p>
<ul>
  <li>Different activation functions and their effects</li>
  <li>Regularization techniques and their impact</li>
  <li>Visualization of learned representations</li>
  <li>Performance comparisons across architectures</li>
</ul>

<h3 id="-interactive-visualizations">📊 Interactive Visualizations</h3>
<p>Creating plots and diagrams to build intuition about:</p>
<ul>
  <li>Loss landscapes and optimization dynamics</li>
  <li>Feature maps in convolutional layers</li>
  <li>Attention patterns in transformers</li>
  <li>Training dynamics across different scales</li>
</ul>

<h3 id="-honest-reflections">💭 Honest Reflections</h3>
<p>Documenting the challenges, “aha” moments, and insights gained along the way.</p>

<h2 id="reference-materials">Reference Materials</h2>

<p>The curriculum references several excellent resources:</p>

<ul>
  <li><strong><a href="https://d2l.ai/">D2L.ai</a></strong> - Interactive deep learning textbook</li>
  <li><strong><a href="https://fleuret.org/public/lbdl.pdf">Learning by Doing in Deep Learning</a></strong> - François Fleuret’s comprehensive guide</li>
  <li><strong><a href="https://karpathy.github.io/2015/05/21/rnn-effectiveness/">The Unreasonable Effectiveness of RNNs</a></strong> - Andrej Karpathy’s classic post</li>
  <li><strong><a href="https://www.youtube.com/watch?v=zjkBMFhNj_g">3Blue1Brown Neural Networks</a></strong> - Visual intuition building</li>
  <li><strong><a href="https://www.youtube.com/@statquest">StatQuest</a></strong> - Statistical concepts explained clearly</li>
</ul>

<h2 id="getting-started">Getting Started</h2>

<p>I’ll be maintaining all code and experiments in a dedicated <a href="https://github.com/oriolcolomefont/deep-learning-ramp-up">GitHub repository</a>, with each exercise in its own folder for easy navigation and reference.</p>

<p>The first exercise - implementing linear regression with manual backpropagation in NumPy - is particularly exciting because it forces a deep understanding of the mathematical foundations that are often abstracted away in modern frameworks.</p>

<h2 id="whats-next">What’s Next</h2>

<p>I’m planning to work through approximately one exercise per week, allowing time for:</p>
<ul>
  <li>Thorough understanding of each concept</li>
  <li>Additional experiments and explorations</li>
  <li>Detailed documentation and visualization</li>
  <li>Connecting concepts to my background in music technology</li>
</ul>

<p>This journey will complement my LLM series perfectly, providing the foundational understanding needed to appreciate the sophisticated architectures used in modern language models.</p>

<hr />

<p><em>Follow along as I work through this comprehensive deep learning curriculum, sharing insights, challenges, and connections to music technology along the way.</em></p>

<p><strong>Tags</strong>: #DeepLearning #MachineLearning #PyTorch #NeuralNetworks #AI #LearningJourney</p>]]></content><author><name>Oriol Colomé Font</name></author><category term="Deep Learning" /><category term="Machine Learning" /><category term="deep-learning-ramp-up" /><category term="neural networks" /><category term="pytorch" /><category term="machine learning" /><category term="AI" /><summary type="html"><![CDATA[Beginning my deep learning journey through Jacob Buckman's comprehensive ramp-up curriculum, from basic linear regression to advanced transformer architectures.]]></summary></entry><entry><title type="html">Building a modern personal website: lessons learned</title><link href="https://oriolcolomefont.github.io/blog/test-post/" rel="alternate" type="text/html" title="Building a modern personal website: lessons learned" /><published>2025-01-08T00:00:00+00:00</published><updated>2025-01-08T00:00:00+00:00</updated><id>https://oriolcolomefont.github.io/blog/test-post</id><content type="html" xml:base="https://oriolcolomefont.github.io/blog/test-post/"><![CDATA[<h2 id="the-journey-to-a-modern-web-presence">The Journey to a Modern Web Presence</h2>

<p>A strong digital presence is no longer optional—it’s foundational. Whether you’re aiming to advance your career, build a brand, or simply showcase your work, your website is now the first touchpoint for most people.</p>

<p>After years in music technology, I finally created a personal website that not only showcases my skills but is maintainable, accessible, and performant.</p>

<h2 id="why-jekyll--github-pages">Why Jekyll + GitHub Pages?</h2>

<h3 id="embracing-static-generation">Embracing Static Generation</h3>

<p>Static site generators like Jekyll have become essential for modern, lightweight websites:</p>

<ul>
  <li><strong>Performance</strong>: Instant load from pre-rendered HTML—no database, no lag.</li>
  <li><strong>Security</strong>: With no backend logic exposed, security risks are minimal.</li>
  <li><strong>Cost</strong>: GitHub Pages provides free, reliable hosting, including custom domains.</li>
  <li><strong>Simplicity</strong>: The infrastructure is minimal—just focus on your content.</li>
</ul>

<p>Jekyll, which powers GitHub Pages out of the box, was my choice for several reasons:</p>

<ul>
  <li>Mature plugin ecosystem</li>
  <li>Liquid templating for flexible layouts</li>
  <li>Markdown for natural content writing</li>
  <li>Native support for posts, collections, and data-driven pages</li>
</ul>

<h2 id="design-philosophy">Design Philosophy</h2>

<h3 id="less-but-better">Less, but Better</h3>

<p>I leaned into a minimalist, modern SaaS-inspired style (think: Linear, Vercel). Key tenets:</p>

<ol>
  <li><strong>Whitespace</strong>: Let content breathe.</li>
  <li><strong>Typography</strong>: Rely on system fonts for speed—no webfont lag.</li>
  <li><strong>Color</strong>: Keep things neutral, with modest accents to highlight important elements.</li>
  <li><strong>Motion</strong>: Use animation sparingly, only to improve clarity or focus.</li>
</ol>

<h3 id="accessibility-is-non-negotiable">Accessibility Is Non-Negotiable</h3>

<ul>
  <li>Semantic, standards-based HTML everywhere</li>
  <li>ARIA labels on interactive elements</li>
  <li>Keyboard navigability for all UI</li>
  <li>Respects user motion preferences (reduced motion)</li>
  <li>Meets high contrast ratios for legibility</li>
</ul>

<h2 id="technical-approach">Technical Approach</h2>

<h3 id="tailwind-css-from-cdn-to-purged-builds">Tailwind CSS: From CDN to Purged Builds</h3>

<p>Initially, I explored using Tailwind via CDN, but that quickly proved inefficient:</p>

<ul>
  <li><strong>Massive bundle</strong>: Unused utilities ballooned CSS sizes (~3MB unminified)</li>
  <li><strong>Sluggish loads</strong>: Longer time-to-interactive</li>
  <li><strong>Security (CSP)</strong>: Requires <code class="language-plaintext highlighter-rouge">unsafe-inline</code>, which is best avoided</li>
</ul>

<p><strong>Current Status:</strong><br />
I’ve adopted a proper Tailwind build pipeline with PurgeCSS. Now, unused styles are stripped at build time—measuring in under 20KB for the entire site.</p>

<h3 id="modular-with-jekyll-includes">Modular with Jekyll Includes</h3>

<p>Componentization is critical for maintainability. Jekyll’s include tag makes it easy:</p>

<div class="language-liquid highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&amp;#123;% include project-card.html 
   title=item.title 
   description=item.description 
   tech_stack=item.tech_stack %&amp;#125;
</code></pre></div></div>

<p>Instead of copy-pasting markup, reusable components now drive the site—much like React/Vue, but without a JS runtime cost.</p>

<h2 id="blog-features">Blog Features</h2>

<h3 id="elevating-user-experience">Elevating User Experience</h3>

<p>A blog today should be more than a reverse-chronological list. I’ve built:</p>

<ul>
  <li><strong>Client-side search</strong> for near-instant results</li>
  <li><strong>Tags and categories</strong> for real information architecture</li>
  <li><strong>Related posts</strong> to increase engagement</li>
  <li><strong>Dynamic Table of Contents</strong> for long-form posts (see sidebar on desktop)</li>
  <li><strong>Estimated reading time</strong> auto-generated per post</li>
</ul>

<p>These features are powered via a combination of Liquid templates, includes, data files, and light JavaScript.</p>

<h2 id="performance-optimization">Performance Optimization</h2>

<h3 id="current-lighthouse-scores">Current Lighthouse Scores</h3>

<p>Continuous focus on performance pays off:</p>

<ul>
  <li><strong>Performance</strong>: 95+</li>
  <li><strong>Accessibility</strong>: 100</li>
  <li><strong>Best Practices</strong>: 100</li>
  <li><strong>SEO</strong>: 100</li>
</ul>

<p><em>(You can check actual numbers in the footer or with Chrome DevTools Lighthouse)</em></p>

<h3 id="behind-the-scenes">Behind the Scenes</h3>

<ol>
  <li><strong>Images</strong>: All images use <code class="language-plaintext highlighter-rouge">loading="lazy"</code>, WebP where possible, and responsive <code class="language-plaintext highlighter-rouge">srcset</code>.</li>
  <li><strong>CSS</strong>: Fully-purged Tailwind, with critical CSS inlined for perceived speed.</li>
  <li><strong>Fonts</strong>: No external webfonts—the system stack ensures speed and privacy.</li>
  <li><strong>JavaScript</strong>: Minimal, deferred, only for UX extras like ToC and search.</li>
  <li><strong>Caching</strong>: Relying on GitHub Pages’ built-in static caching.</li>
</ol>

<h2 id="content-management">Content Management</h2>

<h3 id="the-markdown-publishing-flow">The Markdown Publishing Flow</h3>

<p>Publishing content is now as simple as:</p>

<ol>
  <li>Create a Markdown file in <code class="language-plaintext highlighter-rouge">_posts/</code></li>
  <li>Fill in frontmatter (title, date, tags, etc.)</li>
  <li>Commit and push to GitHub</li>
  <li>GitHub Actions builds and deploys everything automatically</li>
</ol>

<p>There’s no CMS, no database, and near-zero overhead for publishing or updating content.</p>

<h2 id="lessons-learned">Lessons Learned</h2>

<h3 id="what-works-well">What Works Well</h3>

<ul>
  <li><strong>Static-first</strong>: Ultra-fast and secure</li>
  <li><strong>Includes/components</strong>: Code stays dry and easy to manage</li>
  <li><strong>YAML/JSON data files</strong>: One place to update structured data (like music projects)</li>
  <li><strong>“Push-to-deploy”</strong>: Each update is visible to the world in minutes</li>
</ul>

<h3 id="what-id-change-next-time">What I’d Change Next Time</h3>

<ul>
  <li><strong>Start Tailwind build pipeline from day one</strong> to avoid future code churn</li>
  <li><strong>Create more demo/test content</strong> to better stress-test blog and category features</li>
  <li><strong>Analytics integration</strong>: Should have been set up at launch, not as an afterthought</li>
  <li><strong>Dark mode</strong>: It’s a user expectation now, and already implemented site-wide via Tailwind’s dark mode utilities</li>
</ul>

<h2 id="looking-forward">Looking Forward</h2>

<p>My site will keep evolving. Planned improvements:</p>

<ul>
  <li>More deep-dives and case studies on music tech and MIR</li>
  <li>Dedicated project pages and interactive demos</li>
  <li>Newsletter (see footer to sign up)</li>
  <li>Commenting via third-party (privacy-safe) integrations</li>
</ul>

<h2 id="conclusion">Conclusion</h2>

<p>Modern personal websites don’t need complex stacks or paid hosting. With Jekyll, Tailwind CSS, and GitHub Pages you get a performant, scalable site—while retaining full control over your content and tech.</p>

<p>By focusing on accessibility, performance, and clarity, the site offers a better user experience than most all-in-one solutions or heavy JS frameworks.</p>

<hr />

<p><em>Curious about the implementation? <a href="https://github.com/oriolcolomefont/oriolcolomefont.github.io">See the full source code on GitHub.</a></em></p>

<p><strong>Related Topics:</strong><br />
#WebDevelopment #Jekyll #TailwindCSS #Performance #Accessibility #StaticSites</p>]]></content><author><name>Oriol Colomé Font</name></author><category term="Industry Insights" /><category term="Project Management" /><category term="web development" /><category term="Jekyll" /><category term="Tailwind CSS" /><category term="portfolio" /><category term="personal branding" /><summary type="html"><![CDATA[Reflections on building a modern, performant personal website with Jekyll and Tailwind CSS, optimized for GitHub Pages.]]></summary></entry></feed>