Skip to content

Commit

Permalink
Update re-coordination tests for new functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
leorudczenko committed Jan 26, 2024
1 parent 72fb621 commit fd95626
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 50 deletions.
3 changes: 2 additions & 1 deletion tactool/analysis_point.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
DictReader,
writer,
)
from pathlib import Path
from typing import Any

from PyQt5.QtWidgets import (
Expand Down Expand Up @@ -256,7 +257,7 @@ def convert_export_point(analysis_point: AnalysisPoint, headers: list[str]) -> l
return analysis_point_row


def parse_sem_csv(filepath: str) -> list[dict[str, str | int | float]]:
def parse_sem_csv(filepath: str | Path) -> list[dict[str, str | int | float]]:
"""
Parse an SEM CSV file into a list of dictionaries.
We only retain the integer ID value and the coordinates of the points.
Expand Down
35 changes: 35 additions & 0 deletions test/test_import_export.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from tactool.analysis_point import (
AnalysisPoint,
export_tactool_csv,
parse_sem_csv,
)


Expand Down Expand Up @@ -172,3 +173,37 @@ def assert_csv_data(csv_path: str, expected_headers: list[str], expected_data: l
# Attributes from the expected Analysis Point are converted to a string because
# the raw CSV data will all be a string type
assert csv_attribute == str(item_attribute)


def test_parse_sem_csv_good():
# Arrange
sem_csv = Path("test/data/SEM_co-ordinate_import_test_set.csv")
expected_point_dicts = [
{"label": "RefMark", "x": 91.576, "y": 67.762},
{"label": "RefMark", "x": 86.01, "y": 55.893},
{"label": "RefMark", "x": 98.138, "y": 49.417},
{"apid": 509, "label": "Spot", "x": 96.764747, "y": 49.303754},
{"apid": 577, "label": "Spot", "x": 97.520798, "y": 55.785059},
{"apid": 662, "label": "Spot", "x": 93.746436, "y": 60.03264},
{"apid": 705, "label": "Spot", "x": 91.770031, "y": 62.312733},
{"apid": 759, "label": "Spot", "x": 92.415936, "y": 67.080603},
]

# Act
actual_point_dicts = parse_sem_csv(sem_csv)

# Assert
assert expected_point_dicts == actual_point_dicts


def test_parse_sem_csv_bad():
# Arrange
sem_csv = Path("test/data/analysis_points_complete.csv")
expected_error = "SEM CSV missing required header: Particle ID"

# Act
with pytest.raises(KeyError) as excinfo:
parse_sem_csv(sem_csv)

# Assert
assert expected_error in str(excinfo.value)
91 changes: 42 additions & 49 deletions test/test_transformation.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@
Tests for functions in the transformation module
"""
import numpy as np
from csv import DictReader
from pathlib import Path
from typing import Any

import pytest

Expand Down Expand Up @@ -65,9 +64,6 @@ def test_affine_transform_matrix():


def test_toggle_recoordinate_dialog(tactool: TACtool, monkeypatch_qmsgbox_question_yes: pytest.MonkeyPatch):
# close recoord window
# check that toggling off works, main widgets, grey rect, disable graphics scene points

# Check that the RecoordinateDialog does not exist
assert tactool.window.recoordinate_dialog is None
# Check that the main input widgets are enabled
Expand Down Expand Up @@ -120,70 +116,67 @@ def test_toggle_recoordinate_dialog(tactool: TACtool, monkeypatch_qmsgbox_questi


@pytest.mark.parametrize(
["input_csv", "expected_coordinates", "recoordinate_args", "non_coord_headers"],
["input_csv", "expected_points_data"],
[
(
"test/data/analysis_points_complete.csv",
[(336, 472), (318, 394), (268, 469), (340, 527), (380, 362)],
{"invert_x_axis_dest": False, "x_header": "X", "y_header": "Y",
"ref_col": "Type", "ref_label": "RefMark"},
["Name", "Type", "diameter", "scale", "colour", "mount_name", "material", "notes"],
),
(
"test/data/SEM_co-ordinate_import_test_set.csv",
[(460, 472), (478, 394), (528, 469), (525, 458), (509, 483), (487, 466), (476, 458), (464, 477)],
{"invert_x_axis_dest": True, "x_header": "Laser Ablation Centre X", "y_header": "Laser Ablation Centre Y",
"ref_col": "Mineral Classification", "ref_label": "Fiducial"},
["Particle ID", "Mineral Classification", "Effective Diameter m",
"Feret Max Diameter m", "Feret Min Diameter m", "F (N)", "Cl (N)"],
[
[1, "RefMark", 336, 472, 50, 2.0, "#222222", "sample_x83", "mount_x81", "rock", ""],
[2, "RefMark", 318, 394, 50, 2.0, "#222222", "sample_x83", "mount_x81", "rock", ""],
[3, "RefMark", 268, 469, 50, 2.0, "#222222", "sample_x83", "mount_x81", "rock", ""],
[509, "Spot", 271, 458, 50, 2.0, "#222222", "sample_x83", "mount_x81", "rock", ""],
[577, "Spot", 287, 483, 50, 2.0, "#222222", "sample_x83", "mount_x81", "rock", ""],
[662, "Spot", 309, 466, 50, 2.0, "#222222", "sample_x83", "mount_x81", "rock", ""],
[705, "Spot", 320, 458, 50, 2.0, "#222222", "sample_x83", "mount_x81", "rock", ""],
[759, "Spot", 332, 477, 50, 2.0, "#222222", "sample_x83", "mount_x81", "rock", ""],
],
),
(
"test/data/SEM_co-ordinate_import_test_set_4_refs.csv",
[(460, 472), (478, 394), (528, 469), (472, 447), (525, 458),
(509, 483), (487, 466), (476, 458), (464, 477)],
{"invert_x_axis_dest": True, "x_header": "Laser Ablation Centre X", "y_header": "Laser Ablation Centre Y",
"ref_col": "Mineral Classification", "ref_label": "Fiducial"},
["Particle ID", "Mineral Classification", "Effective Diameter m",
"Feret Max Diameter m", "Feret Min Diameter m", "F (N)", "Cl (N)"],
[
[1, "RefMark", 336, 472, 50, 2.0, "#222222", "sample_x83", "mount_x81", "rock", ""],
[2, "RefMark", 318, 394, 50, 2.0, "#222222", "sample_x83", "mount_x81", "rock", ""],
[3, "RefMark", 268, 469, 50, 2.0, "#222222", "sample_x83", "mount_x81", "rock", ""],
[4, "RefMark", 324, 447, 50, 2.0, "#222222", "sample_x83", "mount_x81", "rock", ""],
[509, "Spot", 271, 458, 50, 2.0, "#222222", "sample_x83", "mount_x81", "rock", ""],
[577, "Spot", 287, 483, 50, 2.0, "#222222", "sample_x83", "mount_x81", "rock", ""],
[662, "Spot", 309, 466, 50, 2.0, "#222222", "sample_x83", "mount_x81", "rock", ""],
[705, "Spot", 320, 458, 50, 2.0, "#222222", "sample_x83", "mount_x81", "rock", ""],
[759, "Spot", 332, 477, 50, 2.0, "#222222", "sample_x83", "mount_x81", "rock", ""],
],
),
],
)
def test_recoordinate_sem_points(
tmp_path: Path,
def test_import_and_recoordinate_sem_csv(
tactool: TACtool,
public_index: int,
input_csv: str,
expected_coordinates: list[tuple[int, int]],
recoordinate_args: dict[str, str],
non_coord_headers: list[str],
expected_points_data: list[list[Any]],
):
# Arrange
output_csv = tmp_path / "recoordinated_output.csv"
print(output_csv)
# Place 4 Analysis Points which will be used for recoordination
# Only the first 3 should be used
tactool.graphics_view.left_click.emit(336, 472)
tactool.graphics_view.left_click.emit(318, 394)
tactool.graphics_view.left_click.emit(268, 469)
tactool.graphics_view.left_click.emit(87, 392)
# Toggle recoordinate dialog so that the recoordinate_dialog is callable
tactool.window.toggle_recoordinate_dialog()
# Modify the Analysis Point settings as these should be applied to the recoordinated points
tactool.window.update_point_settings(
sample_name="sample_x83",
mount_name="mount_x81",
material="rock",
label="Spot",
diameter=50,
scale=2.0,
colour="#222222",
)

# Act
tactool.recoordinate_dialog.recoordinate_sem_points(input_csv, output_csv, **recoordinate_args)
# Toggle recoordinate dialog so that the recoordinate_dialog is callable
tactool.window.toggle_recoordinate_dialog()
tactool.recoordinate_dialog.input_csv_filepath_label.setText(input_csv)
tactool.recoordinate_dialog.import_and_recoordinate_sem_csv()

# Assert
with open(input_csv) as input_file, open(output_csv) as output_file:
input_reader = DictReader(input_file)
output_reader = DictReader(output_file)

# Check that the headers remain the same
assert input_reader.fieldnames == output_reader.fieldnames

# Iterate through CSV file lines
for input_item, output_item, (expect_x, expect_y) in zip(input_reader, output_reader, expected_coordinates):
# Check that the non coordinate fields remain the same
for header in non_coord_headers:
assert input_item[header] == output_item[header]
# Check that the coordinate fields are correct
assert int(output_item[recoordinate_args["x_header"]]) == expect_x
assert int(output_item[recoordinate_args["y_header"]]) == expect_y
for expected_point, actual_point in zip(expected_points_data, tactool.table_model.analysis_points):
assert expected_point == actual_point.aslist()[:public_index]

0 comments on commit fd95626

Please sign in to comment.