IPA phonetic toolkit
Project description
ipakit
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 ER0↔wˈɔ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 areb͡vandt͡θ, 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1bab0c750f69aa5d2a39d746eff36c60b2ecf7d8c0287d86a64a4a5bbb15a382
|
|
| MD5 |
3b0507acd1ed9aac0942ca23fe5e68b8
|
|
| BLAKE2b-256 |
a0e64bd452a9f264505f4f3641b12955a7284dc93a5d4615f1198cff3e3ec3b0
|
Provenance
The following attestation bundles were made for ipakit-0.1.0.tar.gz:
Publisher:
publish.yml on lenzo-ka/ipakit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ipakit-0.1.0.tar.gz -
Subject digest:
1bab0c750f69aa5d2a39d746eff36c60b2ecf7d8c0287d86a64a4a5bbb15a382 - Sigstore transparency entry: 2101757919
- Sigstore integration time:
-
Permalink:
lenzo-ka/ipakit@1e2cbdd7aa558035d4bee0531d01485f3ac07625 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/lenzo-ka
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@1e2cbdd7aa558035d4bee0531d01485f3ac07625 -
Trigger Event:
release
-
Statement type:
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5850e9984e231c0fb6828e837a18a85c0a2d7eeeefee94616cc4285c1233aaa6
|
|
| MD5 |
179093f99bc02cfa030ae4ab3e598bcf
|
|
| BLAKE2b-256 |
7a4b16f73d98beb42fdc45972a01440aca2a4948b423ea4f50c88392b8233e1b
|
Provenance
The following attestation bundles were made for ipakit-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on lenzo-ka/ipakit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ipakit-0.1.0-py3-none-any.whl -
Subject digest:
5850e9984e231c0fb6828e837a18a85c0a2d7eeeefee94616cc4285c1233aaa6 - Sigstore transparency entry: 2101758091
- Sigstore integration time:
-
Permalink:
lenzo-ka/ipakit@1e2cbdd7aa558035d4bee0531d01485f3ac07625 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/lenzo-ka
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@1e2cbdd7aa558035d4bee0531d01485f3ac07625 -
Trigger Event:
release
-
Statement type: