codedx 0.2.0__tar.gz → 0.3.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- codedx-0.3.1/CHANGELOG.md +23 -0
- {codedx-0.2.0 → codedx-0.3.1}/PKG-INFO +9 -8
- {codedx-0.2.0 → codedx-0.3.1}/README.md +8 -7
- {codedx-0.2.0 → codedx-0.3.1}/hatch_build.py +13 -2
- {codedx-0.2.0 → codedx-0.3.1}/pyproject.toml +3 -1
- {codedx-0.2.0 → codedx-0.3.1}/src/codedx/__init__.py +5 -1
- codedx-0.3.1/src/codedx/chapters.py +55 -0
- {codedx-0.2.0 → codedx-0.3.1}/src/codedx/icd10who.py +1 -7
- {codedx-0.2.0 → codedx-0.3.1}/.gitignore +0 -0
- {codedx-0.2.0 → codedx-0.3.1}/src/codedx/_core.py +0 -0
- {codedx-0.2.0 → codedx-0.3.1}/src/codedx/icd10cm.py +0 -0
- {codedx-0.2.0 → codedx-0.3.1}/src/codedx/icd10se.py +0 -0
- {codedx-0.2.0 → codedx-0.3.1}/src/codedx/ksh97p.py +0 -0
- {codedx-0.2.0 → codedx-0.3.1}/src/codedx/rehab.py +0 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.3.1 — 2026-06-08
|
|
4
|
+
|
|
5
|
+
- Migrate KSH97-P downloads from Socialstyrelsen to Ehälsomyndigheten Confluence
|
|
6
|
+
|
|
7
|
+
## 0.3.0 — 2026-06-08
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- `chapter_to_roman(chapter)` — convert chapter number (int, `"1"`, or `"01"`) to Roman numeral (`"I"`–`"XXII"`)
|
|
12
|
+
- `roman_to_chapter(roman)` — convert Roman numeral chapter to int 1–22; case-insensitive
|
|
13
|
+
- `get_range(chapter_code)` — extract code range string from a chapter title (e.g. `"01"` → `"A00-B99"`)
|
|
14
|
+
- All three exported from `codedx` top-level
|
|
15
|
+
|
|
16
|
+
## 0.2.0
|
|
17
|
+
|
|
18
|
+
- ICD-10-SE and history file now downloaded from Ehälsomyndigheten (replacing Socialstyrelsen URLs)
|
|
19
|
+
- Retired code lookup now uses the comprehensive history file (`historik-icd-10-se-1997-2026.xlsx`) covering all codes 1997–2026, instead of the partial inactivation list
|
|
20
|
+
|
|
21
|
+
## 0.1.0
|
|
22
|
+
|
|
23
|
+
- Initial release: ICD-10-SE, WHO ICD-10, ICD-10-CM, KSH97-P, rehab code lookups
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codedx
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: Swedish medical coding used for diagnosis codes
|
|
5
5
|
Author-email: Ludvig Hult <ludvig.hult@gmail.com>
|
|
6
6
|
Requires-Python: >=3.12
|
|
@@ -46,13 +46,14 @@ Dots are dropped throughout, matching what is typically found in databases: `A01
|
|
|
46
46
|
pip install codedx
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
-
Downloads data at install time
|
|
49
|
+
Downloads data at install time. Raw files are not redistributed due to licence restrictions.
|
|
50
50
|
|
|
51
|
-
##
|
|
51
|
+
## Data sources
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
- ICD-10-SE and history file now downloaded from Ehälsomyndigheten (replacing Socialstyrelsen URLs)
|
|
55
|
-
- Retired code lookup now uses the comprehensive history file (`historik-icd-10-se-1997-2026.xlsx`) covering all codes 1997–2026, instead of the partial inactivation list
|
|
53
|
+
Classification files come from two Swedish authorities:
|
|
56
54
|
|
|
57
|
-
|
|
58
|
-
|
|
55
|
+
**Ehälsomyndigheten** maintains ICD-10-SE and KSH97-P. Files are downloaded from their Confluence collaboration platform. KSH97-P (primary care classification) is being phased out in favour of ICD-10-SE.
|
|
56
|
+
|
|
57
|
+
**Socialstyrelsen** retains responsibility for the NordDRG system and the associated rehab function codes (UA/UB series). These files are downloaded from Socialstyrelsen's website.
|
|
58
|
+
|
|
59
|
+
WHO ICD-10 (English) and ICD-10-CM are downloaded from WHO and the US CDC respectively.
|
|
@@ -36,13 +36,14 @@ Dots are dropped throughout, matching what is typically found in databases: `A01
|
|
|
36
36
|
pip install codedx
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
-
Downloads data at install time
|
|
39
|
+
Downloads data at install time. Raw files are not redistributed due to licence restrictions.
|
|
40
40
|
|
|
41
|
-
##
|
|
41
|
+
## Data sources
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
- ICD-10-SE and history file now downloaded from Ehälsomyndigheten (replacing Socialstyrelsen URLs)
|
|
45
|
-
- Retired code lookup now uses the comprehensive history file (`historik-icd-10-se-1997-2026.xlsx`) covering all codes 1997–2026, instead of the partial inactivation list
|
|
43
|
+
Classification files come from two Swedish authorities:
|
|
46
44
|
|
|
47
|
-
|
|
48
|
-
|
|
45
|
+
**Ehälsomyndigheten** maintains ICD-10-SE and KSH97-P. Files are downloaded from their Confluence collaboration platform. KSH97-P (primary care classification) is being phased out in favour of ICD-10-SE.
|
|
46
|
+
|
|
47
|
+
**Socialstyrelsen** retains responsibility for the NordDRG system and the associated rehab function codes (UA/UB series). These files are downloaded from Socialstyrelsen's website.
|
|
48
|
+
|
|
49
|
+
WHO ICD-10 (English) and ICD-10-CM are downloaded from WHO and the US CDC respectively.
|
|
@@ -5,6 +5,7 @@ import zipfile
|
|
|
5
5
|
|
|
6
6
|
import certifi
|
|
7
7
|
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
|
|
8
|
+
from hatchling.metadata.plugin.interface import MetadataHookInterface
|
|
8
9
|
|
|
9
10
|
_DATA = pathlib.Path("src/codedx/data")
|
|
10
11
|
|
|
@@ -32,8 +33,8 @@ _MULTI_ZIPS = [
|
|
|
32
33
|
"ksh97p.zip",
|
|
33
34
|
"KSH97-P tables (~400 KB)",
|
|
34
35
|
[
|
|
35
|
-
("ksh97p_2015.xls", "https://
|
|
36
|
-
("ksh97p_se_en.xls", "https://
|
|
36
|
+
("ksh97p_2015.xls", "https://samarbetsyta.ehalsomyndigheten.se/download/attachments/451267034/klassificering-kodtextfil-ksh97-p-2015.xls?version=2&modificationDate=1779623720433&api=v2"),
|
|
37
|
+
("ksh97p_se_en.xls", "https://samarbetsyta.ehalsomyndigheten.se/download/attachments/451267034/klassificering-kodtextfil-ksh97-primarvard-svensk-engelsk.xls?version=1&modificationDate=1779623743547&api=v2"),
|
|
37
38
|
],
|
|
38
39
|
),
|
|
39
40
|
(
|
|
@@ -60,6 +61,16 @@ def _download(url: str, dest: pathlib.Path) -> None:
|
|
|
60
61
|
f.write(chunk)
|
|
61
62
|
|
|
62
63
|
|
|
64
|
+
class CustomMetadataHook(MetadataHookInterface):
|
|
65
|
+
def update(self, metadata: dict) -> None:
|
|
66
|
+
readme = pathlib.Path("README.md").read_text(encoding="utf-8")
|
|
67
|
+
changelog = pathlib.Path("CHANGELOG.md").read_text(encoding="utf-8")
|
|
68
|
+
metadata["readme"] = {
|
|
69
|
+
"content-type": "text/markdown",
|
|
70
|
+
"text": readme + "\n\n" + changelog,
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
|
|
63
74
|
class CustomBuildHook(BuildHookInterface):
|
|
64
75
|
def initialize(self, version, build_data):
|
|
65
76
|
if self.target_name != "wheel":
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "codedx"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.3.1"
|
|
4
4
|
description = "Swedish medical coding used for diagnosis codes"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [
|
|
@@ -25,6 +25,8 @@ exclude = [
|
|
|
25
25
|
"/.gitignore",
|
|
26
26
|
]
|
|
27
27
|
|
|
28
|
+
[tool.hatch.metadata.hooks.custom]
|
|
29
|
+
|
|
28
30
|
[tool.hatch.build.hooks.custom]
|
|
29
31
|
|
|
30
32
|
[dependency-groups]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import pathlib
|
|
2
2
|
|
|
3
|
-
__version__ = "0.
|
|
3
|
+
__version__ = "0.3.0"
|
|
4
4
|
_CACHE_DIR = pathlib.Path.home() / ".cache" / "codedx" / f"v{__version__}"
|
|
5
5
|
|
|
6
6
|
from codedx._core import ( # noqa: E402
|
|
@@ -14,6 +14,7 @@ from codedx._core import ( # noqa: E402
|
|
|
14
14
|
is_rehab_code,
|
|
15
15
|
is_retired_icd10se_code,
|
|
16
16
|
)
|
|
17
|
+
from codedx.chapters import chapter_to_roman, roman_to_chapter, get_range # noqa: E402
|
|
17
18
|
|
|
18
19
|
__all__ = [
|
|
19
20
|
"get_name",
|
|
@@ -25,4 +26,7 @@ __all__ = [
|
|
|
25
26
|
"is_ksh97p_code",
|
|
26
27
|
"is_rehab_code",
|
|
27
28
|
"is_retired_icd10se_code",
|
|
29
|
+
"chapter_to_roman",
|
|
30
|
+
"roman_to_chapter",
|
|
31
|
+
"get_range",
|
|
28
32
|
]
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""Chapter and block numeral/range utilities for ICD-10."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
|
|
5
|
+
_INT_TO_ROMAN: dict[int, str] = {
|
|
6
|
+
1: "I", 2: "II", 3: "III", 4: "IV", 5: "V", 6: "VI", 7: "VII",
|
|
7
|
+
8: "VIII", 9: "IX", 10: "X", 11: "XI", 12: "XII", 13: "XIII",
|
|
8
|
+
14: "XIV", 15: "XV", 16: "XVI", 17: "XVII", 18: "XVIII",
|
|
9
|
+
19: "XIX", 20: "XX", 21: "XXI", 22: "XXII",
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
_ROMAN_TO_INT: dict[str, int] = {v: k for k, v in _INT_TO_ROMAN.items()}
|
|
13
|
+
|
|
14
|
+
_RANGE_RE = re.compile(r'\(([A-Z]\d{2}(?:\.\d)?-[A-Z]\d{2}(?:\.\d)?)\)')
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def chapter_to_roman(chapter: int | str) -> str:
|
|
18
|
+
"""Convert chapter number to Roman numeral. Accepts 1, '1', or '01'."""
|
|
19
|
+
n = int(chapter)
|
|
20
|
+
try:
|
|
21
|
+
return _INT_TO_ROMAN[n]
|
|
22
|
+
except KeyError:
|
|
23
|
+
raise ValueError(f"Chapter number {n!r} out of range 1–22") from None
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def roman_to_chapter(roman: str) -> int:
|
|
27
|
+
"""Convert Roman numeral chapter (e.g. 'XVIII') to integer 1–22. Case-insensitive."""
|
|
28
|
+
try:
|
|
29
|
+
return _ROMAN_TO_INT[roman.upper()]
|
|
30
|
+
except KeyError:
|
|
31
|
+
raise ValueError(f"Unknown Roman numeral {roman!r}") from None
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def get_range(code: str) -> str:
|
|
35
|
+
"""Return the code range string for a chapter.
|
|
36
|
+
|
|
37
|
+
Chapter '01' → 'A00-B99' (extracted from title)
|
|
38
|
+
"""
|
|
39
|
+
import polars as pl
|
|
40
|
+
from codedx._core import icd10se_table
|
|
41
|
+
|
|
42
|
+
try:
|
|
43
|
+
row = icd10se_table.row(by_predicate=pl.col("Code") == code, named=True)
|
|
44
|
+
except Exception:
|
|
45
|
+
raise ValueError(f"Code {code!r} not found in ICD-10-SE") from None
|
|
46
|
+
|
|
47
|
+
if row["Level"] != "Chapter":
|
|
48
|
+
raise ValueError(f"Code {code!r} is level {row['Level']!r}, not Chapter")
|
|
49
|
+
m = _RANGE_RE.search(row["Titel"])
|
|
50
|
+
if m:
|
|
51
|
+
return m.group(1)
|
|
52
|
+
raise ValueError(f"No range found in chapter title: {row['Titel']!r}")
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
__all__ = ["chapter_to_roman", "roman_to_chapter", "get_range"]
|
|
@@ -5,13 +5,7 @@ import pathlib
|
|
|
5
5
|
import polars as pl
|
|
6
6
|
|
|
7
7
|
from codedx import _CACHE_DIR
|
|
8
|
-
|
|
9
|
-
_ROMAN = {
|
|
10
|
-
"I": 1, "II": 2, "III": 3, "IV": 4, "V": 5, "VI": 6, "VII": 7,
|
|
11
|
-
"VIII": 8, "IX": 9, "X": 10, "XI": 11, "XII": 12, "XIII": 13,
|
|
12
|
-
"XIV": 14, "XV": 15, "XVI": 16, "XVII": 17, "XVIII": 18,
|
|
13
|
-
"XIX": 19, "XX": 20, "XXI": 21, "XXII": 22,
|
|
14
|
-
}
|
|
8
|
+
from codedx.chapters import _ROMAN_TO_INT as _ROMAN
|
|
15
9
|
|
|
16
10
|
|
|
17
11
|
def _build(work_dir: pathlib.Path) -> pl.DataFrame:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|