build_tools.syllable_walk_tui.modules.analyzer.screen

Analysis screen modal component.

This module provides the AnalysisScreen modal for viewing corpus shape metrics. Displays raw, objective statistics about loaded corpora without interpretation.

Design Philosophy:
  • Raw numbers only, no value judgments

  • Observable facts about corpus structure

  • Users draw their own conclusions

  • Percentages are objective facts, not interpretations

Percentage Display Strategy:

Percentages are shown in parentheses after raw counts where they provide meaningful context:

  • Length distribution: Count with percentage of total inventory e.g., “2:30 (20.0%)” means 30 syllables of length 2, which is 20% of all syllables

  • Hapax rate: Count with percentage of total unique syllables e.g., “Hapax (freq=1): 456 (37.0%)” means 456 syllables appear only once, comprising 37% of the vocabulary

  • Top 5 frequency: Count with percentage of total occurrences e.g., “the: 500 (4.1%)” means the syllable “the” accounts for 4.1% of all syllable occurrences in the corpus

These percentages help users quickly understand: - How syllable lengths are distributed (length dist) - Vocabulary diversity / “long tail” characteristics (hapax rate) - Corpus concentration / Zipfian distribution (top N coverage)

Attributes

BAR_WIDTH

BAR_FILLED

BAR_EMPTY

FEATURE_SHORT_NAMES

Classes

TerrainDisplay

Widget for displaying terrain visualization bars.

WeightsModal

Modal dialog for editing terrain weights for Patch A and Patch B independently.

FeatureSaturationDisplay

Widget for displaying feature saturation metrics.

MetricsDisplay

Widget for displaying corpus shape metrics with percentages.

AnalysisScreen

Modal screen for viewing corpus shape metrics.

Functions

format_delta(score)

Format score as delta from neutral (0.5).

render_terrain_bar(score, label)

Render a terrain axis as an ASCII bar with pole labels.

render_exemplars_line(exemplars, low_label, high_label)

Render exemplar syllables for both poles of an axis.

format_weight_chip(feature, weight[, selected])

Format a weight as a compact chip for display.

format_weights_row(axis_weights, axis_index, ...)

Format all weights for an axis as a single row.

Module Contents

build_tools.syllable_walk_tui.modules.analyzer.screen.BAR_WIDTH = 30
build_tools.syllable_walk_tui.modules.analyzer.screen.BAR_FILLED = '█'
build_tools.syllable_walk_tui.modules.analyzer.screen.BAR_EMPTY = '░'
build_tools.syllable_walk_tui.modules.analyzer.screen.FEATURE_SHORT_NAMES: dict[str, str]
build_tools.syllable_walk_tui.modules.analyzer.screen.format_delta(score)[source]

Format score as delta from neutral (0.5).

Parameters:

score (float) – Value from 0.0 to 1.0

Returns:

Formatted string like “+0.047” or “-0.023”

Return type:

str

build_tools.syllable_walk_tui.modules.analyzer.screen.render_terrain_bar(score, label)[source]

Render a terrain axis as an ASCII bar with pole labels.

The bar shows position between two poles. Delta from neutral (0.5) is the key precision indicator.

Parameters:
  • score (float) – Value from 0.0 to 1.0

  • label (str) – Text label to show after the bar (e.g., “JAGGED”)

Returns:

Formatted string with bar, label, and delta

Return type:

str

build_tools.syllable_walk_tui.modules.analyzer.screen.render_exemplars_line(exemplars, low_label, high_label)[source]

Render exemplar syllables for both poles of an axis.

Parameters:
Returns:

mala, luno jagged: krask, thrix”

Return type:

Formatted string like “ round

build_tools.syllable_walk_tui.modules.analyzer.screen.format_weight_chip(feature, weight, selected=False)[source]

Format a weight as a compact chip for display.

Parameters:
  • feature (str) – Feature name

  • weight (float) – Weight value

  • selected (bool) – If True, highlight this chip

Returns:

-0.8]” or “>>liq:-0.8<<” if selected

Return type:

Formatted chip like “[liq

build_tools.syllable_walk_tui.modules.analyzer.screen.format_weights_row(axis_weights, axis_index, selected_axis, selected_weight)[source]

Format all weights for an axis as a single row.

Parameters:
Returns:

Formatted string with all weight chips

Return type:

str

class build_tools.syllable_walk_tui.modules.analyzer.screen.TerrainDisplay(terrain=None)[source]

Bases: textual.containers.Vertical

Widget for displaying terrain visualization bars.

Initialize terrain display.

Parameters:

terrain (build_tools.syllable_walk_tui.services.metrics.TerrainMetrics | None) – Computed terrain metrics, or None if not available

DEFAULT_CSS = Multiline-String
Show Value
"""
    TerrainDisplay {
        width: auto;
        height: auto;
        padding: 0 1;
    }

    TerrainDisplay .terrain-header {
        text-style: bold;
        color: $accent;
    }

    TerrainDisplay .terrain-row {
        color: $text;
    }

    TerrainDisplay .terrain-label {
        color: $text-muted;
    }

    TerrainDisplay .terrain-exemplars {
        color: $text-muted;
        text-style: italic;
    }
    """

Default TCSS.

terrain = None
compose()[source]

Create terrain display layout.

class build_tools.syllable_walk_tui.modules.analyzer.screen.WeightsModal(weights_a, weights_b, on_close_callback=None)[source]

Bases: textual.screen.Screen

Modal dialog for editing terrain weights for Patch A and Patch B independently.

Initialize weights modal.

Parameters:
BINDINGS = [('escape', 'close_modal', 'Close'), ('q', 'close_modal', 'Close'), ('tab', 'next_weight', 'Next...

A list of key bindings.

DEFAULT_CSS = Multiline-String
Show Value
"""
    WeightsModal {
        align: center middle;
        background: rgba(0, 0, 0, 0.7);
    }

    #weights-dialog {
        width: 100;
        height: auto;
        background: $surface;
        border: thick $accent;
        padding: 1 2;
    }

    .dialog-title {
        text-style: bold;
        color: $accent;
        text-align: center;
        width: 100%;
        margin-bottom: 1;
    }

    .patch-header {
        text-style: bold;
        color: $primary;
        margin-top: 1;
        text-align: center;
    }

    .axis-row {
        height: auto;
        width: 100%;
    }

    .axis-label {
        width: 8;
        color: $text-muted;
    }

    .weights-value {
        width: 1fr;
        color: $text;
    }

    .dialog-footer {
        color: $text-muted;
        text-align: center;
        margin-top: 1;
        border-top: solid $primary;
        padding-top: 1;
    }
    """

Default TCSS.

weights_a
weights_b
on_close_callback = None
selected_patch = 0
selected_axis = 0
selected_weight = 0
compose()[source]

Create weights dialog layout.

on_mount()[source]

Initialize display after mounting.

action_close_modal()[source]

Close the modal and trigger callback.

action_next_weight()[source]

Navigate to next weight (Tab).

action_prev_weight()[source]

Navigate to previous weight (Shift+Tab).

action_decrease_weight()[source]

Decrease selected weight by 0.1 (j key).

action_increase_weight()[source]

Increase selected weight by 0.1 (k key).

action_reset_weights()[source]

Reset current patch’s weights to defaults.

class build_tools.syllable_walk_tui.modules.analyzer.screen.FeatureSaturationDisplay(metrics=None)[source]

Bases: textual.containers.Vertical

Widget for displaying feature saturation metrics.

Initialize feature saturation display.

DEFAULT_CSS = Multiline-String
Show Value
"""
    FeatureSaturationDisplay {
        width: auto;
        height: auto;
    }

    FeatureSaturationDisplay .feat-header {
        text-style: bold;
        color: $text;
    }

    FeatureSaturationDisplay .feat-row {
        color: $text;
    }

    FeatureSaturationDisplay .feat-label {
        color: $text-muted;
    }
    """

Default TCSS.

metrics = None
compose()[source]

Create feature saturation display.

class build_tools.syllable_walk_tui.modules.analyzer.screen.MetricsDisplay(patch_name, metrics=None)[source]

Bases: textual.containers.Vertical

Widget for displaying corpus shape metrics with percentages.

Renders inventory, frequency, feature saturation, and terrain metrics for a single patch (A or B). Raw counts are displayed alongside derived percentages in parentheses where they provide meaningful context.

Display Format:

PATCH {A|B} ──────────────────────────────────────── INVENTORY

Total syllables: 1,234 Length min: 2 Length max: 8 Length mean: 3.45 Length median: 3.0 Length std: 1.23 Length dist: 2:120 (9.7%), 3:456 (37.0%), …

FREQUENCY

Total occurrences: 12,345 … Hapax (freq=1): 456 (37.0%) … Top 5 by frequency:

the: 500 (4.1%) and: 350 (2.8%) …

FEATURE SATURATION TERRAIN (side-by-side display)

Percentage Semantics:
  • Length dist %: Share of total inventory at each length

  • Hapax %: Proportion of vocabulary that appears only once

  • Top 5 %: Share of total occurrences for each top syllable

patch_name

Identifier “A” or “B” for the corpus patch

metrics

CorpusShapeMetrics instance or None if not loaded

Initialize metrics display.

Parameters:
DEFAULT_CSS = Multiline-String
Show Value
"""
    MetricsDisplay {
        width: 100%;
        height: auto;
        padding: 0 1;
    }

    MetricsDisplay .metrics-header {
        text-style: bold;
        color: $accent;
        margin-bottom: 0;
    }

    MetricsDisplay .metrics-subheader {
        text-style: bold;
        color: $text;
        margin-top: 1;
    }

    MetricsDisplay .metrics-row {
        color: $text;
    }

    MetricsDisplay .metrics-dim {
        color: $text-muted;
    }

    MetricsDisplay .feature-terrain-row {
        height: auto;
        margin-top: 1;
    }
    """

Default TCSS.

patch_name
metrics = None
compose()[source]

Create metrics display layout.

class build_tools.syllable_walk_tui.modules.analyzer.screen.AnalysisScreen(metrics_a=None, metrics_b=None, corpus_path_a=None, corpus_path_b=None, export_dir=None, annotated_data_a=None, annotated_data_b=None)[source]

Bases: textual.screen.Screen

Modal screen for viewing corpus shape metrics.

Displays raw, objective statistics about loaded corpora: - Inventory metrics (counts, lengths) - Frequency distribution metrics - Feature saturation per phonetic feature - Terrain visualization

Design Philosophy:

Raw numbers only, no interpretation or judgment. Users observe and draw their own conclusions.

Keybindings:

Esc: Close screen and return to main view q: Close screen e: Export metrics to text file w: Open weights editor modal

Initialize analysis screen with pre-computed metrics.

Parameters:

Note

Metrics should be computed by the app before pushing this screen, as self.app is not available during compose().

BINDINGS = [('escape', 'close_screen', 'Close'), ('q', 'close_screen', 'Close'), ('e', 'export_metrics',...

A list of key bindings.

DEFAULT_CSS = Multiline-String
Show Value
"""
    AnalysisScreen {
        background: $surface;
    }

    #analysis-header {
        dock: top;
        height: 1;
        background: $boost;
        color: $text;
        text-style: bold;
        text-align: center;
    }

    #analysis-content {
        width: 100%;
        height: 1fr;
    }

    .patch-metrics {
        width: 1fr;
        height: auto;
        border: solid $primary;
        overflow-y: auto;
    }

    #analysis-footer {
        dock: bottom;
        height: 1;
        background: $boost;
        color: $text;
        padding: 0 1;
        text-align: center;
    }
    """

Default TCSS.

metrics_a = None
metrics_b = None
corpus_path_a = None
corpus_path_b = None
export_dir
annotated_data_a = None
annotated_data_b = None
feature_saturation_a
feature_saturation_b
weights_a
weights_b
compose()[source]

Create analysis screen layout.

action_close_screen()[source]

Close this screen and return to main view.

action_export_metrics()[source]

Export metrics to a text file.

action_open_weights()[source]

Open the weights editor modal.

action_refresh_exemplars()[source]

Resample exemplars with new RNG for variety.