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.

81 lines
2.7 KiB

""" 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
from .columns import (
COL_NAME_EXPOSURE_ID,
COL_NAME_PARAMETERS_TIME,
COL_NAME_PARAMETERS_CHANNEL,
)
ExposureInfo = namedtuple("ExposureInfo", ["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] = ExposureInfo(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[COL_NAME_EXPOSURE_ID] == exposure_id
data_frame.loc[mask, COL_NAME_PARAMETERS_CHANNEL] = info.channel
data_frame.loc[mask, COL_NAME_PARAMETERS_TIME] = info.time
data_frame[COL_NAME_PARAMETERS_CHANNEL] = data_frame[
COL_NAME_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[COL_NAME_PARAMETERS_CHANNEL] = numpy.nan
data_frame[COL_NAME_PARAMETERS_TIME] = numpy.nan
params = _get_measurement_params(folder)
if params:
available_exposures = set(data_frame[COL_NAME_EXPOSURE_ID].unique())
if available_exposures == set(params.keys()):
return _add_measurement_params(data_frame, params)
return data_frame