Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions dicom_standard/extract_conf_profile_attributes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Extract the listing of all attributes given in table E.1-1 from part 15 of the DICOM Standard.
'''
from typing import cast, Dict, List, Union
import re
import sys

from bs4 import BeautifulSoup
Expand All @@ -18,6 +19,8 @@

RETIREMENT_MISMATCH_ATTRIBUTES = ['Referenced Patient Alias Sequence']

TAG_PATTERN = re.compile(r'\(\w{4},\w{4}\)')

AttrTableType = List[Dict[str, Union[str, bool]]]


Expand All @@ -39,11 +42,26 @@ def get_conf_profile_table(standard: BeautifulSoup) -> List[TableDictType]:
return table_to_dict(list_table, COLUMN_TITLES, omit_empty=True)


def extract_tag(raw_tag: str) -> str:
"""Standard workaround: isolate the tag from a cell that qualifies it with prose
The "Private Attributes" row of Table E.1-1 gives its tag as
"(gggg,eeee) where gggg is odd". Without this, the trailing prose ends up in the
attribute's tag and ID, giving that one row a shape no other row has.
Args:
raw_tag (str): the contents of the table's tag cell
Returns:
str: the tag alone, or the original cell if it contains no tag
"""
match = TAG_PATTERN.search(raw_tag)
return match.group(0) if match else raw_tag


def table_to_json(table: List[TableDictType]) -> List[TableDictType]:
attributes = []
for attr in table:
attr['id'] = pl.create_slug(attr['tag'])
attr['tag'] = attr['tag'].upper()
tag = extract_tag(attr['tag'])
attr['id'] = pl.create_slug(tag)
attr['tag'] = tag.upper()
attributes.append(attr)
return attributes

Expand Down
32 changes: 32 additions & 0 deletions tests/extract_conf_profile_attributes_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
'''
Unit tests covering functions in `extract_conf_profile_attributes.py`.
'''
import pytest

from dicom_standard.extract_conf_profile_attributes import extract_tag, table_to_json


@pytest.mark.parametrize('raw_tag,expected', [
('(0008,0050)', '(0008,0050)'),
('(50xx,xxxx)', '(50xx,xxxx)'),
('(gggg,eeee) where gggg is odd', '(gggg,eeee)'),
])
def test_extract_tag(raw_tag, expected):
assert extract_tag(raw_tag) == expected


def test_extract_tag_passes_through_cell_without_a_tag():
assert extract_tag('No tag here') == 'No tag here'


def test_table_to_json_derives_id_from_the_tag_alone():
table = [
{'name': 'Accession Number', 'tag': '(0008,0050)'},
{'name': 'Curve Data', 'tag': '(50xx,xxxx)'},
{'name': 'Private Attributes', 'tag': '(gggg,eeee) where gggg is odd'},
]
attributes = table_to_json(table)
assert [attr['tag'] for attr in attributes] == [
'(0008,0050)', '(50XX,XXXX)', '(GGGG,EEEE)']
assert [attr['id'] for attr in attributes] == [
'00080050', '50xxxxxx', 'ggggeeee']