Parsing the numerical output from Sensovation SensoSpot image analysis.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

360 lines
9.5 KiB

from datetime import datetime
import pytest
from .conftest import EXAMPLE_DIR_XML_WITH_PARAMS, EXAMPLE_DIR_XML_WO_PARAMS
class DummyDataFunc:
def __init__(self, as_bool):
self.data = None
self.as_bool = as_bool
def __call__(self, data):
self.data = data
def __bool__(self):
return self.as_bool
def test_parser_target_init():
from sensospot_parser.xml_parser import ParserTarget
target = ParserTarget()
assert target.collected == []
assert target._current == {}
assert target._data_func is None
@pytest.mark.parametrize(
("tag", "attributes", "expected"),
[
("UnknownTag", {"ID": "something"}, {}),
(
"ScanJobResult",
{"ID": "scan job 1"},
{"Analysis.Name": "scan job 1"},
),
(
"AssayResult",
{"ID": "C03"},
{"Well.Name": "C03", "Well.Row": "C", "Well.Column": 3},
),
("ChannelConfig1", {}, {"Exposure.Id": 1}),
("Spot", {"ID": "456"}, {"Pos.Id": 456}),
(
"Result",
{"Label": "a label", "Type": "Unknown", "Value": "a value"},
{"a label": "a value"},
),
],
)
@pytest.mark.parametrize("additionals", [{}, {"Ignored": "value"}])
def test_parser_target_start_simple_attributes(
tag, attributes, additionals, expected
):
from sensospot_parser.xml_parser import ParserTarget
target = ParserTarget()
attributes.update(additionals)
target.start(tag, attributes) # stateful operation
assert target._current == expected
assert target._data_func is None
def test_parser_target_start_timestamp():
from sensospot_parser.xml_parser import ParserTarget
target = ParserTarget()
target.start("Timestamp", {})
assert target._data_func == target._data_timestamp_parser
def test_parser_target_start_image_file_name():
from sensospot_parser.xml_parser import ParserTarget
target = ParserTarget()
target.start("ImageFileName", {})
assert target._data_func == target._data_image_name_parser
@pytest.mark.parametrize(
("data_type", "value", "expected"),
[
("unknown type", 1, "1"),
("System.Int32", "12", 12),
("System.UInt32", "23", 23),
("System.Double", "4.56", 4.56),
("System.Boolean", "true", True),
("System.Boolean", "True", True),
("System.Boolean", "Xrue", False),
],
)
def test_parser_target_result_attributes_parser(data_type, value, expected):
from sensospot_parser.xml_parser import ParserTarget
target = ParserTarget()
data = {"Label": "some label", "Type": data_type, "Value": value}
target._result_attributes_parser(data) # stateful operation
assert target._current == {"some label": expected}
assert type(target._current["some label"]) == type(expected)
@pytest.mark.parametrize(
("value", "expected"),
[
(
"3/7/2022 5:31:47 PM",
datetime(2022, 3, 7, 17, 31, 47), # noqa: DTZ001
),
(
"03/7/2022 5:31:47 PM",
datetime(2022, 3, 7, 17, 31, 47), # noqa: DTZ001
),
(
"3/07/2022 5:31:47 PM",
datetime(2022, 3, 7, 17, 31, 47), # noqa: DTZ001
),
(
"03/07/2022 5:31:47 PM",
datetime(2022, 3, 7, 17, 31, 47), # noqa: DTZ001
),
(
"3/7/2022 5:3:47 PM",
datetime(2022, 3, 7, 17, 3, 47), # noqa: DTZ001
),
(
"3/7/2022 5:31:4 PM",
datetime(2022, 3, 7, 17, 31, 4), # noqa: DTZ001
),
(
"3/7/2022 5:31:47 pm",
datetime(2022, 3, 7, 17, 31, 47), # noqa: DTZ001
),
(
"3/7/2022 5:31:47 AM",
datetime(2022, 3, 7, 5, 31, 47), # noqa: DTZ001
),
],
)
def test_parser_target_data_timestamp_parser(value, expected):
from sensospot_parser.xml_parser import ParserTarget
target = ParserTarget()
target._data_timestamp_parser(value) # stateful operation
assert target._current == {"Analysis.Datetime": expected}
def test_parser_target_data_image_name_parser():
from sensospot_parser.xml_parser import ParserTarget
target = ParserTarget()
target._data_image_name_parser(" some file path ") # stateful operation
assert target._current == {"Analysis.Image": "some file path"}
def test_parser_target_data_does_not_call_function():
from sensospot_parser.xml_parser import ParserTarget
target = ParserTarget()
dummy = DummyDataFunc(as_bool=False)
target._data_func = dummy
target.data("some data") # the NotImplementedError is not raised
assert dummy.data is None
def test_parser_target_data_does_call_function():
from sensospot_parser.xml_parser import ParserTarget
target = ParserTarget()
dummy = DummyDataFunc(as_bool=True)
target._data_func = dummy
target.data("some data") # stateful operation
assert dummy.data == "some data"
def test_parser_target_data_reacts_on_spot():
from sensospot_parser.xml_parser import ParserTarget
target = ParserTarget()
target._current = {"some current": "data values"}
target.end("Spot") # stateful operation
assert target.collected == [{"some current": "data values"}]
assert target.collected[0] is not target._current
def test_parser_target_data_does_only_react_on_spot():
from sensospot_parser.xml_parser import ParserTarget
target = ParserTarget()
target._current = {"some current": "data values"}
target.end("NonSpotTag") # stateful operation
assert target.collected == []
def test_parser_target_closed():
from sensospot_parser.xml_parser import ParserTarget
target = ParserTarget()
target.closed() # stateful operation, must be callable
def test_find_result_xml_file_ok(tmp_path):
from sensospot_parser.xml_parser import _find_result_xml_file
xls_file = tmp_path / "result.xsl"
xls_file.touch()
xml_file = tmp_path / "result.xml"
xml_file.touch()
result = _find_result_xml_file(tmp_path)
assert result == xml_file
def test_find_result_xml_file_no_matching_xml_file(tmp_path):
from sensospot_parser.xml_parser import _find_result_xml_file
xls_file = tmp_path / "result.xsl"
xls_file.touch()
xml_file = tmp_path / "other.xml"
xml_file.touch()
result = _find_result_xml_file(tmp_path)
assert result is None
def test_find_result_xml_file_no_xsl_file(tmp_path):
from sensospot_parser.xml_parser import _find_result_xml_file
xml_file = tmp_path / "result.xml"
xml_file.touch()
result = _find_result_xml_file(tmp_path)
assert result is None
def test_find_result_xml_file_multiple_xsl_files(tmp_path):
from sensospot_parser.xml_parser import _find_result_xml_file
xls_file = tmp_path / "result.xsl"
xls_file.touch()
surplus_file = tmp_path / "surplus.xsl"
surplus_file.touch()
xml_file = tmp_path / "result.xml"
xml_file.touch()
result = _find_result_xml_file(tmp_path)
assert result is None
def test_find_result_hidden_xsl_file(tmp_path):
from sensospot_parser.xml_parser import _find_result_xml_file
xls_file = tmp_path / ".result.xsl"
xls_file.touch()
xml_file = tmp_path / ".result.xml"
xml_file.touch()
result = _find_result_xml_file(tmp_path)
assert result is None
def test_parse_xml_file_ok(example_dir):
import pandas
from sensospot_parser.xml_parser import (
_find_result_xml_file,
parse_xml_file,
)
folder = example_dir / EXAMPLE_DIR_XML_WO_PARAMS
xml_file = _find_result_xml_file(folder)
result = parse_xml_file(xml_file)
assert isinstance(result, pandas.DataFrame)
assert len(result) == 4 * 4 * 4 * 100
assert set(result["Well.Row"]) == set("ABCD")
assert set(result["Well.Column"]) == {1, 2, 3, 4}
assert set(result["Exposure.Id"]) == {1, 2, 3, 4}
assert min(result["Spot.Diameter"]) == 22
assert max(result["Spot.Diameter"]) == 34
assert "Parameters.Time" not in result
@pytest.mark.parametrize(
("file_name", "message"),
[
("not_existing.xml", "Xml file does not exist"),
("defect.xml", "Could not parse assay results xml file"),
("malformed_data.xml", "Malformed data in xml file"),
],
)
def test_parse_xml_file_raies_error(file_name, message, example_dir):
from sensospot_parser.xml_parser import parse_xml_file
xml_file = example_dir / file_name
with pytest.raises(ValueError) as e: # noqa: PT011
parse_xml_file(xml_file)
assert message in str(e)
def test_parse_xml_folder_with_params(example_dir):
import pandas
from sensospot_parser.xml_parser import parse_xml_folder
folder = example_dir / EXAMPLE_DIR_XML_WITH_PARAMS
result = parse_xml_folder(folder)
assert isinstance(result, pandas.DataFrame)
assert len(result) == 4 * 4 * 4 * 100
assert not result["Parameters.Time"].hasnans
def test_parse_xml_folder_without_params(example_dir):
import pandas
from sensospot_parser.xml_parser import parse_xml_folder
folder = example_dir / EXAMPLE_DIR_XML_WO_PARAMS
result = parse_xml_folder(folder)
assert isinstance(result, pandas.DataFrame)
assert len(result) == 4 * 4 * 4 * 100
assert result["Parameters.Time"].hasnans
def test_parse_xml_folder_non_existing_xml_file(tmp_path):
from sensospot_parser.xml_parser import parse_xml_folder
with pytest.raises(ValueError) as e: # noqa: PT011
parse_xml_folder(tmp_path)
assert "Could not find assay results xml file" in str(e)