""" Sensospot Data Parser Parsing the numerical output from Sensovations Sensospot image analysis. """ from pathlib import Path from collections import namedtuple import numpy import pandas from defusedxml import ElementTree from . import columns 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 _get_channel_data(channel_node): # child.tag == "ChannelConfig1" exposure_id = int(channel_node.tag[-1]) # channel_description == "[Cy3|Cy5] Green" description = channel_node.attrib["Description"] exposure_channel = description.rsplit(" ", 1)[-1] # floats can be used for exposure times, not only ints exposure_time = float(channel_node.attrib["ExposureTimeMs"]) return { columns.EXPOSURE_ID: exposure_id, columns.PARAMETERS_CHANNEL: exposure_channel.lower(), columns.PARAMETERS_TIME: exposure_time, } 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) data = [_get_channel_data(child) for child in tree.find("Channels")] return pandas.DataFrame(data) 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_optional_measurement_parameters(data_frame, folder): """adds measurement params to the data frame, if they could be parsed""" params = get_measurement_params(folder) if params is not None: params_exposures = params[columns.EXPOSURE_ID].unique() data_exposures = data_frame[columns.EXPOSURE_ID].unique() if set(data_exposures) == set(params_exposures): return data_frame.merge(params, how="left", on=columns.EXPOSURE_ID) # only executing if the parameters were not merged to the data frame data_frame[columns.PARAMETERS_CHANNEL] = numpy.nan data_frame[columns.PARAMETERS_TIME] = numpy.nan return data_frame