Holger Frey
4 years ago
7 changed files with 249 additions and 38 deletions
@ -0,0 +1,74 @@
@@ -0,0 +1,74 @@
|
||||
""" Sensospot Data Parser |
||||
|
||||
Parsing the numerical output from Sensovations Sensospot image analysis. |
||||
""" |
||||
|
||||
from pathlib import Path |
||||
from collections import namedtuple |
||||
|
||||
import numpy |
||||
from defusedxml import ElementTree |
||||
|
||||
MeasurementParams = namedtuple("MeasurementParams", ["channel", "time"]) |
||||
|
||||
|
||||
def _search_measurement_params_file(folder): |
||||
""" searches for a exposure settings file in a folder """ |
||||
folder_path = Path(folder) |
||||
params_folder = folder_path / "Parameters" |
||||
if not params_folder.is_dir(): |
||||
return None |
||||
param_files = list(params_folder.glob("**/*.svexp")) |
||||
if len(param_files) == 1: |
||||
return param_files[0] |
||||
else: |
||||
return None |
||||
|
||||
|
||||
def _parse_measurement_params(params_file): |
||||
""" parses the cannel informations from a settings file """ |
||||
file_path = Path(params_file) |
||||
with file_path.open("r") as file_handle: |
||||
tree = ElementTree.parse(file_handle) |
||||
result = {} |
||||
for child in tree.find("Channels"): |
||||
# child.tag == "ChannelConfig1" |
||||
exposure = int(child.tag[-1]) |
||||
channel_description = child.attrib["Description"] |
||||
# channel_description == "[Cy3|Cy5] Green" |
||||
channel = channel_description.rsplit(" ", 1)[-1] |
||||
time = int(child.attrib["ExposureTimeMs"]) |
||||
result[exposure] = MeasurementParams(channel.lower(), time) |
||||
return result |
||||
|
||||
|
||||
def _get_measurement_params(folder): |
||||
""" returns measurement parameters """ |
||||
params_file = _search_measurement_params_file(folder) |
||||
if params_file is not None: |
||||
return _parse_measurement_params(params_file) |
||||
return None |
||||
|
||||
|
||||
def _add_measurement_params(data_frame, params): |
||||
""" adds measurement parameters to a data frame """ |
||||
for exposure_id, info in params.items(): |
||||
mask = data_frame["Exposure.Id"] == exposure_id |
||||
data_frame.loc[mask, "Parameters.Channel"] = info.channel |
||||
data_frame.loc[mask, "Parameters.Time"] = info.time |
||||
data_frame["Parameters.Channel"] = data_frame["Parameters.Channel"].astype( |
||||
"category" |
||||
) |
||||
return data_frame |
||||
|
||||
|
||||
def add_optional_measurement_parameters(data_frame, folder): |
||||
""" adds measurement params to the data frame, if they could be parsed """ |
||||
data_frame["Parameters.Channel"] = numpy.nan |
||||
data_frame["Parameters.Time"] = numpy.nan |
||||
params = _get_measurement_params(folder) |
||||
if params: |
||||
available_exposures = set(data_frame["Exposure.Id"].unique()) |
||||
if available_exposures == set(params.keys()): |
||||
return _add_measurement_params(data_frame, params) |
||||
return data_frame |
@ -0,0 +1,37 @@
@@ -0,0 +1,37 @@
|
||||
""" test fixtures """ |
||||
|
||||
from pathlib import Path |
||||
|
||||
import pytest |
||||
|
||||
EXAMPLE_DIR_WO_PARAMS = "mtp_wo_parameters" |
||||
EXAMPLE_DIR_WITH_PARAMS = "mtp_with_parameters" |
||||
|
||||
|
||||
@pytest.fixture |
||||
def example_dir(request): |
||||
root_dir = Path(request.config.rootdir) |
||||
yield root_dir / "example_data" |
||||
|
||||
|
||||
@pytest.fixture |
||||
def example_file(example_dir): |
||||
data_dir = example_dir / EXAMPLE_DIR_WO_PARAMS |
||||
yield data_dir / "160218_SG2-013-001_Regen1_Cy3-100_1_A1_1.csv" |
||||
|
||||
|
||||
@pytest.fixture |
||||
def exposure_df(): |
||||
from pandas import DataFrame |
||||
|
||||
yield DataFrame(data={"Exposure.Id": [1, 2, 3]}) |
||||
|
||||
|
||||
@pytest.fixture |
||||
def dir_for_caching(tmpdir, example_file): |
||||
import shutil |
||||
|
||||
temp_path = Path(tmpdir) |
||||
dest = temp_path / example_file.name |
||||
shutil.copy(example_file, dest) |
||||
yield temp_path |
@ -0,0 +1,125 @@
@@ -0,0 +1,125 @@
|
||||
from .conftest import EXAMPLE_DIR_WO_PARAMS, EXAMPLE_DIR_WITH_PARAMS |
||||
|
||||
|
||||
def test_search_measurement_params_file_ok(example_dir): |
||||
from sensospot_data.parameters import _search_measurement_params_file |
||||
|
||||
result = _search_measurement_params_file( |
||||
example_dir / EXAMPLE_DIR_WITH_PARAMS |
||||
) |
||||
|
||||
assert result.suffix == ".svexp" |
||||
|
||||
|
||||
def test_search_measurement_params_file_no_parameters_folder(example_dir): |
||||
from sensospot_data.parameters import _search_measurement_params_file |
||||
|
||||
result = _search_measurement_params_file( |
||||
example_dir / EXAMPLE_DIR_WO_PARAMS |
||||
) |
||||
|
||||
assert result is None |
||||
|
||||
|
||||
def test_ssearch_measurement_params_file_parameters_file(tmpdir): |
||||
from sensospot_data.parameters import _search_measurement_params_file |
||||
|
||||
params_dir = tmpdir / "Parameters" |
||||
params_dir.mkdir() |
||||
|
||||
result = _search_measurement_params_file(tmpdir) |
||||
|
||||
assert result is None |
||||
|
||||
|
||||
def test_parse_channel_info(example_dir): |
||||
from sensospot_data.parameters import ( |
||||
_search_measurement_params_file, |
||||
_parse_measurement_params, |
||||
) |
||||
|
||||
params = _search_measurement_params_file( |
||||
example_dir / EXAMPLE_DIR_WITH_PARAMS |
||||
) |
||||
result = _parse_measurement_params(params) |
||||
|
||||
assert set(result.keys()) == {1, 2, 3} |
||||
assert result[1] == ("green", 100) |
||||
assert result[2] == ("red", 150) |
||||
assert result[3] == ("red", 15) |
||||
|
||||
|
||||
def test_get_measurement_params_file_found(example_dir): |
||||
from sensospot_data.parameters import _get_measurement_params |
||||
|
||||
result = _get_measurement_params(example_dir / EXAMPLE_DIR_WITH_PARAMS) |
||||
|
||||
assert set(result.keys()) == {1, 2, 3} |
||||
assert result[1] == ("green", 100) |
||||
assert result[2] == ("red", 150) |
||||
assert result[3] == ("red", 15) |
||||
|
||||
|
||||
def test_get_measurement_params_file_not_found(example_dir): |
||||
from sensospot_data.parameters import _get_measurement_params |
||||
|
||||
result = _get_measurement_params(example_dir / EXAMPLE_DIR_WO_PARAMS) |
||||
|
||||
assert result is None |
||||
|
||||
|
||||
def test_add_measurement_params(exposure_df): |
||||
from sensospot_data.parameters import ( |
||||
_add_measurement_params, |
||||
MeasurementParams, |
||||
) |
||||
|
||||
params = { |
||||
1: MeasurementParams("red", 10), |
||||
2: MeasurementParams("green", 20), |
||||
3: MeasurementParams("blue", 50), |
||||
} |
||||
|
||||
result = _add_measurement_params(exposure_df, params) |
||||
|
||||
assert result["Exposure.Id"][0] == 1 |
||||
assert result["Parameters.Channel"][0] == "red" |
||||
assert result["Parameters.Time"][0] == 10 |
||||
assert result["Exposure.Id"][1] == 2 |
||||
assert result["Parameters.Channel"][1] == "green" |
||||
assert result["Parameters.Time"][1] == 20 |
||||
assert result["Exposure.Id"][2] == 3 |
||||
assert result["Parameters.Channel"][2] == "blue" |
||||
assert result["Parameters.Time"][2] == 50 |
||||
|
||||
|
||||
def test_add_optional_measurement_parameters_with_params_file( |
||||
exposure_df, example_dir |
||||
): |
||||
from sensospot_data.parameters import add_optional_measurement_parameters |
||||
|
||||
folder = example_dir / EXAMPLE_DIR_WITH_PARAMS |
||||
add_optional_measurement_parameters(exposure_df, folder) |
||||
|
||||
expected = [(1, "green", 100), (2, "red", 150), (3, "red", 15)] |
||||
for exposure_id, channel, time in expected: |
||||
mask = exposure_df["Exposure.Id"] == exposure_id |
||||
example_row = exposure_df.loc[mask].iloc[0] |
||||
assert example_row["Parameters.Channel"] == channel |
||||
assert example_row["Parameters.Time"] == time |
||||
|
||||
|
||||
def test_add_optional_measurement_parameters_without_params_file( |
||||
exposure_df, example_dir |
||||
): |
||||
from sensospot_data.parameters import add_optional_measurement_parameters |
||||
from pandas import isnull |
||||
|
||||
folder = example_dir / EXAMPLE_DIR_WO_PARAMS |
||||
add_optional_measurement_parameters(exposure_df, folder) |
||||
|
||||
for exposure_id in range(1, 4): |
||||
mask = exposure_df["Exposure.Id"] == exposure_id |
||||
example_row = exposure_df.loc[mask].iloc[0] |
||||
assert isnull(example_row["Parameters.Channel"]) |
||||
assert isnull(example_row["Parameters.Time"]) |
Loading…
Reference in new issue