Skip to content

Commit

Permalink
✅ acq2sqlite.py:none_to_null so template and input missingness matches
Browse files Browse the repository at this point in the history
  • Loading branch information
WillForan committed Nov 25, 2024
1 parent 21e835b commit f5cd600
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 16 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ docs/_static/mrqart/main.css: static/main.css
##

.lint: $(wildcard *.py) $(wildcard sphinx/*.rst) | venv-dev
$(source_venv) && black . > .lint && isort . >> .lint && codespell -w >> .lint
$(source_venv) && black . > .lint && isort --skip-gitignore . >> .lint && codespell -w >> .lint

test: .test.doctest .test.pytest
.test.doctest: change_header.py acq2sqlite.py dcmmeta2tsv.py | venv-program venv-dev #$(wildcard *py)
Expand Down
14 changes: 14 additions & 0 deletions acq2sqlite.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,19 @@
logging.basicConfig(level=os.environ.get("LOGLEVEL", logging.INFO))


def none_to_null(row: Optional[sqlite3.Row]):
"""
Template should match get_header. This changes all ``None``s to ``"null"``
:param row: single row from a sqlite query (likely :py:func:`get_template`)
"""
if not row:
return row
res = {}
for k in row.keys():
res[k] = row[k] if row[k] else NULLVAL.value
return res


def column_names():
"""
These names match what's used by dcmmeta2tsv.py and 00_build_db.bash
Expand Down Expand Up @@ -289,6 +302,7 @@ def get_template(self, pname: str, seqname: str) -> sqlite3.Row:
(pname, seqname),
)
res = cur.fetchone()
res = none_to_null(res)
logging.debug("found template: %s", res)
return res

Expand Down
10 changes: 6 additions & 4 deletions template_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ def find_errors(template: TagValues, current_hdr: TagValues) -> dict[str, ErrorC
"""
errors = {}
for k in DBQuery.CONSTS:
t_k = template.get(k, "0")
h_k = current_hdr.get(k, "0")
t_k = template.get(k, "null")
h_k = current_hdr.get(k, "null")

# TODO: more checks for specific headers
#: TR is in milliseconds. no need to keep decimals precision
Expand All @@ -66,11 +66,13 @@ class TemplateChecker:
read a dicom file and report if it conforms to the expected template
"""

def __init__(self):
def __init__(self, db=None):
"""
db connection and tag reader (from taglist.txt)
:param db: sql connection passed on to :py:class:`DBQuery`.
``None`` (default) is local sqlite3.
"""
self.db = DBQuery()
self.db = DBQuery(db)
self.reader = DicomTagReader()

def check_file(self, dcm_path) -> CheckResult:
Expand Down
3 changes: 2 additions & 1 deletion tests/test_html.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
from jinja2 import Template

from compliance_check_html import generate_html_report
#from template_checker import CheckResult, TemplateChecker

# from template_checker import CheckResult, TemplateChecker


@pytest.fixture
Expand Down
27 changes: 17 additions & 10 deletions tests/test_sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from acq2sqlite import DBQuery
from dcmmeta2tsv import DicomTagReader, TagDicts
from template_checker import TemplateChecker, CheckResult
from template_checker import CheckResult, TemplateChecker

#: Example template to test against. Previously used within test like::
#: mocker.patch.object(template_checker.db, "get_template", return_value=mock_template)
Expand All @@ -25,24 +25,29 @@
# Other relevant fields can be added as well if seen as necessary
}


@pytest.fixture
def db():
"""create an in memory database handler"""
mem_db = DBQuery(sqlite3.connect(":memory:"))
with open("schema.sql") as f:
_ = [mem_db.sql.execute(c) for c in f.read().split(";")]
# create template table. also see ../make_template_by_count.sql
mem_db.sql.execute("""
mem_db.sql.execute(
"""
create table template_by_count (
n int, Project text, SequenceName text,
param_id int, first text, last text)""")
param_id int, first text, last text)"""
)
vals = [x for x in MOCK_TEMPLATE.values()]
cols = ",".join(MOCK_TEMPLATE.keys())
qs = ",".join(["?" for x in vals])
sql = f"INSERT INTO acq_param ({cols}) VALUES ({qs})"
mem_db.sql.execute(sql, vals)
sql = "INSERT INTO template_by_count (Project, SequenceName, param_id)" + \
f"VALUES ('{MOCK_TEMPLATE['Project']}', '{MOCK_TEMPLATE['SequenceName']}', 1)"
sql = (
"INSERT INTO template_by_count (Project, SequenceName, param_id)"
+ f"VALUES ('{MOCK_TEMPLATE['Project']}', '{MOCK_TEMPLATE['SequenceName']}', 1)"
)
mem_db.sql.execute(sql)

return mem_db
Expand Down Expand Up @@ -142,7 +147,7 @@ def test_find_acquisitions_since(db):

@pytest.fixture
def template_checker(db):
return TemplateChecker(db)
return TemplateChecker(db.sql)


def test_check_header_notemplate(template_checker):
Expand All @@ -159,8 +164,9 @@ def test_check_header_notemplate(template_checker):
"Comments": "Unaliased MB3/PE4/LB SENSE1",
}
result = template_checker.check_header(test_row)
assert result['errors'] == {}
assert result['conforms']
assert result["errors"] == {}
assert result["conforms"]


def test_check_header(template_checker):
"""
Expand Down Expand Up @@ -190,7 +196,8 @@ def test_check_header(template_checker):
assert result["input"] == test_row
assert result["template"]["TR"] == MOCK_TEMPLATE["TR"]

def test_check_header_matches(db, template_checker):

def test_check_header_matches(template_checker):
result: CheckResult = template_checker.check_header(MOCK_TEMPLATE)
assert result["conforms"] == True
assert result["errors"] == {}
assert result["conforms"] == True

0 comments on commit f5cd600

Please sign in to comment.