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=100) 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(remade_events, crop_size=100) 97 for list_a, list_b in zip(images_1, images_3): 98 assert len(list_a) == len(list_b) 99 for image_a, image_b in zip(list_a, list_b): 100 assert np.array_equal(image_a, image_b) 101 102 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 142 143 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] 165 166 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") 211 212 213def test_ocular_conversions(): 214 scan = csi_scans.Scan.load_txt("tests/data") 215 input_path = "/mnt/HDSCA_Development/DZ/0B58703/ocular" 216 result = csi_events.EventArray.load_ocular(input_path) 217 # For the purposes of this test, we will manually relabel "clust" == nan to 0 218 # These come from ocular_interesting.rds, which does not have clusters 219 result.metadata["clust"] = result.metadata["clust"].fillna(0) 220 result.metadata["hcpc"] = result.metadata["hcpc"].fillna(0) 221 result.save_ocular("tests/data") 222 new_result = csi_events.EventArray.load_ocular("tests/data") 223 # Sort them so that they are in the same order 224 result.sort(["tile", "x", "y"]) 225 new_result.sort(["tile", "x", "y"]) 226 # Note: hcpc method within ocularr and here are different 227 result.metadata["hcpc"] = new_result.metadata["hcpc"].copy(deep=True) 228 assert result == new_result 229 # Clean up 230 os.remove("tests/data/rc-final.csv") 231 os.remove("tests/data/rc-final.rds") 232 os.remove("tests/data/rc-final1.rds") 233 os.remove("tests/data/rc-final2.rds") 234 os.remove("tests/data/rc-final3.rds") 235 os.remove("tests/data/rc-final4.rds") 236 237 # Try it with "others" files 238 result = csi_events.EventArray.load_ocular(input_path, event_type="others") 239 result.save_ocular("tests/data", event_type="others") 240 new_result = csi_events.EventArray.load_ocular("tests/data", event_type="others") 241 result.sort(["tile", "x", "y"]) 242 new_result.sort(["tile", "x", "y"]) 243 # Note: hcpc method within ocularr and here are different 244 result.metadata["hcpc"] = new_result.metadata["hcpc"].copy(deep=True) 245 assert result == new_result 246 # Clean up 247 os.remove("tests/data/others-final.csv") 248 os.remove("tests/data/others-final.rds") 249 os.remove("tests/data/others-final1.rds") 250 os.remove("tests/data/others-final2.rds") 251 os.remove("tests/data/others-final3.rds") 252 os.remove("tests/data/others-final4.rds")
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=100) 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(remade_events, crop_size=100) 98 for list_a, list_b in zip(images_1, images_3): 99 assert len(list_a) == len(list_b) 100 for image_a, image_b in zip(list_a, list_b): 101 assert np.array_equal(image_a, image_b)
def
test_event_coordinates_for_bzscanner():
104def test_event_coordinates_for_bzscanner(): 105 scan = csi_scans.Scan.load_txt("tests/data") 106 # Origin 107 tile = csi_tiles.Tile(scan, 0) 108 event = csi_events.Event(scan, tile, 0, 0) 109 scan_origin = event.get_scan_position() 110 assert 2500 <= scan_origin[0] <= 3500 111 assert 2500 <= scan_origin[1] <= 3500 112 scan_origin_on_slide = event.get_slide_position() 113 assert 71500 <= scan_origin_on_slide[0] <= 72500 114 assert 21500 <= scan_origin_on_slide[1] <= 22500 115 # Within the same tile, "bottom-right corner" 116 event = csi_events.Event(scan, tile, 1000, 1000) 117 scan_position = event.get_scan_position() 118 assert scan_origin[0] <= scan_position[0] 119 assert scan_origin[1] <= scan_position[1] 120 slide_position = event.get_slide_position() 121 assert slide_position[0] <= scan_origin_on_slide[0] 122 assert slide_position[1] <= scan_origin_on_slide[1] 123 124 # Next row, opposite side 125 tile = csi_tiles.Tile(scan, (scan.roi[0].tile_cols - 1, 1)) 126 event = csi_events.Event(scan, tile, 1000, 1000) 127 scan_position = event.get_scan_position() 128 assert scan_origin[0] <= scan_position[0] 129 assert scan_origin[1] <= scan_position[1] 130 slide_position = event.get_slide_position() 131 assert slide_position[0] <= scan_origin_on_slide[0] 132 assert slide_position[1] <= scan_origin_on_slide[1] 133 134 # Opposite corner 135 tile = csi_tiles.Tile(scan, (scan.roi[0].tile_cols - 1, scan.roi[0].tile_rows - 1)) 136 event = csi_events.Event(scan, tile, 1361, 1003) 137 scan_position = event.get_scan_position() 138 assert 21500 <= scan_position[0] <= 22500 139 assert 58500 <= scan_position[1] <= 60500 140 slide_position = event.get_slide_position() 141 assert 14500 <= slide_position[0] <= 15500 142 assert 2500 <= slide_position[1] <= 3500
def
test_event_coordinates_for_axioscan():
145def test_event_coordinates_for_axioscan(): 146 scan = csi_scans.Scan.load_yaml("tests/data") 147 # Origin 148 tile = csi_tiles.Tile(scan, 0) 149 event = csi_events.Event(scan, tile, 0, 0) 150 scan_position = event.get_scan_position() 151 assert -59000 <= scan_position[0] < -55000 152 assert 0 <= scan_position[1] < 4000 153 slide_position = event.get_slide_position() 154 assert 16000 <= slide_position[0] < 20000 155 assert scan_position[1] == slide_position[1] 156 157 # Opposite corner 158 tile = csi_tiles.Tile(scan, (scan.roi[0].tile_cols - 1, scan.roi[0].tile_rows - 1)) 159 event = csi_events.Event(scan, tile, 2000, 2000) 160 scan_position = event.get_scan_position() 161 assert -4000 <= scan_position[0] <= 0 162 assert 21000 <= scan_position[1] <= 25000 163 slide_position = event.get_slide_position() 164 assert 71000 <= slide_position[0] <= 75000 165 assert scan_position[1] == slide_position[1]
def
test_eventarray_conversions():
168def test_eventarray_conversions(): 169 scan = csi_scans.Scan.load_yaml("tests/data") 170 # Origin 171 tile = csi_tiles.Tile(scan, 0) 172 event0 = csi_events.Event(scan, tile, 0, 0) 173 event1 = csi_events.Event(scan, tile, 1000, 1000) 174 event2 = csi_events.Event(scan, tile, 2000, 2000) 175 176 event_array = csi_events.EventArray.from_events([event0, event1, event2]) 177 178 assert len(event_array) == 3 179 assert event_array.metadata is None 180 assert event_array.features is None 181 182 event0.metadata = pd.Series({"event0": 0}) 183 184 try: 185 event_array = csi_events.EventArray.from_events([event0, event1, event2]) 186 # Should throw error 187 assert False 188 except ValueError: 189 pass 190 191 event1.metadata = pd.Series({"event0": 1}) 192 event2.metadata = pd.Series({"event0": 2}) 193 194 event_array = csi_events.EventArray.from_events([event0, event1, event2]) 195 196 assert len(event_array) == 3 197 198 events_df = event_array.to_dataframe() 199 200 assert len(events_df) == 3 201 202 assert event_array == csi_events.EventArray.from_dataframe(events_df) 203 204 # Test saving and loading 205 assert event_array.save_csv("tests/data/events.csv") 206 assert event_array == csi_events.EventArray.load_csv("tests/data/events.csv") 207 os.remove("tests/data/events.csv") 208 209 assert event_array.save_hdf5("tests/data/events.h5") 210 assert event_array == csi_events.EventArray.load_hdf5("tests/data/events.h5") 211 os.remove("tests/data/events.h5")
def
test_ocular_conversions():
214def test_ocular_conversions(): 215 scan = csi_scans.Scan.load_txt("tests/data") 216 input_path = "/mnt/HDSCA_Development/DZ/0B58703/ocular" 217 result = csi_events.EventArray.load_ocular(input_path) 218 # For the purposes of this test, we will manually relabel "clust" == nan to 0 219 # These come from ocular_interesting.rds, which does not have clusters 220 result.metadata["clust"] = result.metadata["clust"].fillna(0) 221 result.metadata["hcpc"] = result.metadata["hcpc"].fillna(0) 222 result.save_ocular("tests/data") 223 new_result = csi_events.EventArray.load_ocular("tests/data") 224 # Sort them so that they are in the same order 225 result.sort(["tile", "x", "y"]) 226 new_result.sort(["tile", "x", "y"]) 227 # Note: hcpc method within ocularr and here are different 228 result.metadata["hcpc"] = new_result.metadata["hcpc"].copy(deep=True) 229 assert result == new_result 230 # Clean up 231 os.remove("tests/data/rc-final.csv") 232 os.remove("tests/data/rc-final.rds") 233 os.remove("tests/data/rc-final1.rds") 234 os.remove("tests/data/rc-final2.rds") 235 os.remove("tests/data/rc-final3.rds") 236 os.remove("tests/data/rc-final4.rds") 237 238 # Try it with "others" files 239 result = csi_events.EventArray.load_ocular(input_path, event_type="others") 240 result.save_ocular("tests/data", event_type="others") 241 new_result = csi_events.EventArray.load_ocular("tests/data", event_type="others") 242 result.sort(["tile", "x", "y"]) 243 new_result.sort(["tile", "x", "y"]) 244 # Note: hcpc method within ocularr and here are different 245 result.metadata["hcpc"] = new_result.metadata["hcpc"].copy(deep=True) 246 assert result == new_result 247 # Clean up 248 os.remove("tests/data/others-final.csv") 249 os.remove("tests/data/others-final.rds") 250 os.remove("tests/data/others-final1.rds") 251 os.remove("tests/data/others-final2.rds") 252 os.remove("tests/data/others-final3.rds") 253 os.remove("tests/data/others-final4.rds")