Skip to content

lenzo-ka/ipakit

Repository files navigation

ipakit

CI PyPI Python versions License: BSD 2-Clause

A pure-Python IPA (International Phonetic Alphabet) phonetic toolkit: phonetic features, distances, natural classes, and conversion between IPA and CMU ARPABET, X-SAMPA, Kirshenbaum, and TIMIT notations.

  • Zero runtime dependencies — all phonetic data ships as XML in the package.
  • Typed (py.typed, mypy-strict clean).
  • Both a library and a CLI (ipakit).

Install

pip install ipakit

For development (tests, linters, and the X-SAMPA table tooling):

pip install -e ".[dev]"

Quick start (Python)

import ipakit

# Phonetic features and descriptions
ipakit.describe("p")            # 'voiceless bilabial plosive'
ipakit.features("p")            # {'manner': 'plosive', 'place': 'bilabial', ...}

# Phonetic distance (0.0 identical … 1.0 maximally different)
ipakit.distance("p", "b")       # 0.043   (differ only in voicing)
ipakit.nearest_phones("p", n=3) # [('ɸ', 0.005), ('f', 0.008), ('p͡f', 0.008)]
ipakit.word_similarity("kæt", "kæd")   # 0.986

# Tokenize / normalize (tie-bar affricates, diphthongs)
ipakit.tokenize("t͡ʃe͡ɪnd͡ʒ")   # ['t͡ʃ', 'e͡ɪ', 'n', 'd͡ʒ']

# Validate
ipakit.validate_ipa("kæt")      # []  (valid)
ipakit.validate_ipa("k4t")      # [{'type': 'error', 'code': 'unknown_symbol', ...}]

Conversions

# CMU ARPABET
ipakit.to_cmu("ˈkæt")             # ['K', 'AE1', 'T']
ipakit.to_ipa(["K", "AE1", "T"])  # 'kˈæt'

# X-SAMPA (ASCII)
ipakit.ipa_to_xsampa("t͡ʃ")        # 't_S'
ipakit.xsampa_to_ipa("t_S")        # 't͡ʃ'

# Kirshenbaum / TIMIT
ipakit.to_kirshenbaum("kæt")       # 'k&t'
ipakit.to_timit("kæt")             # ['k', 'ae', 't']

# Features straight from a non-IPA symbol (list of per-segment dicts)
ipakit.features_from_xsampa("t_S")  # [{'manner': 'affricate', 'place': 'postalveolar', ...}]
ipakit.features_from_cmu("K")       # [{'manner': 'plosive', 'place': 'velar', ...}]

By default converters skip symbols they can't map. Pass strict=True to any of them to raise ValueError on unconvertible input instead:

ipakit.to_cmu("k4t")                # ['K', 'T']  (the '4' is skipped)
ipakit.to_cmu("k4t", strict=True)   # ValueError: Cannot convert to CMU ARPABET: ...

Distribution-aware distance

distance() is the raw feature metric — an absolute, inventory-independent mean over phonetic features (so distance("p", "b") is always 0.043). Raw distances bunch up in a narrow band, which makes fixed thresholds hard to pick. normalized_distance() renormalizes a raw distance to its percentile within the bundled IPA inventory's pairwise distribution, spreading values across [0, 1]:

ipakit.distance("p", "b")             # 0.043   raw feature distance
ipakit.normalized_distance("p", "b")  # 0.155   percentile within bundled IPA
ipakit.normalized_distance("p", "a")  # 0.602
ipakit.confusability("p", "b")        # 0.845   complement of normalized_distance

For a model over a chosen reference inventory — percentiles are relative to it and not comparable across inventories — use distance_model():

from ipakit import Phoneset

eng = ipakit.distance_model(
    Phoneset.from_list(
        ["p", "b", "t", "d", "k", "ɡ", "s", "z", "m", "n", "l", "ɹ", "a", "i", "u"],
        name="english",
    )
)
eng.distance("p", "b")                       # 0.267   percentile within this 15-phone set
eng.nearest("p", n=3)                        # [('t', 0.048), ('s', 0.086), ('k', 0.21)]
eng.word_similarity("kæt", "kæd")            # 0.956
eng.is_similar("kæt", "kæd", threshold=0.8)  # True

distance_model() also accepts gamma (power transform to push dissimilar pairs apart), sub_mode="di" (delete+insert substitution cost for word alignment), and threshold / max_length_ratio defaults for is_similar. The raw pairwise matrix ships as ipakit/data/confusion.json; per-inventory models reuse it and only re-slice the percentile distribution.

Conventions

  • Stress is placed on the vowel (the syllable nucleus), not the syllable onset: to_ipa(["K", "AE1", "T"])kˈæt. Syllabification is preserved across round trips (W AO1 T ER0wˈɔtɚ).
  • Affricates and diphthongs use the tie bar (t͡ʃ, e͡ɪ).
  • Round-trip guarantee (X-SAMPA only): IPA written in these conventions round-trips through X-SAMPA (ipa → xsampa → ipa). The only exceptions are b͡v and t͡θ, where the X-SAMPA tie encoding _ collides with a diacritic/tone encoding (_v, _T) — an inherent X-SAMPA ambiguity that ICU shares. The CMU, TIMIT, and Kirshenbaum mappings are lossy (they collapse IPA distinctions) and carry no round-trip guarantee.

CLI

ipakit features p                    # Get features for 'p'
ipakit describe p                    # "voiceless bilabial plosive"
ipakit convert to-cmu "kˈæt"         # IPA to CMU: K AE1 T (stress on the vowel)
ipakit convert to-ipa K AE1 T        # CMU to IPA: kˈæt
ipakit convert to-xsampa "t͡ʃ"        # IPA to X-SAMPA: t_S
ipakit query match plosive bilabial  # Find phones by feature
ipakit analysis natural-class p t k  # Shared features of a set
ipakit analysis minimal-pairs p      # Find similar phones
ipakit distance pair p b             # Raw feature distance: ~0.04
ipakit distance confusability p b    # Inventory-relative: 0.8454
ipakit distance word kæt kæd         # Word similarity: 0.9742

The distance confusability/word commands use the distribution-aware model; scope them to a reference inventory with --phoneset FILE (one phone per line).

Most commands accept --format json (or -j) for machine-readable output. Run ipakit, ipakit <group>, or append help/-h anywhere for usage.

Development

pip install -e ".[dev]"   # or ".[test]" / ".[lint]" for a lean subset
pre-commit install        # black, ruff, mypy --strict, hygiene hooks
pytest                    # unit tests + docstring examples

CI (.github/workflows/ci.yml) mirrors these on every push/PR across Python 3.11–3.13, and validates the committed derived artifacts (the IPA ↔ X-SAMPA table and the phone-distance matrix) against their generators in scripts/.

License

BSD 2-Clause — see LICENSE.

About

No description, website, or topics provided.

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages