tests.test_scans

  1import os
  2
  3from csi_images.csi_scans import Scan
  4
  5
  6def test_from_yaml():
  7    scan = Scan.load_yaml("tests/data")
  8    # Assert that the scan is valid
  9    assert scan.slide_id != ""
 10    assert scan.exists
 11    assert scan.path != ""
 12    assert scan.start_datetime != ""
 13    assert scan.end_datetime != ""
 14    assert scan.scan_time_s > 0
 15    assert scan.scanner_id != ""
 16    assert scan.tray_pos != ""
 17    assert scan.slide_pos != ""
 18    assert scan.camera != ""
 19    assert scan.objective != ""
 20    assert scan.pixel_size_um > 0
 21    assert scan.tile_width_px > 0
 22    assert scan.tile_height_px > 0
 23    assert scan.tile_x_offset_px >= 0
 24    assert scan.tile_y_offset_px >= 0
 25    assert scan.tile_overlap_proportion >= 0
 26    assert len(scan.channels) > 0
 27    for channel in scan.channels:
 28        assert channel.name != ""
 29        assert channel.exposure_ms > 0
 30        assert channel.intensity > 0
 31        assert channel.gain_applied
 32    assert len(scan.roi) > 0
 33    for roi in scan.roi:
 34        assert roi.origin_x_um != -1
 35        assert roi.origin_y_um != -1
 36        assert roi.width_um > 0
 37        assert roi.height_um > 0
 38        assert roi.tile_rows > 0
 39        assert roi.tile_cols > 0
 40        assert roi.focus_points is not None
 41
 42    # Should be able to read and autopopulate scan.yaml component
 43    assert scan == Scan.load_yaml("tests/data/scan.yaml")
 44
 45    # Write, read, then delete the scan.yaml
 46    scan.save_yaml("tests/data/temp.yaml")
 47    assert scan == Scan.load_yaml("tests/data/temp.yaml")
 48    os.remove("tests/data/temp.yaml")
 49
 50    # If we change the name, it's no longer equal but has the same profile
 51    scan2 = Scan.load_yaml("tests/data")
 52    scan2.slide_id = "DIFFERENT"
 53    assert scan != scan2
 54    assert scan.has_same_profile(scan2)
 55
 56    # If we change the tile size, it no longer has the same profile
 57    scan2 = Scan.load_yaml("tests/data")
 58    scan2.tile_width_px = 1
 59    assert scan != scan2
 60    assert not scan.has_same_profile(scan2)
 61
 62
 63def test_from_txt():
 64    scan = Scan.load_txt("tests/data")
 65    # Assert that the scan is valid
 66    assert scan.slide_id != ""
 67    assert scan.exists
 68    assert scan.path != ""
 69    assert scan.start_datetime != ""
 70    assert scan.end_datetime != ""
 71    assert scan.scan_time_s > 0
 72    assert scan.scanner_id != ""
 73    assert scan.tray_pos != ""
 74    assert scan.slide_pos != ""
 75    # assert scan.camera != ""  # Unclear
 76    assert scan.objective != ""
 77    assert scan.pixel_size_um > 0
 78    assert scan.tile_width_px > 0
 79    assert scan.tile_height_px > 0
 80    assert scan.tile_x_offset_px >= 0
 81    assert scan.tile_y_offset_px >= 0
 82    assert scan.tile_overlap_proportion >= 0
 83    assert len(scan.channels) > 0
 84    for channel in scan.channels:
 85        assert channel.name != ""
 86        assert channel.exposure_ms > 0
 87        assert channel.intensity > 0
 88        # assert channel.gain_applied  # Not necessarily clear
 89    assert len(scan.roi) > 0
 90    for roi in scan.roi:
 91        assert roi.origin_x_um != -1
 92        assert roi.origin_y_um != -1
 93        assert roi.width_um > 0
 94        assert roi.height_um > 0
 95        assert roi.tile_rows > 0
 96        assert roi.tile_cols > 0
 97        assert roi.focus_points is not None
 98
 99    # Should be able to read and autopopulate scan.txt component
100    assert scan == Scan.load_txt("tests/data/slideinfo.txt")
101
102
103def test_dict():
104    scan = Scan.load_txt("tests/data")
105    # Should be the same back and forth from dictionary
106    assert scan == Scan.from_dict(scan.to_dict())
107
108
109def test_names_and_indices():
110    # Should be able to get the correct indices for the channels
111    scan = Scan.load_txt("tests/data")
112    correct_channel_order = ["DAPI", "TRITC", "CY5", "BF", "FITC"]
113    assert scan.get_channel_indices(correct_channel_order) == [0, 1, 2, 3, 4]
114
115    # Should return -1 for None
116    assert scan.get_channel_indices([None]) == [-1]
117
118    # Should return -1 for invalid channel names
119    assert scan.get_channel_indices(["INVALID"]) == [-1]
120
121
122def test_image_size():
123    scan = Scan.load_yaml("tests/data")
124    assert scan.get_image_size() == (2020, 2020)
def test_from_yaml():
 7def test_from_yaml():
 8    scan = Scan.load_yaml("tests/data")
 9    # Assert that the scan is valid
10    assert scan.slide_id != ""
11    assert scan.exists
12    assert scan.path != ""
13    assert scan.start_datetime != ""
14    assert scan.end_datetime != ""
15    assert scan.scan_time_s > 0
16    assert scan.scanner_id != ""
17    assert scan.tray_pos != ""
18    assert scan.slide_pos != ""
19    assert scan.camera != ""
20    assert scan.objective != ""
21    assert scan.pixel_size_um > 0
22    assert scan.tile_width_px > 0
23    assert scan.tile_height_px > 0
24    assert scan.tile_x_offset_px >= 0
25    assert scan.tile_y_offset_px >= 0
26    assert scan.tile_overlap_proportion >= 0
27    assert len(scan.channels) > 0
28    for channel in scan.channels:
29        assert channel.name != ""
30        assert channel.exposure_ms > 0
31        assert channel.intensity > 0
32        assert channel.gain_applied
33    assert len(scan.roi) > 0
34    for roi in scan.roi:
35        assert roi.origin_x_um != -1
36        assert roi.origin_y_um != -1
37        assert roi.width_um > 0
38        assert roi.height_um > 0
39        assert roi.tile_rows > 0
40        assert roi.tile_cols > 0
41        assert roi.focus_points is not None
42
43    # Should be able to read and autopopulate scan.yaml component
44    assert scan == Scan.load_yaml("tests/data/scan.yaml")
45
46    # Write, read, then delete the scan.yaml
47    scan.save_yaml("tests/data/temp.yaml")
48    assert scan == Scan.load_yaml("tests/data/temp.yaml")
49    os.remove("tests/data/temp.yaml")
50
51    # If we change the name, it's no longer equal but has the same profile
52    scan2 = Scan.load_yaml("tests/data")
53    scan2.slide_id = "DIFFERENT"
54    assert scan != scan2
55    assert scan.has_same_profile(scan2)
56
57    # If we change the tile size, it no longer has the same profile
58    scan2 = Scan.load_yaml("tests/data")
59    scan2.tile_width_px = 1
60    assert scan != scan2
61    assert not scan.has_same_profile(scan2)
def test_from_txt():
 64def test_from_txt():
 65    scan = Scan.load_txt("tests/data")
 66    # Assert that the scan is valid
 67    assert scan.slide_id != ""
 68    assert scan.exists
 69    assert scan.path != ""
 70    assert scan.start_datetime != ""
 71    assert scan.end_datetime != ""
 72    assert scan.scan_time_s > 0
 73    assert scan.scanner_id != ""
 74    assert scan.tray_pos != ""
 75    assert scan.slide_pos != ""
 76    # assert scan.camera != ""  # Unclear
 77    assert scan.objective != ""
 78    assert scan.pixel_size_um > 0
 79    assert scan.tile_width_px > 0
 80    assert scan.tile_height_px > 0
 81    assert scan.tile_x_offset_px >= 0
 82    assert scan.tile_y_offset_px >= 0
 83    assert scan.tile_overlap_proportion >= 0
 84    assert len(scan.channels) > 0
 85    for channel in scan.channels:
 86        assert channel.name != ""
 87        assert channel.exposure_ms > 0
 88        assert channel.intensity > 0
 89        # assert channel.gain_applied  # Not necessarily clear
 90    assert len(scan.roi) > 0
 91    for roi in scan.roi:
 92        assert roi.origin_x_um != -1
 93        assert roi.origin_y_um != -1
 94        assert roi.width_um > 0
 95        assert roi.height_um > 0
 96        assert roi.tile_rows > 0
 97        assert roi.tile_cols > 0
 98        assert roi.focus_points is not None
 99
100    # Should be able to read and autopopulate scan.txt component
101    assert scan == Scan.load_txt("tests/data/slideinfo.txt")
def test_dict():
104def test_dict():
105    scan = Scan.load_txt("tests/data")
106    # Should be the same back and forth from dictionary
107    assert scan == Scan.from_dict(scan.to_dict())
def test_names_and_indices():
110def test_names_and_indices():
111    # Should be able to get the correct indices for the channels
112    scan = Scan.load_txt("tests/data")
113    correct_channel_order = ["DAPI", "TRITC", "CY5", "BF", "FITC"]
114    assert scan.get_channel_indices(correct_channel_order) == [0, 1, 2, 3, 4]
115
116    # Should return -1 for None
117    assert scan.get_channel_indices([None]) == [-1]
118
119    # Should return -1 for invalid channel names
120    assert scan.get_channel_indices(["INVALID"]) == [-1]
def test_image_size():
123def test_image_size():
124    scan = Scan.load_yaml("tests/data")
125    assert scan.get_image_size() == (2020, 2020)