Skip to main content

IPA phonetic toolkit

Project description

ipakit

CI PyPI Python versions License: MIT

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

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ipakit-0.1.0.tar.gz (107.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ipakit-0.1.0-py3-none-any.whl (97.7 kB view details)

Uploaded Python 3

File details

Details for the file ipakit-0.1.0.tar.gz.

File metadata

  • Download URL: ipakit-0.1.0.tar.gz
  • Upload date:
  • Size: 107.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ipakit-0.1.0.tar.gz
Algorithm Hash digest
SHA256 1bab0c750f69aa5d2a39d746eff36c60b2ecf7d8c0287d86a64a4a5bbb15a382
MD5 3b0507acd1ed9aac0942ca23fe5e68b8
BLAKE2b-256 a0e64bd452a9f264505f4f3641b12955a7284dc93a5d4615f1198cff3e3ec3b0

See more details on using hashes here.

Provenance

The following attestation bundles were made for ipakit-0.1.0.tar.gz:

Publisher: publish.yml on lenzo-ka/ipakit

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ipakit-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: ipakit-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 97.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ipakit-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5850e9984e231c0fb6828e837a18a85c0a2d7eeeefee94616cc4285c1233aaa6
MD5 179093f99bc02cfa030ae4ab3e598bcf
BLAKE2b-256 7a4b16f73d98beb42fdc45972a01440aca2a4948b423ea4f50c88392b8233e1b

See more details on using hashes here.

Provenance

The following attestation bundles were made for ipakit-0.1.0-py3-none-any.whl:

Publisher: publish.yml on lenzo-ka/ipakit

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page