build_tools.syllable_walk_tui.modules.analyzer.screen
=====================================================
.. py:module:: build_tools.syllable_walk_tui.modules.analyzer.screen
.. autoapi-nested-parse::
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
----------
.. autoapisummary::
build_tools.syllable_walk_tui.modules.analyzer.screen.BAR_WIDTH
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
Classes
-------
.. autoapisummary::
build_tools.syllable_walk_tui.modules.analyzer.screen.TerrainDisplay
build_tools.syllable_walk_tui.modules.analyzer.screen.WeightsModal
build_tools.syllable_walk_tui.modules.analyzer.screen.FeatureSaturationDisplay
build_tools.syllable_walk_tui.modules.analyzer.screen.MetricsDisplay
build_tools.syllable_walk_tui.modules.analyzer.screen.AnalysisScreen
Functions
---------
.. autoapisummary::
build_tools.syllable_walk_tui.modules.analyzer.screen.format_delta
build_tools.syllable_walk_tui.modules.analyzer.screen.render_terrain_bar
build_tools.syllable_walk_tui.modules.analyzer.screen.render_exemplars_line
build_tools.syllable_walk_tui.modules.analyzer.screen.format_weight_chip
build_tools.syllable_walk_tui.modules.analyzer.screen.format_weights_row
Module Contents
---------------
.. py:data:: BAR_WIDTH
:value: 30
.. py:data:: BAR_FILLED
:value: '█'
.. py:data:: BAR_EMPTY
:value: '░'
.. py:data:: FEATURE_SHORT_NAMES
:type: dict[str, str]
.. py:function:: format_delta(score)
Format score as delta from neutral (0.5).
:param score: Value from 0.0 to 1.0
:returns: Formatted string like "+0.047" or "-0.023"
.. py:function:: render_terrain_bar(score, label)
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.
:param score: Value from 0.0 to 1.0
:param label: Text label to show after the bar (e.g., "JAGGED")
:returns: Formatted string with bar, label, and delta
.. py:function:: render_exemplars_line(exemplars, low_label, high_label)
Render exemplar syllables for both poles of an axis.
:param exemplars: PoleExemplars containing syllables from each pole, or None
:param low_label: Label for low pole (e.g., "round")
:param high_label: Label for high pole (e.g., "jagged")
:returns: mala, luno jagged: krask, thrix"
:rtype: Formatted string like " round
.. py:function:: format_weight_chip(feature, weight, selected = False)
Format a weight as a compact chip for display.
:param feature: Feature name
:param weight: Weight value
:param selected: If True, highlight this chip
:returns: -0.8]" or ">>liq:-0.8<<" if selected
:rtype: Formatted chip like "[liq
.. py:function:: format_weights_row(axis_weights, axis_index, selected_axis, selected_weight)
Format all weights for an axis as a single row.
:param axis_weights: The weights for this axis
:param axis_index: Index of this axis (0=shape, 1=craft, 2=space)
:param selected_axis: Currently selected axis index
:param selected_weight: Currently selected weight index within the axis
:returns: Formatted string with all weight chips
.. py:class:: TerrainDisplay(terrain = None)
Bases: :py:obj:`textual.containers.Vertical`
Widget for displaying terrain visualization bars.
Initialize terrain display.
:param terrain: Computed terrain metrics, or None if not available
.. py:attribute:: DEFAULT_CSS
:value: Multiline-String
.. raw:: html
Show Value
.. code-block:: python
"""
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;
}
"""
.. raw:: html
Default TCSS.
.. py:attribute:: terrain
:value: None
.. py:method:: compose()
Create terrain display layout.
.. py:class:: WeightsModal(weights_a, weights_b, on_close_callback = None)
Bases: :py:obj:`textual.screen.Screen`
Modal dialog for editing terrain weights for Patch A and Patch B independently.
Initialize weights modal.
:param weights_a: TerrainWeights for Patch A (modified in place)
:param weights_b: TerrainWeights for Patch B (modified in place)
:param on_close_callback: Function to call when modal closes
.. py:attribute:: BINDINGS
:value: [('escape', 'close_modal', 'Close'), ('q', 'close_modal', 'Close'), ('tab', 'next_weight', 'Next...
A list of key bindings.
.. py:attribute:: DEFAULT_CSS
:value: Multiline-String
.. raw:: html
Show Value
.. code-block:: python
"""
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;
}
"""
.. raw:: html
Default TCSS.
.. py:attribute:: weights_a
.. py:attribute:: weights_b
.. py:attribute:: on_close_callback
:value: None
.. py:attribute:: selected_patch
:value: 0
.. py:attribute:: selected_axis
:value: 0
.. py:attribute:: selected_weight
:value: 0
.. py:method:: compose()
Create weights dialog layout.
.. py:method:: on_mount()
Initialize display after mounting.
.. py:method:: action_close_modal()
Close the modal and trigger callback.
.. py:method:: action_next_weight()
Navigate to next weight (Tab).
.. py:method:: action_prev_weight()
Navigate to previous weight (Shift+Tab).
.. py:method:: action_decrease_weight()
Decrease selected weight by 0.1 (j key).
.. py:method:: action_increase_weight()
Increase selected weight by 0.1 (k key).
.. py:method:: action_reset_weights()
Reset current patch's weights to defaults.
.. py:class:: FeatureSaturationDisplay(metrics = None)
Bases: :py:obj:`textual.containers.Vertical`
Widget for displaying feature saturation metrics.
Initialize feature saturation display.
.. py:attribute:: DEFAULT_CSS
:value: Multiline-String
.. raw:: html
Show Value
.. code-block:: python
"""
FeatureSaturationDisplay {
width: auto;
height: auto;
}
FeatureSaturationDisplay .feat-header {
text-style: bold;
color: $text;
}
FeatureSaturationDisplay .feat-row {
color: $text;
}
FeatureSaturationDisplay .feat-label {
color: $text-muted;
}
"""
.. raw:: html
Default TCSS.
.. py:attribute:: metrics
:value: None
.. py:method:: compose()
Create feature saturation display.
.. py:class:: MetricsDisplay(patch_name, metrics = None)
Bases: :py:obj:`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
.. attribute:: patch_name
Identifier "A" or "B" for the corpus patch
.. attribute:: metrics
CorpusShapeMetrics instance or None if not loaded
Initialize metrics display.
:param patch_name: "A" or "B" to identify the patch
:param metrics: Computed corpus shape metrics, or None if not loaded
.. py:attribute:: DEFAULT_CSS
:value: Multiline-String
.. raw:: html
Show Value
.. code-block:: python
"""
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;
}
"""
.. raw:: html
Default TCSS.
.. py:attribute:: patch_name
.. py:attribute:: metrics
:value: None
.. py:method:: compose()
Create metrics display layout.
.. py:class:: 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)
Bases: :py:obj:`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.
:param metrics_a: Pre-computed metrics for Patch A, or None if not loaded
:param metrics_b: Pre-computed metrics for Patch B, or None if not loaded
:param corpus_path_a: Path to Patch A corpus directory
:param corpus_path_b: Path to Patch B corpus directory
:param export_dir: Directory for exports (defaults to _working/)
:param annotated_data_a: Optional annotated data for Patch A (for exemplars)
:param annotated_data_b: Optional annotated data for Patch B (for exemplars)
.. note::
Metrics should be computed by the app before pushing this screen,
as self.app is not available during compose().
.. py:attribute:: BINDINGS
:value: [('escape', 'close_screen', 'Close'), ('q', 'close_screen', 'Close'), ('e', 'export_metrics',...
A list of key bindings.
.. py:attribute:: DEFAULT_CSS
:value: Multiline-String
.. raw:: html
Show Value
.. code-block:: python
"""
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;
}
"""
.. raw:: html
Default TCSS.
.. py:attribute:: metrics_a
:value: None
.. py:attribute:: metrics_b
:value: None
.. py:attribute:: corpus_path_a
:value: None
.. py:attribute:: corpus_path_b
:value: None
.. py:attribute:: export_dir
.. py:attribute:: annotated_data_a
:value: None
.. py:attribute:: annotated_data_b
:value: None
.. py:attribute:: feature_saturation_a
.. py:attribute:: feature_saturation_b
.. py:attribute:: weights_a
.. py:attribute:: weights_b
.. py:method:: compose()
Create analysis screen layout.
.. py:method:: action_close_screen()
Close this screen and return to main view.
.. py:method:: action_export_metrics()
Export metrics to a text file.
.. py:method:: action_open_weights()
Open the weights editor modal.
.. py:method:: action_refresh_exemplars()
Resample exemplars with new RNG for variety.