|
|
|
from collections import namedtuple
|
|
|
|
|
|
|
|
import pandas
|
|
|
|
import pytest
|
|
|
|
|
|
|
|
from .conftest import EXAMPLE_DIR_WO_PARAMS, EXAMPLE_DIR_WITH_PARAMS
|
|
|
|
|
|
|
|
ExposureSetting = namedtuple("ExposureSetting", ["channel", "time"])
|
|
|
|
|
|
|
|
|
|
|
|
def test_split_data_frame(example_dir):
|
|
|
|
from sensospot_data.parser import process_folder
|
|
|
|
from sensospot_data.normalisation import _split_data_frame
|
|
|
|
|
|
|
|
data_frame = process_folder(example_dir / EXAMPLE_DIR_WITH_PARAMS)
|
|
|
|
|
|
|
|
result = _split_data_frame(data_frame, "Well.Row")
|
|
|
|
|
|
|
|
assert set(result.keys()) == set("ABC")
|
|
|
|
for key, value_df in result.items():
|
|
|
|
assert set(value_df["Well.Row"].unique()) == {key}
|
|
|
|
|
|
|
|
|
|
|
|
def test_infer_exposure_from_parameters(example_dir):
|
|
|
|
from sensospot_data.parser import process_folder
|
|
|
|
from sensospot_data.normalisation import _infer_exposure_from_parameters
|
|
|
|
|
|
|
|
data_frame = process_folder(example_dir / EXAMPLE_DIR_WITH_PARAMS)
|
|
|
|
result = _infer_exposure_from_parameters(data_frame)
|
|
|
|
|
|
|
|
assert all(result["Exposure.Channel"] == result["Parameters.Channel"])
|
|
|
|
assert all(result["Exposure.Time"] == result["Parameters.Time"])
|
|
|
|
|
|
|
|
|
|
|
|
def test_infer_exposure_from_parameters_raises_error(example_dir):
|
|
|
|
from sensospot_data.parser import process_folder
|
|
|
|
from sensospot_data.normalisation import _infer_exposure_from_parameters
|
|
|
|
|
|
|
|
data_frame = process_folder(example_dir / EXAMPLE_DIR_WO_PARAMS)
|
|
|
|
|
|
|
|
with pytest.raises(ValueError) as excinfo:
|
|
|
|
_infer_exposure_from_parameters(data_frame)
|
|
|
|
|
|
|
|
assert str(excinfo.value).startswith("Exposure Map: measurement")
|
|
|
|
|
|
|
|
|
|
|
|
def test_apply_exposure_map(example_dir):
|
|
|
|
from sensospot_data.parser import process_folder
|
|
|
|
from sensospot_data.normalisation import apply_exposure_map
|
|
|
|
|
|
|
|
exposure_map = {
|
|
|
|
1: ExposureSetting("Cy3", 100),
|
|
|
|
2: ExposureSetting("Cy5", 15),
|
|
|
|
3: ExposureSetting("Cy5", 150),
|
|
|
|
}
|
|
|
|
|
|
|
|
data_frame = process_folder(example_dir / EXAMPLE_DIR_WITH_PARAMS)
|
|
|
|
result = apply_exposure_map(data_frame, exposure_map)
|
|
|
|
|
|
|
|
for key, value in exposure_map.items():
|
|
|
|
mask = result["Exposure.Id"] == key
|
|
|
|
partial = result.loc[mask]
|
|
|
|
assert set(partial["Exposure.Channel"].unique()) == {value.channel}
|
|
|
|
assert set(partial["Exposure.Time"].unique()) == {value.time}
|
|
|
|
|
|
|
|
|
|
|
|
def test_apply_exposure_map_raises_error(example_dir):
|
|
|
|
from sensospot_data.parser import process_folder
|
|
|
|
from sensospot_data.normalisation import apply_exposure_map
|
|
|
|
|
|
|
|
exposure_map = {
|
|
|
|
1: ExposureSetting("Cy3", 100),
|
|
|
|
2: ExposureSetting("Cy5", 15),
|
|
|
|
"X": ExposureSetting("Cy5", 150),
|
|
|
|
}
|
|
|
|
|
|
|
|
data_frame = process_folder(example_dir / EXAMPLE_DIR_WITH_PARAMS)
|
|
|
|
|
|
|
|
with pytest.raises(ValueError) as excinfo:
|
|
|
|
apply_exposure_map(data_frame, exposure_map)
|
|
|
|
|
|
|
|
assert str(excinfo.value).startswith("Exposure Map differs")
|
|
|
|
|
|
|
|
|
|
|
|
def test_apply_exposure_map_from_parameters(example_dir):
|
|
|
|
from sensospot_data.parser import process_folder
|
|
|
|
from sensospot_data.normalisation import apply_exposure_map
|
|
|
|
|
|
|
|
data_frame = process_folder(example_dir / EXAMPLE_DIR_WITH_PARAMS)
|
|
|
|
result = apply_exposure_map(data_frame, None)
|
|
|
|
|
|
|
|
assert all(result["Exposure.Channel"] == result["Parameters.Channel"])
|
|
|
|
assert all(result["Exposure.Time"] == result["Parameters.Time"])
|
|
|
|
|
|
|
|
|
|
|
|
def test_apply_exposure_map_from_parameters_raises_error(example_dir):
|
|
|
|
from sensospot_data.parser import process_folder
|
|
|
|
from sensospot_data.normalisation import apply_exposure_map
|
|
|
|
|
|
|
|
data_frame = process_folder(example_dir / EXAMPLE_DIR_WO_PARAMS)
|
|
|
|
|
|
|
|
with pytest.raises(ValueError) as excinfo:
|
|
|
|
apply_exposure_map(data_frame, None)
|
|
|
|
|
|
|
|
assert str(excinfo.value).startswith("Exposure Map: measurement")
|
|
|
|
|
|
|
|
|
|
|
|
def test_check_overflow_limit_defaults():
|
|
|
|
from sensospot_data.normalisation import _check_overflow_limit
|
|
|
|
|
|
|
|
data_frame = pandas.DataFrame(data={"Spot.Mean": [0.1, 0.5, 0.6]})
|
|
|
|
|
|
|
|
result = _check_overflow_limit(data_frame)
|
|
|
|
|
|
|
|
assert list(result["Spot.Overflow"]) == [False, False, True]
|
|
|
|
|
|
|
|
|
|
|
|
def test_check_overflow_limit_custom_limit():
|
|
|
|
from sensospot_data.normalisation import _check_overflow_limit
|
|
|
|
|
|
|
|
data_frame = pandas.DataFrame(data={"Spot.Sat": [4, 2, 3, 4]})
|
|
|
|
|
|
|
|
result = _check_overflow_limit(data_frame, "Spot.Sat", 2)
|
|
|
|
|
|
|
|
assert list(result["Spot.Overflow"]) == [True, False, True, True]
|
|
|
|
|
|
|
|
|
|
|
|
def test_reduce_overflow_in_channel(normalization_data_frame):
|
|
|
|
from sensospot_data.normalisation import (
|
|
|
|
_reduce_overflow_in_channel,
|
|
|
|
_check_overflow_limit,
|
|
|
|
)
|
|
|
|
|
|
|
|
data_frame = _check_overflow_limit(
|
|
|
|
normalization_data_frame, "Saturation", 1
|
|
|
|
)
|
|
|
|
result = _reduce_overflow_in_channel(data_frame)
|
|
|
|
|
|
|
|
sorted_results = result.sort_values(
|
|
|
|
by=["Well.Row", "Well.Column", "Pos.Id"]
|
|
|
|
)
|
|
|
|
|
|
|
|
assert list(sorted_results["Value"]) == [
|
|
|
|
1,
|
|
|
|
2,
|
|
|
|
3,
|
|
|
|
1,
|
|
|
|
10,
|
|
|
|
10,
|
|
|
|
10,
|
|
|
|
10,
|
|
|
|
100,
|
|
|
|
100,
|
|
|
|
100,
|
|
|
|
100,
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
def test_reduce_overflow_in_channel_shortcut(normalization_data_frame):
|
|
|
|
from sensospot_data.normalisation import (
|
|
|
|
_reduce_overflow_in_channel,
|
|
|
|
_check_overflow_limit,
|
|
|
|
)
|
|
|
|
|
|
|
|
normalization_data_frame["Exposure.Time"] = 1
|
|
|
|
|
|
|
|
data_frame = _check_overflow_limit(
|
|
|
|
normalization_data_frame, "Saturation", 1
|
|
|
|
)
|
|
|
|
result = _reduce_overflow_in_channel(data_frame)
|
|
|
|
|
|
|
|
assert result is data_frame
|
|
|
|
|
|
|
|
|
|
|
|
def test_reduce_overflow(normalization_data_frame):
|
|
|
|
from sensospot_data.normalisation import reduce_overflow
|
|
|
|
|
|
|
|
result = reduce_overflow(normalization_data_frame, "Saturation", 1)
|
|
|
|
|
|
|
|
assert "Cy5" in result
|
|
|
|
|
|
|
|
sorted_results = result["Cy5"].sort_values(
|
|
|
|
by=["Well.Row", "Well.Column", "Pos.Id"]
|
|
|
|
)
|
|
|
|
|
|
|
|
assert list(sorted_results["Value"]) == [
|
|
|
|
1,
|
|
|
|
2,
|
|
|
|
3,
|
|
|
|
1,
|
|
|
|
10,
|
|
|
|
10,
|
|
|
|
10,
|
|
|
|
10,
|
|
|
|
100,
|
|
|
|
100,
|
|
|
|
100,
|
|
|
|
100,
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
def test_infer_normalization_map(normalization_data_frame):
|
|
|
|
from sensospot_data.normalisation import (
|
|
|
|
_infer_normalization_map,
|
|
|
|
_split_data_frame,
|
|
|
|
)
|
|
|
|
|
|
|
|
normalization_data_frame.loc[5, "Exposure.Channel"] = "Cy3"
|
|
|
|
split_frames = _split_data_frame(
|
|
|
|
normalization_data_frame, "Exposure.Channel"
|
|
|
|
)
|
|
|
|
|
|
|
|
result = _infer_normalization_map(split_frames)
|
|
|
|
|
|
|
|
assert result == {"Cy3": 25, "Cy5": 50}
|
|
|
|
|
|
|
|
|
|
|
|
def test_normalize_exposure(normalization_data_frame):
|
|
|
|
from sensospot_data.normalisation import (
|
|
|
|
_normalize_exposure,
|
|
|
|
reduce_overflow,
|
|
|
|
)
|
|
|
|
from sensospot_data.columns import COLUMN_NORMALIZATION
|
|
|
|
|
|
|
|
reduced = reduce_overflow(normalization_data_frame, "Saturation", 1)
|
|
|
|
result = _normalize_exposure(reduced["Cy5"], 100)
|
|
|
|
|
|
|
|
sorted_results = result.sort_values(
|
|
|
|
by=["Well.Row", "Well.Column", "Pos.Id"]
|
|
|
|
)
|
|
|
|
expected_values = [1, 4, 15, 1, 10, 10, 10, 10, 100, 100, 100, 100]
|
|
|
|
|
|
|
|
for normalized_col in COLUMN_NORMALIZATION.values():
|
|
|
|
list(sorted_results[normalized_col]) == expected_values
|
|
|
|
|
|
|
|
|
|
|
|
def test_normalize_exposure_time(normalization_data_frame):
|
|
|
|
from sensospot_data.normalisation import (
|
|
|
|
normalize_exposure_time,
|
|
|
|
reduce_overflow,
|
|
|
|
)
|
|
|
|
|
|
|
|
reduced = reduce_overflow(normalization_data_frame, "Saturation", 1)
|
|
|
|
result = normalize_exposure_time(reduced)
|
|
|
|
|
|
|
|
assert "Cy5" in result
|
|
|
|
|
|
|
|
sorted_results = result["Cy5"].sort_values(
|
|
|
|
by=["Well.Row", "Well.Column", "Pos.Id"]
|
|
|
|
)
|
|
|
|
expected_values = [1, 4, 15, 1, 10, 10, 10, 10, 100, 100, 100, 100]
|
|
|
|
|
|
|
|
assert list(sorted_results["Normalized.Spot.Mean"]) == expected_values
|
|
|
|
|
|
|
|
|
|
|
|
def test_normalize_exposure_time_infered_map(normalization_data_frame):
|
|
|
|
from sensospot_data.normalisation import (
|
|
|
|
normalize_exposure_time,
|
|
|
|
reduce_overflow,
|
|
|
|
)
|
|
|
|
|
|
|
|
reduced = reduce_overflow(normalization_data_frame, "Saturation", 1)
|
|
|
|
result = normalize_exposure_time(reduced)
|
|
|
|
|
|
|
|
assert "Cy5" in result
|
|
|
|
|
|
|
|
sorted_results = result["Cy5"].sort_values(
|
|
|
|
by=["Well.Row", "Well.Column", "Pos.Id"]
|
|
|
|
)
|
|
|
|
expected_values = [1, 4, 15, 1, 10, 10, 10, 10, 100, 100, 100, 100]
|
|
|
|
|
|
|
|
assert list(sorted_results["Normalized.Spot.Mean"]) == expected_values
|
|
|
|
|
|
|
|
|
|
|
|
def test_normalize_measurement(example_dir):
|
|
|
|
from sensospot_data.normalisation import normalize_measurement
|
|
|
|
from sensospot_data.parser import process_folder
|
|
|
|
|
|
|
|
sub_dir = example_dir / EXAMPLE_DIR_WITH_PARAMS
|
|
|
|
data_frame = process_folder(sub_dir)
|
|
|
|
|
|
|
|
exposure_map = {
|
|
|
|
1: ExposureSetting("Cy3", 100),
|
|
|
|
2: ExposureSetting("Cy5", 15),
|
|
|
|
3: ExposureSetting("Cy5", 150),
|
|
|
|
}
|
|
|
|
|
|
|
|
result = normalize_measurement(data_frame, exposure_map)
|
|
|
|
cy3_df, cy5_df = result["Cy3"], result["Cy5"]
|
|
|
|
|
|
|
|
assert set(result.keys()) == {"Cy3", "Cy5"}
|
|
|
|
assert cy3_df["Normalized.Exposure.Time"].unique() == 100
|
|
|
|
assert cy5_df["Normalized.Exposure.Time"].unique() == 150
|