theHarmonicAlgorithm-3.1.0: Real-time harmonic progression generation for TidalCycles live performance
Safe HaskellNone
LanguageGHC2021

Harmonic.Rules.Import.Merge

Description

The stages of the ingestion pipeline that sit between the per-piece cadence expansion (Harmonic.Rules.Import.Transform) and the graph write (Harmonic.Rules.Import.Graph): normalising raw composer names to corpus keys, applying the curated allow-list, and merging per-composer transition maps into per-edge composer weight maps.

The composer-key contract

slug is the ingester's normaliser. The exporter (scripts/export_ycacl.R, normalize_composer) must apply the SAME rule: any curation list matched against keys produced under a different normalisation silently drops every composer whose two keys disagree. Any change here must be mirrored in the exporter.

Synopsis

Documentation

type ComposerPieces = Map Text (Map Text [ChordSlice]) Source #

Composer catalogues keyed by normalised (slug) composer name.

slug :: Text -> Text Source #

Normalise a raw corpus composer string to a graph composer key: lowercase, keep alphanumerics and spaces, then map spaces (and any other retained non-alphanumeric) to _.

This is the key under which every edge weight is stored and fetched (r.weights in Neo4j, parsed by Harmonic.Evaluation.Database.Query).

normalizeComposers :: YCACLData -> ComposerPieces Source #

Re-key the parsed corpus by slug, merging composers whose raw names normalise identically.

filterComposers :: [Text] -> [Text] -> ComposerPieces -> (ComposerPieces, [(Text, Int)]) Source #

Apply curation: an allow-list (empty admits everything) and an exclude-list. Returns the kept catalogues and the dropped keys (with piece counts), so the caller can REPORT every refusal instead of losing composers silently.

mergeComposerTransitions :: Map Text (Map Edge Double) -> [(Cadence, Cadence, ComposerWeights)] Source #

Merge per-composer transition probability maps into one map per edge, keyed by composer. Edges whose total weight is zero are excluded. Weights are SPARSE: a composer absent from an edge's map carries implicit weight 0 — the read side (resolveWeights) reads a missing key as 0, so dense zero-padding would only inflate the store.