Skill Tracer
Skills › Scientific Agent Skills › pyhealth › medcode.md

medcode.md

77 lines · skills/pyhealth/references/medcode.md at 5f2bc03

Open on GitHub
1# Medical codes and tokenizers
2
3PyHealth 2.0.2 implements local lookup/mapping over **downloaded, cached** reference
4tables. They are not all bundled in the wheel. First use needs public network access
5to `https://storage.googleapis.com/pyhealth/resource/`; there is no API key, JSON
6request body or pagination. SDK reads retrieve CSV resources by filename and cache
7processed mappings. Record the resource snapshot/checksum for reproducible work;
8package version alone does not pin the remote tables.
9

Medical codes and tokenizers

PyHealth 2.0.2 implements local lookup/mapping over downloaded, cached reference tables. They are not all bundled in the wheel. First use needs public network access to https://storage.googleapis.com/pyhealth/resource/; there is no API key, JSON request body or pagination. SDK reads retrieve CSV resources by filename and cache processed mappings. Record the resource snapshot/checksum for reproducible work; package version alone does not pin the remote tables.

Raw lines 1 to 9
10## Lookup within a system
12```python
13from pyhealth.medcode import InnerMap
14icd9 = InnerMap.load("ICD9CM")
15print(icd9.lookup("428.0"))
16# Congestive heart failure, unspecified
17print(icd9.get_ancestors("428.0"))
18# ['428', '420-429.99', '390-459.99', '001-999.99']
19atc = InnerMap.load("ATC")
20print(atc.lookup("M01AE51"))
21# ibuprofen, combinations
22```
24These calls and results were executed with 2.0.2. Supported vocabulary classes
25include `ICD9CM`, `ICD10CM`, `ICD9PROC`, `ICD10PCS`, `ATC`, `NDC`, `RxNorm`, `CCSCM`
26and `CCSPROC`. A class being available does not guarantee every cross-map exists.
27Validate unknown codes instead of inventing a description.

Lookup within a system

from pyhealth.medcode import InnerMap
icd9 = InnerMap.load("ICD9CM")
print(icd9.lookup("428.0"))
# Congestive heart failure, unspecified
print(icd9.get_ancestors("428.0"))
# ['428', '420-429.99', '390-459.99', '001-999.99']
atc = InnerMap.load("ATC")
print(atc.lookup("M01AE51"))
# ibuprofen, combinations

These calls and results were executed with 2.0.2. Supported vocabulary classes include ICD9CM, ICD10CM, ICD9PROC, ICD10PCS, ATC, NDC, RxNorm, CCSCM and CCSPROC. A class being available does not guarantee every cross-map exists. Validate unknown codes instead of inventing a description.

Raw lines 10 to 28
29## Cross-map
31```python
32from pyhealth.medcode import CrossMap
33print(CrossMap.load("ICD9CM", "CCSCM").map("428.0")) # ['108']
34print(CrossMap.load("NDC", "RxNorm").map("50580049698")) # ['209387']
35ndc_to_atc = CrossMap.load("NDC", "ATC")
36print(ndc_to_atc.map("00527051210")) # ['A11CC01']
37print(ndc_to_atc.map("00527051210", target_kwargs={"level": 3})) # ['A11C']
38```
40These mapping examples were executed. `CrossMap` first tries
41`<source>_to_<target>.csv` and on an HTTP error tries the reversed filename; the CSV
42columns still identify the requested direction. If neither resource exists, handle
43the failure explicitly. A source code may yield `[]` or multiple targets. Keep NDCs
44as strings to preserve leading zeros. Never assume mappings are bijective,
45lossless, current regulatory coding guidance, or enough to eliminate cohort shift.
47Do not promise arbitrary ICD-9/ICD-10 conversion merely because both vocabularies
48load. Verify the desired map resource and its version. When combining MIMIC-IV
49codes, preserve each row's `icd_version` before conversion. Report unmapped and
50multiply mapped fractions, normalization decisions and any discarded records.
51For code reduction, inspect the actual vocabulary; there is no universal fixed CCS
52category count across resources and editions.

Cross-map

from pyhealth.medcode import CrossMap
print(CrossMap.load("ICD9CM", "CCSCM").map("428.0"))  # ['108']
print(CrossMap.load("NDC", "RxNorm").map("50580049698"))  # ['209387']
ndc_to_atc = CrossMap.load("NDC", "ATC")
print(ndc_to_atc.map("00527051210"))  # ['A11CC01']
print(ndc_to_atc.map("00527051210", target_kwargs={"level": 3}))  # ['A11C']

These mapping examples were executed. CrossMap first tries <source>_to_<target>.csv and on an HTTP error tries the reversed filename; the CSV columns still identify the requested direction. If neither resource exists, handle the failure explicitly. A source code may yield [] or multiple targets. Keep NDCs as strings to preserve leading zeros. Never assume mappings are bijective, lossless, current regulatory coding guidance, or enough to eliminate cohort shift.

Do not promise arbitrary ICD-9/ICD-10 conversion merely because both vocabularies load. Verify the desired map resource and its version. When combining MIMIC-IV codes, preserve each row's icd_version before conversion. Report unmapped and multiply mapped fractions, normalization decisions and any discarded records. For code reduction, inspect the actual vocabulary; there is no universal fixed CCS category count across resources and editions.

Raw lines 29 to 53
54## Tokenizer dimensions
56```python
57from pyhealth.tokenizer import Tokenizer
58vocab = ["A01A", "A02A", "A02B", "A03C", "A03D", "A04A"]
59tok = Tokenizer(tokens=vocab, special_tokens=["<pad>", "<unk>"])
60encoded_2d = tok.batch_encode_2d([["A03C", "A03D"], ["A04A", "B035"]])
61assert encoded_2d == [[5, 6], [7, 1]]
62print(tok.batch_decode_2d(encoded_2d))
63# [['A03C', 'A03D'], ['A04A', '<unk>']]
64encoded_3d = tok.batch_encode_3d([[["A03C", "A03D"], ["A04A"]], [["B035"]]])
65print(tok.batch_decode_3d(encoded_3d))
66# [[['A03C', 'A03D'], ['A04A']], [['<unk>']]]
67```
69Decode a 3D encoding with `batch_decode_3d`, not `batch_decode_2d`. Padding is
70removed by default; unknown tokens cannot be reconstructed. The reserved indices
71are 0 and 1 only because the special-token order above specifies them. Fit/reuse a
72training vocabulary; changing token order after loading weights invalidates the
73embedding semantics. Normal dataset processors usually handle tokenization.
75Sources: [MedCode](https://pyhealth.readthedocs.io/en/latest/api/medcode.html),
76[Tokenizer](https://pyhealth.readthedocs.io/en/latest/api/tokenizer.html), and released
772.0.2 `medcode/utils.py`, `cross_map.py`, `inner_map.py`, `tokenizer.py`.

Tokenizer dimensions

from pyhealth.tokenizer import Tokenizer
vocab = ["A01A", "A02A", "A02B", "A03C", "A03D", "A04A"]
tok = Tokenizer(tokens=vocab, special_tokens=["<pad>", "<unk>"])
encoded_2d = tok.batch_encode_2d([["A03C", "A03D"], ["A04A", "B035"]])
assert encoded_2d == [[5, 6], [7, 1]]
print(tok.batch_decode_2d(encoded_2d))
# [['A03C', 'A03D'], ['A04A', '<unk>']]
encoded_3d = tok.batch_encode_3d([[["A03C", "A03D"], ["A04A"]], [["B035"]]])
print(tok.batch_decode_3d(encoded_3d))
# [[['A03C', 'A03D'], ['A04A']], [['<unk>']]]

Decode a 3D encoding with batch_decode_3d, not batch_decode_2d. Padding is removed by default; unknown tokens cannot be reconstructed. The reserved indices are 0 and 1 only because the special-token order above specifies them. Fit/reuse a training vocabulary; changing token order after loading weights invalidates the embedding semantics. Normal dataset processors usually handle tokenization.

Sources: MedCode, Tokenizer, and released 2.0.2 medcode/utils.py, cross_map.py, inner_map.py, tokenizer.py.

Raw lines 54 to 77