tests.test_events
1import os 2import time 3 4import cv2 5import numpy as np 6import pandas as pd 7 8from csi_images import csi_events, csi_tiles, csi_scans 9 10 11if os.environ.get("DEBIAN_FRONTEND") == "noninteractive": 12 SHOW_PLOTS = False 13else: 14 # Change this to your preference for local testing, but commit as True 15 SHOW_PLOTS = True 16 17 18def test_getting_event(): 19 scan = csi_scans.Scan.load_txt("tests/data") 20 tile = csi_tiles.Tile(scan, 1000) 21 event = csi_events.Event( 22 scan, 23 tile, 24 515, 25 411, 26 ) 27 images = event.extract_images() 28 assert len(images) == 4 29 images = event.extract_images(crop_size=100, in_pixels=True) 30 assert images[0].shape == (100, 100) 31 images = event.extract_images(crop_size=50, in_pixels=True) 32 assert images[0].shape == (50, 50) 33 34 if SHOW_PLOTS: 35 for image in images: 36 cv2.imshow("Bright DAPI event in the center", image) 37 cv2.waitKey(0) 38 cv2.destroyAllWindows() 39 40 # Test a corner event 41 event = csi_events.Event( 42 scan, 43 tile, 44 2, 45 1000, 46 ) 47 images = event.extract_images() 48 assert len(images) == 4 49 images = event.extract_images(crop_size=100, in_pixels=True) 50 assert images[0].shape == (100, 100) 51 images = event.extract_images(crop_size=200, in_pixels=True) 52 assert images[0].shape == (200, 200) 53 54 if SHOW_PLOTS: 55 for image in images: 56 cv2.imshow("Events in the corner of a tile", image) 57 cv2.waitKey(0) 58 cv2.destroyAllWindows() 59 60 61def test_getting_many_events(): 62 scan = csi_scans.Scan.load_txt("tests/data") 63 tile = csi_tiles.Tile(scan, 1000) 64 tile2 = csi_tiles.Tile(scan, 0) 65 events = [ 66 csi_events.Event(scan, tile, 515, 411), 67 csi_events.Event(scan, tile2, 2, 1000), 68 csi_events.Event(scan, tile, 1000, 1000), 69 csi_events.Event(scan, tile, 87, 126), 70 csi_events.Event(scan, tile, 1000, 2), 71 csi_events.Event(scan, tile2, 800, 800), 72 csi_events.Event(scan, tile, 1000, 662), 73 ] 74 # Test time to extract images sequentially 75 start_time = time.time() 76 images_1 = [] 77 for event in events: 78 images_1.append(event.extract_images()) 79 sequential_time = time.time() - start_time 80 81 # Test time to extract images in parallel 82 start_time = time.time() 83 images_2 = csi_events.Event.extract_images_for_list(events, crop_size=50) 84 parallel_time = time.time() - start_time 85 assert parallel_time < sequential_time 86 for list_a, list_b in zip(images_1, images_2): 87 assert len(list_a) == len(list_b) 88 for image_a, image_b in zip(list_a, list_b): 89 assert np.array_equal(image_a, image_b) 90 91 # Test that it works after converting to EventArray and back 92 event_array = csi_events.EventArray.from_events(events) 93 remade_events = event_array.to_events( 94 [scan], ignore_metadata=True, ignore_features=True 95 ) 96 images_3 = csi_events.Event.extract_images_for_list( 97 remade_events, 98 crop_size=50, 99 ) 100 101 102def test_event_coordinates_for_bzscanner(): 103 scan = csi_scans.Scan.load_txt("tests/data") 104 # Origin 105 tile = csi_tiles.Tile(scan, 0) 106 event = csi_events.Event(scan, tile, 0, 0) 107 scan_origin = event.get_scan_position() 108 assert 2500 <= scan_origin[0] <= 3500 109 assert 2500 <= scan_origin[1] <= 3500 110 scan_origin_on_slide = event.get_slide_position() 111 assert 71500 <= scan_origin_on_slide[0] <= 72500 112 assert 21500 <= scan_origin_on_slide[1] <= 22500 113 # Within the same tile, "bottom-right corner" 114 event = csi_events.Event(scan, tile, 1000, 1000) 115 scan_position = event.get_scan_position() 116 assert scan_origin[0] <= scan_position[0] 117 assert scan_origin[1] <= scan_position[1] 118 slide_position = event.get_slide_position() 119 assert slide_position[0] <= scan_origin_on_slide[0] 120 assert slide_position[1] <= scan_origin_on_slide[1] 121 122 # Next row, opposite side 123 tile = csi_tiles.Tile(scan, (scan.roi[0].tile_cols - 1, 1)) 124 event = csi_events.Event(scan, tile, 1000, 1000) 125 scan_position = event.get_scan_position() 126 assert scan_origin[0] <= scan_position[0] 127 assert scan_origin[1] <= scan_position[1] 128 slide_position = event.get_slide_position() 129 assert slide_position[0] <= scan_origin_on_slide[0] 130 assert slide_position[1] <= scan_origin_on_slide[1] 131 132 # Opposite corner 133 tile = csi_tiles.Tile(scan, (scan.roi[0].tile_cols - 1, scan.roi[0].tile_rows - 1)) 134 event = csi_events.Event(scan, tile, 1361, 1003) 135 scan_position = event.get_scan_position() 136 assert 21500 <= scan_position[0] <= 22500 137 assert 58500 <= scan_position[1] <= 60500 138 slide_position = event.get_slide_position() 139 assert 14500 <= slide_position[0] <= 15500 140 assert 2500 <= slide_position[1] <= 3500 141 142 143def test_event_coordinates_for_axioscan(): 144 scan = csi_scans.Scan.load_yaml("tests/data") 145 # Origin 146 tile = csi_tiles.Tile(scan, 0) 147 event = csi_events.Event(scan, tile, 0, 0) 148 scan_position = event.get_scan_position() 149 assert -59000 <= scan_position[0] < -55000 150 assert 0 <= scan_position[1] < 4000 151 slide_position = event.get_slide_position() 152 assert 16000 <= slide_position[0] < 20000 153 assert scan_position[1] == slide_position[1] 154 155 # Opposite corner 156 tile = csi_tiles.Tile(scan, (scan.roi[0].tile_cols - 1, scan.roi[0].tile_rows - 1)) 157 event = csi_events.Event(scan, tile, 2000, 2000) 158 scan_position = event.get_scan_position() 159 assert -4000 <= scan_position[0] <= 0 160 assert 21000 <= scan_position[1] <= 25000 161 slide_position = event.get_slide_position() 162 assert 71000 <= slide_position[0] <= 75000 163 assert scan_position[1] == slide_position[1] 164 165 166def test_eventarray_conversions(): 167 scan = csi_scans.Scan.load_yaml("tests/data") 168 # Origin 169 tile = csi_tiles.Tile(scan, 0) 170 event0 = csi_events.Event(scan, tile, 0, 0) 171 event1 = csi_events.Event(scan, tile, 1000, 1000) 172 event2 = csi_events.Event(scan, tile, 2000, 2000) 173 174 event_array = csi_events.EventArray.from_events([event0, event1, event2]) 175 176 assert len(event_array) == 3 177 assert event_array.metadata is None 178 assert event_array.features is None 179 180 event0.metadata = pd.Series({"event0": 0}) 181 182 try: 183 event_array = csi_events.EventArray.from_events([event0, event1, event2]) 184 # Should throw error 185 assert False 186 except ValueError: 187 pass 188 189 event1.metadata = pd.Series({"event0": 1}) 190 event2.metadata = pd.Series({"event0": 2}) 191 192 event_array = csi_events.EventArray.from_events([event0, event1, event2]) 193 194 assert len(event_array) == 3 195 196 events_df = event_array.to_dataframe() 197 198 assert len(events_df) == 3 199 200 assert event_array == csi_events.EventArray.from_dataframe(events_df) 201 202 # Test saving and loading 203 assert event_array.save_csv("tests/data/events.csv") 204 assert event_array == csi_events.EventArray.load_csv("tests/data/events.csv") 205 os.remove("tests/data/events.csv") 206 207 assert event_array.save_hdf5("tests/data/events.h5") 208 assert event_array == csi_events.EventArray.load_hdf5("tests/data/events.h5") 209 os.remove("tests/data/events.h5")
def
test_getting_event():
19def test_getting_event(): 20 scan = csi_scans.Scan.load_txt("tests/data") 21 tile = csi_tiles.Tile(scan, 1000) 22 event = csi_events.Event( 23 scan, 24 tile, 25 515, 26 411, 27 ) 28 images = event.extract_images() 29 assert len(images) == 4 30 images = event.extract_images(crop_size=100, in_pixels=True) 31 assert images[0].shape == (100, 100) 32 images = event.extract_images(crop_size=50, in_pixels=True) 33 assert images[0].shape == (50, 50) 34 35 if SHOW_PLOTS: 36 for image in images: 37 cv2.imshow("Bright DAPI event in the center", image) 38 cv2.waitKey(0) 39 cv2.destroyAllWindows() 40 41 # Test a corner event 42 event = csi_events.Event( 43 scan, 44 tile, 45 2, 46 1000, 47 ) 48 images = event.extract_images() 49 assert len(images) == 4 50 images = event.extract_images(crop_size=100, in_pixels=True) 51 assert images[0].shape == (100, 100) 52 images = event.extract_images(crop_size=200, in_pixels=True) 53 assert images[0].shape == (200, 200) 54 55 if SHOW_PLOTS: 56 for image in images: 57 cv2.imshow("Events in the corner of a tile", image) 58 cv2.waitKey(0) 59 cv2.destroyAllWindows()
def
test_getting_many_events():
62def test_getting_many_events(): 63 scan = csi_scans.Scan.load_txt("tests/data") 64 tile = csi_tiles.Tile(scan, 1000) 65 tile2 = csi_tiles.Tile(scan, 0) 66 events = [ 67 csi_events.Event(scan, tile, 515, 411), 68 csi_events.Event(scan, tile2, 2, 1000), 69 csi_events.Event(scan, tile, 1000, 1000), 70 csi_events.Event(scan, tile, 87, 126), 71 csi_events.Event(scan, tile, 1000, 2), 72 csi_events.Event(scan, tile2, 800, 800), 73 csi_events.Event(scan, tile, 1000, 662), 74 ] 75 # Test time to extract images sequentially 76 start_time = time.time() 77 images_1 = [] 78 for event in events: 79 images_1.append(event.extract_images()) 80 sequential_time = time.time() - start_time 81 82 # Test time to extract images in parallel 83 start_time = time.time() 84 images_2 = csi_events.Event.extract_images_for_list(events, crop_size=50) 85 parallel_time = time.time() - start_time 86 assert parallel_time < sequential_time 87 for list_a, list_b in zip(images_1, images_2): 88 assert len(list_a) == len(list_b) 89 for image_a, image_b in zip(list_a, list_b): 90 assert np.array_equal(image_a, image_b) 91 92 # Test that it works after converting to EventArray and back 93 event_array = csi_events.EventArray.from_events(events) 94 remade_events = event_array.to_events( 95 [scan], ignore_metadata=True, ignore_features=True 96 ) 97 images_3 = csi_events.Event.extract_images_for_list( 98 remade_events, 99 crop_size=50, 100 )
def
test_event_coordinates_for_bzscanner():
103def test_event_coordinates_for_bzscanner(): 104 scan = csi_scans.Scan.load_txt("tests/data") 105 # Origin 106 tile = csi_tiles.Tile(scan, 0) 107 event = csi_events.Event(scan, tile, 0, 0) 108 scan_origin = event.get_scan_position() 109 assert 2500 <= scan_origin[0] <= 3500 110 assert 2500 <= scan_origin[1] <= 3500 111 scan_origin_on_slide = event.get_slide_position() 112 assert 71500 <= scan_origin_on_slide[0] <= 72500 113 assert 21500 <= scan_origin_on_slide[1] <= 22500 114 # Within the same tile, "bottom-right corner" 115 event = csi_events.Event(scan, tile, 1000, 1000) 116 scan_position = event.get_scan_position() 117 assert scan_origin[0] <= scan_position[0] 118 assert scan_origin[1] <= scan_position[1] 119 slide_position = event.get_slide_position() 120 assert slide_position[0] <= scan_origin_on_slide[0] 121 assert slide_position[1] <= scan_origin_on_slide[1] 122 123 # Next row, opposite side 124 tile = csi_tiles.Tile(scan, (scan.roi[0].tile_cols - 1, 1)) 125 event = csi_events.Event(scan, tile, 1000, 1000) 126 scan_position = event.get_scan_position() 127 assert scan_origin[0] <= scan_position[0] 128 assert scan_origin[1] <= scan_position[1] 129 slide_position = event.get_slide_position() 130 assert slide_position[0] <= scan_origin_on_slide[0] 131 assert slide_position[1] <= scan_origin_on_slide[1] 132 133 # Opposite corner 134 tile = csi_tiles.Tile(scan, (scan.roi[0].tile_cols - 1, scan.roi[0].tile_rows - 1)) 135 event = csi_events.Event(scan, tile, 1361, 1003) 136 scan_position = event.get_scan_position() 137 assert 21500 <= scan_position[0] <= 22500 138 assert 58500 <= scan_position[1] <= 60500 139 slide_position = event.get_slide_position() 140 assert 14500 <= slide_position[0] <= 15500 141 assert 2500 <= slide_position[1] <= 3500
def
test_event_coordinates_for_axioscan():
144def test_event_coordinates_for_axioscan(): 145 scan = csi_scans.Scan.load_yaml("tests/data") 146 # Origin 147 tile = csi_tiles.Tile(scan, 0) 148 event = csi_events.Event(scan, tile, 0, 0) 149 scan_position = event.get_scan_position() 150 assert -59000 <= scan_position[0] < -55000 151 assert 0 <= scan_position[1] < 4000 152 slide_position = event.get_slide_position() 153 assert 16000 <= slide_position[0] < 20000 154 assert scan_position[1] == slide_position[1] 155 156 # Opposite corner 157 tile = csi_tiles.Tile(scan, (scan.roi[0].tile_cols - 1, scan.roi[0].tile_rows - 1)) 158 event = csi_events.Event(scan, tile, 2000, 2000) 159 scan_position = event.get_scan_position() 160 assert -4000 <= scan_position[0] <= 0 161 assert 21000 <= scan_position[1] <= 25000 162 slide_position = event.get_slide_position() 163 assert 71000 <= slide_position[0] <= 75000 164 assert scan_position[1] == slide_position[1]
def
test_eventarray_conversions():
167def test_eventarray_conversions(): 168 scan = csi_scans.Scan.load_yaml("tests/data") 169 # Origin 170 tile = csi_tiles.Tile(scan, 0) 171 event0 = csi_events.Event(scan, tile, 0, 0) 172 event1 = csi_events.Event(scan, tile, 1000, 1000) 173 event2 = csi_events.Event(scan, tile, 2000, 2000) 174 175 event_array = csi_events.EventArray.from_events([event0, event1, event2]) 176 177 assert len(event_array) == 3 178 assert event_array.metadata is None 179 assert event_array.features is None 180 181 event0.metadata = pd.Series({"event0": 0}) 182 183 try: 184 event_array = csi_events.EventArray.from_events([event0, event1, event2]) 185 # Should throw error 186 assert False 187 except ValueError: 188 pass 189 190 event1.metadata = pd.Series({"event0": 1}) 191 event2.metadata = pd.Series({"event0": 2}) 192 193 event_array = csi_events.EventArray.from_events([event0, event1, event2]) 194 195 assert len(event_array) == 3 196 197 events_df = event_array.to_dataframe() 198 199 assert len(events_df) == 3 200 201 assert event_array == csi_events.EventArray.from_dataframe(events_df) 202 203 # Test saving and loading 204 assert event_array.save_csv("tests/data/events.csv") 205 assert event_array == csi_events.EventArray.load_csv("tests/data/events.csv") 206 os.remove("tests/data/events.csv") 207 208 assert event_array.save_hdf5("tests/data/events.h5") 209 assert event_array == csi_events.EventArray.load_hdf5("tests/data/events.h5") 210 os.remove("tests/data/events.h5")