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.
75 lines
2.5 KiB
75 lines
2.5 KiB
4 years ago
|
""" 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
|