aegean.viz¶
viz ¶
One-line visualization helpers (the [viz] extra: matplotlib, imported lazily).
Convenience plots over the corpus model and the analysis layer — each function
draws one publication-ready-enough figure and returns the matplotlib Axes
(pass ax= to compose subplots; call .figure.savefig(...) to write a
file). These are conveniences, not a plotting framework: for anything bespoke,
take the numbers from aegean.analysis and plot them yourself.
Most functions take backend="matplotlib" (the default) or
backend="plotly". With "plotly" they return a Plotly Figure instead
of a matplotlib Axes (call .write_html(...) to save an interactive
page); Plotly is imported lazily and, if absent, raises a clear pointer to
pip install 'pyaegean[viz-interactive]'.
import aegean stays dependency-free — matplotlib (and Plotly) are imported
only inside the plotting calls, and a missing matplotlib raises a clear pointer
to pip install 'pyaegean[viz]'. From the shell: aegean plot ….
TimelineBin
dataclass
¶
One time bucket: start is the bin's first year (negative = BCE); count is the
number of documents whose parsed date midpoint falls in [start, start + bin_width).
Timeline
dataclass
¶
Timeline(bins: tuple[TimelineBin, ...], parsed: int, unparsed: int, total: int, bin_width: int)
The result of bucketing a corpus's documents over parsed dates.
bins are the non-empty buckets in chronological order; unparsed counts the
documents whose meta.period :func:parse_period could not read (never dropped —
always reported). unparsed_fraction is that count over total.
correspondence_layout ¶
correspondence_layout(points: Sequence[tuple[float, float]], *, percentile: float = 0.9, pad_factor: float = 1.1, floor: float = 1e-09) -> list[tuple[float, float]]
Scale CA coordinates into the box [-1, 1]² for legible plotting.
A correspondence-analysis axis is usually dominated by one or two outlier
points that, scaled by the global maximum, crush the rest of the cloud into a
thin band. This scales each axis independently to its percentile-th
absolute coordinate (×pad_factor) and pins points beyond that at the box
edge (±1). The picture then shows relative position along each axis, not
literal CA distances — state that in any caption.
plot_sign_frequencies ¶
Horizontal frequency bars — the aegean stats table as a figure.
kind="signs" (default) counts individual signs; kind="words" whole
words. Most frequent at the top.
plot_dispersion ¶
plot_dispersion(corpus: Any, *, kind: str = 'words', min_frequency: int = 2, annotate: int = 10, ax: Any = None) -> Any
Frequency (log x) against Gries' normalized DP (y).
The diagnostic read: bottom-right = frequent corpus-wide vocabulary;
top-right = frequent but concentrated items (formulaic or site/genre-bound
— on Aegean material usually the interesting quadrant). The annotate
most frequent items are labeled.
plot_keyness ¶
plot_keyness(target: Any, reference: Any, *, kind: str = 'words', top: int = 15, min_target: int = 2, ax: Any = None) -> Any
Diverging bars of the top-G² key items: log-ratio effect size,
right = overused in the target, left = underused. Bar labels carry G².
plot_collocation_network ¶
plot_collocation_network(corpus: Any, word: str | None = None, *, max_nodes: int = 24, min_count: int = 2, ax: Any = None) -> Any
A document-co-occurrence network of multi-sign words (circular layout).
Edges join words attested together in min_count+ documents; width and
opacity scale with the count. word restricts to that word's ego
network. Exploratory on undeciphered material: an edge is shared
context, not an asserted phrase or meaning.
plot_scansion ¶
A scansion grid for one verse line: syllables in metrical position, long (—) and short (⏑) marks, foot boundaries, and the caesura (‖).
line is Greek text (scanned via greek.scan_line) or an existing
LineScansion. Raises ScansionError if the text does not fit the
meter (synizesis is declined, never inferred).
plot_balance ¶
Accounting reconciliation at a glance: each checked total (KU-RO /
TO-SO) as computed sum (x) vs stated total (y). Points on the diagonal
balance; red points do not — the discrepancies worth a closer look. The
reconciliation inherits the heuristics of balance_check (section
boundaries are inferred), so treat outliers as leads, not verdicts.
plot_correspondence_analysis ¶
plot_correspondence_analysis(ca: CAResult, *, label_top: int = 12, ax: Any = None) -> Any
Correspondence-analysis biplot: rows (blue) and columns (amber) in one
plane, with per-axis percentile scaling so a single outlier can't flatten the
cloud (see :func:correspondence_layout). The heaviest label_top columns
and all rows are labelled. Shows relative position along each axis, not
literal CA distances.
plot_findspots ¶
A scatter of the corpus's find-sites: longitude (x) against latitude (y), marker size scaled by the number of inscriptions from each site, each point labelled with its site name and count.
Coordinates come from the bundled site gazetteer (:func:aegean.geo.site_coordinates,
stdlib — no [geo] extra needed to plot). Find-site labels are resolved through the
same whitespace-normalized index :mod:aegean.geo uses, so the plot's site and
inscription counts agree with :func:aegean.geo.to_geodataframe (a label split across
lines still maps, and raw-label variants of one gazetteer site aggregate into one
point). Sites absent from the gazetteer are dropped; if no site maps, the corpus has
nothing to place and a clear ValueError is raised (the CLI turns it into a one-line
message).
parse_period ¶
Best-effort parse of an origDate-style date string to a (start, end) year range,
BCE years negative and CE positive (e.g. "480—450 BCE" → (-480, -450),
"Third century BC" → (-300, -201), "II century C.E" → (101, 200),
"27 BC - 14 AD" → (-27, 14), "II-III century CE" → (101, 300)).
A range is split into sides and each side is read on its own era and century intent, so a
cross-era span keeps both signs; a side missing an era or the "century" word inherits it
from the other side ("100-90 BC", "II-III century CE"). Returns None when the string
carries no readable century or era-qualified year (a bare "Hellenistic" or "" is honestly
unparseable, not guessed). Half/quarter and hedge qualifiers ("Second half of", "Perhaps",
"Ca.") are ignored, and the whole century is returned. This is a heuristic for aggregate
binning, not a dating authority.
timeline_bins ¶
timeline_bins(corpus: Any, *, bin_width: int = 100) -> Timeline
Bucket a corpus's documents into bin_width-year bins by their parsed date.
Each document is placed by the midpoint of its :func:parse_period range; documents
with no readable date are counted in unparsed (never silently dropped). Default
bin_width=100 gives one bar per century.
plot_timeline ¶
plot_timeline(corpus: Any, *, bin_width: int = 100, backend: str = 'matplotlib', ax: Any = None) -> Any
Document counts over bin_width-year bins (default one bar per century), from the
best-effort dates in meta.period (see :func:parse_period).
The fraction of documents whose date could not be read is stated on the figure and
available on :func:timeline_bins — dates are never silently dropped. Raises
ValueError only for a corpus with no documents at all.
plot_sign_network ¶
plot_sign_network(corpus: Any, *, level: str = 'sign', scope: str = 'document', min_count: int = 1, max_nodes: int = 30, backend: str = 'matplotlib', ax: Any = None) -> Any
Render the corpus's co-occurrence graph (:func:aegean.analysis.graph.cooccurrence_graph)
with a deterministic, seedless frequency-ranked circular layout.
level ("sign"/"word"), scope ("document"/"line") and min_count
are passed straight to the graph builder; the max_nodes most frequent nodes are drawn.
Node size scales with corpus frequency, edge width with the shared-unit weight. Raises
ValueError when nothing co-occurs at the threshold. Exploratory: an edge is shared
context on undeciphered material, never an asserted phrase or meaning.