tests.test_events
1import os 2import time 3 4import pytest 5 6import cv2 7import numpy as np 8import pandas as pd 9 10from csi_images.csi_scans import Scan 11from csi_images.csi_tiles import Tile 12from csi_images.csi_events import Event, EventArray 13from csi_images import csi_images 14 15if os.environ.get("DEBIAN_FRONTEND") == "noninteractive": 16 SHOW_PLOTS = False 17else: 18 # Change this to your preference for local testing, but commit as True 19 SHOW_PLOTS = True 20 21 22@pytest.fixture 23def bzscan(): 24 return Scan.load_txt("tests/data") 25 26 27@pytest.fixture 28def axscan(): 29 return Scan.load_yaml("tests/data") 30 31 32def test_get_crops(bzscan): 33 tile = Tile(bzscan, 1000) 34 event = Event(tile, 400, 350) 35 36 # Test a regular event 37 images = event.get_crops() 38 assert len(images) == 5 39 images = event.get_crops(crop_size=50) 40 assert images[0].shape == (50, 50) 41 images = event.get_crops(crop_size=100) 42 assert images[0].shape == (100, 100) 43 44 if SHOW_PLOTS: 45 for image in images: 46 cv2.imshow("Bright DAPI event in the center", image) 47 cv2.waitKey(0) 48 cv2.destroyAllWindows() 49 50 # Test a corner event 51 event = Event(tile, 1350, 2) 52 images = event.get_crops() 53 assert len(images) == 5 54 images = event.get_crops(crop_size=200) 55 assert images[0].shape == (200, 200) 56 images = event.get_crops(crop_size=100) 57 assert images[0].shape == (100, 100) 58 59 if SHOW_PLOTS: 60 for image in images: 61 cv2.imshow("Events in the top-right corner of a tile", image) 62 cv2.waitKey(0) 63 cv2.destroyAllWindows() 64 65 # Test many events 66 tile2 = Tile(bzscan, 500) 67 events = [ 68 Event(tile, 515, 411), 69 Event(tile2, 2, 1000), 70 Event(tile, 1000, 1000), 71 Event(tile, 87, 126), 72 Event(tile, 1000, 2), 73 Event(tile2, 800, 800), 74 Event(tile, 1000, 662), 75 ] 76 77 # Test time to extract images sequentially 78 start_time = time.time() 79 images_1 = [] 80 for event in events: 81 images_1.append(event.get_crops()) 82 sequential_time = time.time() - start_time 83 84 # Test time to extract images in parallel 85 start_time = time.time() 86 images_2 = Event.get_many_crops(events, crop_size=100) 87 parallel_time = time.time() - start_time 88 assert parallel_time < sequential_time 89 for list_a, list_b in zip(images_1, images_2): 90 assert len(list_a) == len(list_b) 91 for image_a, image_b in zip(list_a, list_b): 92 assert np.array_equal(image_a, image_b) 93 94 # Test that it works after converting to EventArray and back 95 event_array = EventArray.from_events(events) 96 remade_events = event_array.to_events( 97 [bzscan], ignore_metadata=True, ignore_features=True 98 ) 99 images_3 = Event.get_many_crops(remade_events, crop_size=100) 100 for list_a, list_b in zip(images_1, images_3): 101 assert len(list_a) == len(list_b) 102 for image_a, image_b in zip(list_a, list_b): 103 assert np.array_equal(image_a, image_b) 104 105 106def test_event_coordinates_for_bzscanner(bzscan): 107 # Origin 108 tile = Tile(bzscan, 0) 109 event = Event(tile, 0, 0) 110 scan_origin = event.get_scan_position() 111 assert 2500 <= scan_origin[0] <= 3500 112 assert 2500 <= scan_origin[1] <= 3500 113 scan_origin_on_slide = event.get_slide_position() 114 assert 71500 <= scan_origin_on_slide[0] <= 72500 115 assert 21500 <= scan_origin_on_slide[1] <= 22500 116 # Within the same tile, "top-right corner" 117 event = Event(tile, 1000, 0) 118 scan_position = event.get_scan_position() 119 assert scan_origin[0] < scan_position[0] 120 assert scan_origin[1] == scan_position[1] 121 slide_position = event.get_slide_position() 122 assert scan_origin_on_slide[0] == slide_position[0] 123 assert scan_origin_on_slide[1] > slide_position[1] 124 # Within the same tile, "bottom-left corner" 125 event = Event(tile, 0, 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 scan_origin_on_slide[0] > slide_position[0] 131 assert scan_origin_on_slide[1] == slide_position[1] 132 133 # Next row, opposite side 134 tile = Tile(bzscan, (bzscan.roi[0].tile_cols - 1, 1)) 135 event = Event(tile, 1000, 1000) 136 scan_position = event.get_scan_position() 137 assert scan_origin[0] <= scan_position[0] 138 assert scan_origin[1] <= scan_position[1] 139 slide_position = event.get_slide_position() 140 assert slide_position[0] <= scan_origin_on_slide[0] 141 assert slide_position[1] <= scan_origin_on_slide[1] 142 143 # Opposite corner 144 tile = Tile(bzscan, (bzscan.roi[0].tile_cols - 1, bzscan.roi[0].tile_rows - 1)) 145 event = Event(tile, 1361, 1003) 146 scan_position = event.get_scan_position() 147 assert 21500 <= scan_position[0] <= 22500 148 assert 58500 <= scan_position[1] <= 60500 149 slide_position = event.get_slide_position() 150 assert 14500 <= slide_position[0] <= 15500 151 assert 2500 <= slide_position[1] <= 3500 152 153 154def test_event_coordinates_for_axioscan(axscan): 155 # Origin 156 tile = Tile(axscan, 0) 157 event = Event(tile, 0, 0) 158 scan_position = event.get_scan_position() 159 assert -59000 <= scan_position[0] < -55000 160 assert 0 <= scan_position[1] < 4000 161 slide_position = event.get_slide_position() 162 assert 16000 <= slide_position[0] < 20000 163 assert scan_position[1] == slide_position[1] 164 165 # Opposite corner 166 tile = Tile(axscan, (axscan.roi[0].tile_cols - 1, axscan.roi[0].tile_rows - 1)) 167 event = Event(tile, 2000, 2000) 168 scan_position = event.get_scan_position() 169 assert -4000 <= scan_position[0] <= 0 170 assert 21000 <= scan_position[1] <= 25000 171 slide_position = event.get_slide_position() 172 assert 71000 <= slide_position[0] <= 75000 173 assert scan_position[1] == slide_position[1] 174 175 176def test_eventarray_conversions(axscan): 177 # Origin 178 tile = Tile(axscan, 0) 179 event0 = Event(tile, 0, 0) 180 event1 = Event(tile, 1000, 1000) 181 event2 = Event(tile, 2000, 2000) 182 183 event_array = EventArray.from_events([event0, event1, event2]) 184 185 assert len(event_array) == 3 186 assert event_array.metadata is None 187 assert event_array.features is None 188 189 event0.metadata = pd.Series({"event0": 0}) 190 191 try: 192 event_array = EventArray.from_events([event0, event1, event2]) 193 # Should throw error 194 assert False 195 except ValueError: 196 pass 197 198 event1.metadata = pd.Series({"event0": 1}) 199 event2.metadata = pd.Series({"event0": 2}) 200 201 event_array = EventArray.from_events([event0, event1, event2]) 202 203 assert len(event_array) == 3 204 205 events_df = event_array.to_dataframe() 206 207 assert len(events_df) == 3 208 209 assert event_array == EventArray.from_dataframe(events_df) 210 211 # Test adding different dtypes and converting back and forth 212 event_array.features = pd.DataFrame( 213 {"feature1": [1, 2, 3], "feature2": [4.0, 5.0, 6.0]} 214 ) 215 remade_event_list = event_array.to_events([axscan]) 216 assert len(remade_event_list) == 3 217 remade_event_array = EventArray.from_events(remade_event_list) 218 assert event_array == remade_event_array 219 # Test saving and loading 220 assert event_array.save_csv("tests/data/events.csv") 221 assert event_array == EventArray.load_csv("tests/data/events.csv") 222 os.remove("tests/data/events.csv") 223 224 assert event_array.save_hdf5("tests/data/events.h5") 225 assert event_array == EventArray.load_hdf5("tests/data/events.h5") 226 os.remove("tests/data/events.h5") 227 228 229# @pytest.mark.skip(reason="No longer required.") 230def test_ocular_conversions(): 231 input_path = "/mnt/HDSCA_Development/DZ/0B68818/ocular" 232 result = EventArray.load_ocular(input_path) 233 # For the purposes of this test, we will manually relabel "clust" == nan to 0 234 # These come from ocular_interesting.rds, which does not have clusters 235 result.metadata["clust"] = result.metadata["clust"].fillna(0) 236 result.metadata["hcpc"] = result.metadata["hcpc"].fillna(0) 237 result.save_ocular("tests/data") 238 new_result = EventArray.load_ocular("tests/data") 239 # # Sort them so that they are in the same order 240 result = result.sort(["tile", "x", "y"]) 241 new_result = new_result.sort(["tile", "x", "y"]) 242 # Note: hcpc method within ocularr and here are different 243 result.metadata["hcpc"] = new_result.metadata["hcpc"].copy() 244 assert result == new_result 245 # Clean up 246 os.remove("tests/data/rc-final.csv") 247 os.remove("tests/data/rc-final.rds") 248 os.remove("tests/data/rc-final1.rds") 249 os.remove("tests/data/rc-final2.rds") 250 os.remove("tests/data/rc-final3.rds") 251 os.remove("tests/data/rc-final4.rds") 252 253 # Try it with "others" files 254 result = EventArray.load_ocular(input_path, event_type="others") 255 result.save_ocular("tests/data", event_type="others") 256 new_result = EventArray.load_ocular("tests/data", event_type="others") 257 result = result.sort(["tile", "x", "y"]) 258 new_result = new_result.sort(["tile", "x", "y"]) 259 # Note: hcpc method within ocularr and here are different 260 result.metadata["hcpc"] = new_result.metadata["hcpc"].copy() 261 assert result == new_result 262 # Clean up 263 os.remove("tests/data/others-final.csv") 264 os.remove("tests/data/others-final.rds") 265 os.remove("tests/data/others-final1.rds") 266 os.remove("tests/data/others-final2.rds") 267 os.remove("tests/data/others-final3.rds") 268 os.remove("tests/data/others-final4.rds") 269 270 271def test_copy_sort_rows_get(axscan): 272 # Origin 273 tile = Tile(axscan, 0) 274 events = [ 275 Event(tile, 0, 100), 276 Event(tile, 0, 0), 277 Event(tile, 1000, 1000), 278 Event(tile, 1000, 1), 279 Event(tile, 2000, 2000), 280 ] 281 282 events = EventArray.from_events(events) 283 284 # Copy 285 events_copy = events.copy() 286 events_copy.info["x"] = np.uint16(1) 287 # Check that changes to the copy did not change the original 288 assert events_copy.info["x"].equals(pd.Series([1, 1, 1, 1, 1], dtype=np.uint16)) 289 assert events.info["x"].equals(pd.Series([0, 0, 1000, 1000, 2000], dtype=np.uint16)) 290 291 # Sort 292 events = events.sort(["x", "y"], ascending=[False, True]) 293 assert events.info["x"].equals(pd.Series([2000, 1000, 1000, 0, 0], dtype=np.uint16)) 294 assert events.info["y"].equals(pd.Series([2000, 1, 1000, 0, 100], dtype=np.uint16)) 295 296 # Get 297 events_get = events.get(["x", "y"]) 298 assert events_get["x"].equals(pd.Series([2000, 1000, 1000, 0, 0], dtype=np.uint16)) 299 assert events_get["y"].equals(pd.Series([2000, 1, 1000, 0, 100], dtype=np.uint16)) 300 assert events_get.columns.equals(pd.Index(["x", "y"])) 301 302 # Rows 303 events_get = events.rows([0, 1, 3]) 304 assert len(events_get) == 3 305 assert events_get.info["x"].equals(pd.Series([2000, 1000, 0], dtype=np.uint16)) 306 assert events_get.info["y"].equals(pd.Series([2000, 1, 0], dtype=np.uint16)) 307 events_get = events.rows([True, False, False, True, True]) 308 assert len(events_get) == 3 309 assert events_get.info["x"].equals(pd.Series([2000, 0, 0], dtype=np.uint16)) 310 assert events_get.info["y"].equals(pd.Series([2000, 0, 100], dtype=np.uint16)) 311 312 313def test_event_montages(bzscan): 314 tile = Tile(bzscan, 1000) 315 event = Event(tile, 515, 411) 316 images = event.get_crops(crop_size=100) 317 318 montage = csi_images.make_montage( 319 images, 320 [0, 1, 4, 2], 321 {0: (0, 0, 1), 1: (1, 0, 0), 2: (0, 1, 0), 4: (1, 1, 1)}, 322 labels=["RGB", "DAPI", "AF555", "AF488", "AF647"], 323 ) 324 if SHOW_PLOTS: 325 cv2.imshow( 326 "Full, classic montage with labels", 327 cv2.cvtColor(montage, cv2.COLOR_RGB2BGR), 328 ) 329 cv2.waitKey(0) 330 cv2.destroyAllWindows() 331 332 333def test_saving_crops_and_montages(bzscan): 334 tile = Tile(bzscan, 1000) 335 tile2 = Tile(bzscan, 0) 336 events = [ 337 Event(tile, 515, 411), 338 Event(tile2, 2, 1000), 339 Event(tile, 1000, 1000), 340 Event(tile2, 800, 800), 341 Event(tile, 1000, 662), 342 ] 343 344 # Get all crops and montages 345 serial_crops = [] 346 serial_montages = [] 347 for event in events: 348 serial_crops.append(event.get_crops()) 349 serial_montages.append(event.get_montage()) 350 351 # Save crops and montages 352 Event.get_and_save_many_crops(events, "temp", bzscan.get_channel_names()) 353 Event.get_and_save_many_montages(events, "temp") 354 355 saved_crops = [] 356 saved_montages = [] 357 for event in events: 358 crops = event.load_crops("temp") 359 saved_crops.append([crops[c] for c in bzscan.get_channel_names()]) 360 saved_montages.append(event.load_montage("temp")) 361 362 # Make sure crops are identical 363 for a, b in zip(serial_crops, saved_crops): 364 for a_img, b_img in zip(a, b): 365 assert np.array_equal(a_img, b_img) 366 367 # Montages got JPEG compressed, so 368 # Size comparison: 369 for a, b in zip(serial_montages, saved_montages): 370 assert a.shape == b.shape 371 372 # Visual inspection 373 if SHOW_PLOTS: 374 cv2.imshow("Original", cv2.cvtColor(serial_montages[0], cv2.COLOR_RGB2BGR)) 375 cv2.imshow("Saved", cv2.cvtColor(saved_montages[0], cv2.COLOR_RGB2BGR)) 376 cv2.waitKey(0) 377 cv2.destroyAllWindows() 378 379 # Clean up 380 for file in os.listdir("temp"): 381 os.remove(os.path.join("temp", file)) 382 os.rmdir("temp")
@pytest.fixture
def
bzscan():
@pytest.fixture
def
axscan():
def
test_get_crops(bzscan):
33def test_get_crops(bzscan): 34 tile = Tile(bzscan, 1000) 35 event = Event(tile, 400, 350) 36 37 # Test a regular event 38 images = event.get_crops() 39 assert len(images) == 5 40 images = event.get_crops(crop_size=50) 41 assert images[0].shape == (50, 50) 42 images = event.get_crops(crop_size=100) 43 assert images[0].shape == (100, 100) 44 45 if SHOW_PLOTS: 46 for image in images: 47 cv2.imshow("Bright DAPI event in the center", image) 48 cv2.waitKey(0) 49 cv2.destroyAllWindows() 50 51 # Test a corner event 52 event = Event(tile, 1350, 2) 53 images = event.get_crops() 54 assert len(images) == 5 55 images = event.get_crops(crop_size=200) 56 assert images[0].shape == (200, 200) 57 images = event.get_crops(crop_size=100) 58 assert images[0].shape == (100, 100) 59 60 if SHOW_PLOTS: 61 for image in images: 62 cv2.imshow("Events in the top-right corner of a tile", image) 63 cv2.waitKey(0) 64 cv2.destroyAllWindows() 65 66 # Test many events 67 tile2 = Tile(bzscan, 500) 68 events = [ 69 Event(tile, 515, 411), 70 Event(tile2, 2, 1000), 71 Event(tile, 1000, 1000), 72 Event(tile, 87, 126), 73 Event(tile, 1000, 2), 74 Event(tile2, 800, 800), 75 Event(tile, 1000, 662), 76 ] 77 78 # Test time to extract images sequentially 79 start_time = time.time() 80 images_1 = [] 81 for event in events: 82 images_1.append(event.get_crops()) 83 sequential_time = time.time() - start_time 84 85 # Test time to extract images in parallel 86 start_time = time.time() 87 images_2 = Event.get_many_crops(events, crop_size=100) 88 parallel_time = time.time() - start_time 89 assert parallel_time < sequential_time 90 for list_a, list_b in zip(images_1, images_2): 91 assert len(list_a) == len(list_b) 92 for image_a, image_b in zip(list_a, list_b): 93 assert np.array_equal(image_a, image_b) 94 95 # Test that it works after converting to EventArray and back 96 event_array = EventArray.from_events(events) 97 remade_events = event_array.to_events( 98 [bzscan], ignore_metadata=True, ignore_features=True 99 ) 100 images_3 = Event.get_many_crops(remade_events, crop_size=100) 101 for list_a, list_b in zip(images_1, images_3): 102 assert len(list_a) == len(list_b) 103 for image_a, image_b in zip(list_a, list_b): 104 assert np.array_equal(image_a, image_b)
def
test_event_coordinates_for_bzscanner(bzscan):
107def test_event_coordinates_for_bzscanner(bzscan): 108 # Origin 109 tile = Tile(bzscan, 0) 110 event = Event(tile, 0, 0) 111 scan_origin = event.get_scan_position() 112 assert 2500 <= scan_origin[0] <= 3500 113 assert 2500 <= scan_origin[1] <= 3500 114 scan_origin_on_slide = event.get_slide_position() 115 assert 71500 <= scan_origin_on_slide[0] <= 72500 116 assert 21500 <= scan_origin_on_slide[1] <= 22500 117 # Within the same tile, "top-right corner" 118 event = Event(tile, 1000, 0) 119 scan_position = event.get_scan_position() 120 assert scan_origin[0] < scan_position[0] 121 assert scan_origin[1] == scan_position[1] 122 slide_position = event.get_slide_position() 123 assert scan_origin_on_slide[0] == slide_position[0] 124 assert scan_origin_on_slide[1] > slide_position[1] 125 # Within the same tile, "bottom-left corner" 126 event = Event(tile, 0, 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 scan_origin_on_slide[0] > slide_position[0] 132 assert scan_origin_on_slide[1] == slide_position[1] 133 134 # Next row, opposite side 135 tile = Tile(bzscan, (bzscan.roi[0].tile_cols - 1, 1)) 136 event = Event(tile, 1000, 1000) 137 scan_position = event.get_scan_position() 138 assert scan_origin[0] <= scan_position[0] 139 assert scan_origin[1] <= scan_position[1] 140 slide_position = event.get_slide_position() 141 assert slide_position[0] <= scan_origin_on_slide[0] 142 assert slide_position[1] <= scan_origin_on_slide[1] 143 144 # Opposite corner 145 tile = Tile(bzscan, (bzscan.roi[0].tile_cols - 1, bzscan.roi[0].tile_rows - 1)) 146 event = Event(tile, 1361, 1003) 147 scan_position = event.get_scan_position() 148 assert 21500 <= scan_position[0] <= 22500 149 assert 58500 <= scan_position[1] <= 60500 150 slide_position = event.get_slide_position() 151 assert 14500 <= slide_position[0] <= 15500 152 assert 2500 <= slide_position[1] <= 3500
def
test_event_coordinates_for_axioscan(axscan):
155def test_event_coordinates_for_axioscan(axscan): 156 # Origin 157 tile = Tile(axscan, 0) 158 event = Event(tile, 0, 0) 159 scan_position = event.get_scan_position() 160 assert -59000 <= scan_position[0] < -55000 161 assert 0 <= scan_position[1] < 4000 162 slide_position = event.get_slide_position() 163 assert 16000 <= slide_position[0] < 20000 164 assert scan_position[1] == slide_position[1] 165 166 # Opposite corner 167 tile = Tile(axscan, (axscan.roi[0].tile_cols - 1, axscan.roi[0].tile_rows - 1)) 168 event = Event(tile, 2000, 2000) 169 scan_position = event.get_scan_position() 170 assert -4000 <= scan_position[0] <= 0 171 assert 21000 <= scan_position[1] <= 25000 172 slide_position = event.get_slide_position() 173 assert 71000 <= slide_position[0] <= 75000 174 assert scan_position[1] == slide_position[1]
def
test_eventarray_conversions(axscan):
177def test_eventarray_conversions(axscan): 178 # Origin 179 tile = Tile(axscan, 0) 180 event0 = Event(tile, 0, 0) 181 event1 = Event(tile, 1000, 1000) 182 event2 = Event(tile, 2000, 2000) 183 184 event_array = EventArray.from_events([event0, event1, event2]) 185 186 assert len(event_array) == 3 187 assert event_array.metadata is None 188 assert event_array.features is None 189 190 event0.metadata = pd.Series({"event0": 0}) 191 192 try: 193 event_array = EventArray.from_events([event0, event1, event2]) 194 # Should throw error 195 assert False 196 except ValueError: 197 pass 198 199 event1.metadata = pd.Series({"event0": 1}) 200 event2.metadata = pd.Series({"event0": 2}) 201 202 event_array = EventArray.from_events([event0, event1, event2]) 203 204 assert len(event_array) == 3 205 206 events_df = event_array.to_dataframe() 207 208 assert len(events_df) == 3 209 210 assert event_array == EventArray.from_dataframe(events_df) 211 212 # Test adding different dtypes and converting back and forth 213 event_array.features = pd.DataFrame( 214 {"feature1": [1, 2, 3], "feature2": [4.0, 5.0, 6.0]} 215 ) 216 remade_event_list = event_array.to_events([axscan]) 217 assert len(remade_event_list) == 3 218 remade_event_array = EventArray.from_events(remade_event_list) 219 assert event_array == remade_event_array 220 # Test saving and loading 221 assert event_array.save_csv("tests/data/events.csv") 222 assert event_array == EventArray.load_csv("tests/data/events.csv") 223 os.remove("tests/data/events.csv") 224 225 assert event_array.save_hdf5("tests/data/events.h5") 226 assert event_array == EventArray.load_hdf5("tests/data/events.h5") 227 os.remove("tests/data/events.h5")
def
test_ocular_conversions():
231def test_ocular_conversions(): 232 input_path = "/mnt/HDSCA_Development/DZ/0B68818/ocular" 233 result = EventArray.load_ocular(input_path) 234 # For the purposes of this test, we will manually relabel "clust" == nan to 0 235 # These come from ocular_interesting.rds, which does not have clusters 236 result.metadata["clust"] = result.metadata["clust"].fillna(0) 237 result.metadata["hcpc"] = result.metadata["hcpc"].fillna(0) 238 result.save_ocular("tests/data") 239 new_result = EventArray.load_ocular("tests/data") 240 # # Sort them so that they are in the same order 241 result = result.sort(["tile", "x", "y"]) 242 new_result = 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() 245 assert result == new_result 246 # Clean up 247 os.remove("tests/data/rc-final.csv") 248 os.remove("tests/data/rc-final.rds") 249 os.remove("tests/data/rc-final1.rds") 250 os.remove("tests/data/rc-final2.rds") 251 os.remove("tests/data/rc-final3.rds") 252 os.remove("tests/data/rc-final4.rds") 253 254 # Try it with "others" files 255 result = EventArray.load_ocular(input_path, event_type="others") 256 result.save_ocular("tests/data", event_type="others") 257 new_result = EventArray.load_ocular("tests/data", event_type="others") 258 result = result.sort(["tile", "x", "y"]) 259 new_result = new_result.sort(["tile", "x", "y"]) 260 # Note: hcpc method within ocularr and here are different 261 result.metadata["hcpc"] = new_result.metadata["hcpc"].copy() 262 assert result == new_result 263 # Clean up 264 os.remove("tests/data/others-final.csv") 265 os.remove("tests/data/others-final.rds") 266 os.remove("tests/data/others-final1.rds") 267 os.remove("tests/data/others-final2.rds") 268 os.remove("tests/data/others-final3.rds") 269 os.remove("tests/data/others-final4.rds")
def
test_copy_sort_rows_get(axscan):
272def test_copy_sort_rows_get(axscan): 273 # Origin 274 tile = Tile(axscan, 0) 275 events = [ 276 Event(tile, 0, 100), 277 Event(tile, 0, 0), 278 Event(tile, 1000, 1000), 279 Event(tile, 1000, 1), 280 Event(tile, 2000, 2000), 281 ] 282 283 events = EventArray.from_events(events) 284 285 # Copy 286 events_copy = events.copy() 287 events_copy.info["x"] = np.uint16(1) 288 # Check that changes to the copy did not change the original 289 assert events_copy.info["x"].equals(pd.Series([1, 1, 1, 1, 1], dtype=np.uint16)) 290 assert events.info["x"].equals(pd.Series([0, 0, 1000, 1000, 2000], dtype=np.uint16)) 291 292 # Sort 293 events = events.sort(["x", "y"], ascending=[False, True]) 294 assert events.info["x"].equals(pd.Series([2000, 1000, 1000, 0, 0], dtype=np.uint16)) 295 assert events.info["y"].equals(pd.Series([2000, 1, 1000, 0, 100], dtype=np.uint16)) 296 297 # Get 298 events_get = events.get(["x", "y"]) 299 assert events_get["x"].equals(pd.Series([2000, 1000, 1000, 0, 0], dtype=np.uint16)) 300 assert events_get["y"].equals(pd.Series([2000, 1, 1000, 0, 100], dtype=np.uint16)) 301 assert events_get.columns.equals(pd.Index(["x", "y"])) 302 303 # Rows 304 events_get = events.rows([0, 1, 3]) 305 assert len(events_get) == 3 306 assert events_get.info["x"].equals(pd.Series([2000, 1000, 0], dtype=np.uint16)) 307 assert events_get.info["y"].equals(pd.Series([2000, 1, 0], dtype=np.uint16)) 308 events_get = events.rows([True, False, False, True, True]) 309 assert len(events_get) == 3 310 assert events_get.info["x"].equals(pd.Series([2000, 0, 0], dtype=np.uint16)) 311 assert events_get.info["y"].equals(pd.Series([2000, 0, 100], dtype=np.uint16))
def
test_event_montages(bzscan):
314def test_event_montages(bzscan): 315 tile = Tile(bzscan, 1000) 316 event = Event(tile, 515, 411) 317 images = event.get_crops(crop_size=100) 318 319 montage = csi_images.make_montage( 320 images, 321 [0, 1, 4, 2], 322 {0: (0, 0, 1), 1: (1, 0, 0), 2: (0, 1, 0), 4: (1, 1, 1)}, 323 labels=["RGB", "DAPI", "AF555", "AF488", "AF647"], 324 ) 325 if SHOW_PLOTS: 326 cv2.imshow( 327 "Full, classic montage with labels", 328 cv2.cvtColor(montage, cv2.COLOR_RGB2BGR), 329 ) 330 cv2.waitKey(0) 331 cv2.destroyAllWindows()
def
test_saving_crops_and_montages(bzscan):
334def test_saving_crops_and_montages(bzscan): 335 tile = Tile(bzscan, 1000) 336 tile2 = Tile(bzscan, 0) 337 events = [ 338 Event(tile, 515, 411), 339 Event(tile2, 2, 1000), 340 Event(tile, 1000, 1000), 341 Event(tile2, 800, 800), 342 Event(tile, 1000, 662), 343 ] 344 345 # Get all crops and montages 346 serial_crops = [] 347 serial_montages = [] 348 for event in events: 349 serial_crops.append(event.get_crops()) 350 serial_montages.append(event.get_montage()) 351 352 # Save crops and montages 353 Event.get_and_save_many_crops(events, "temp", bzscan.get_channel_names()) 354 Event.get_and_save_many_montages(events, "temp") 355 356 saved_crops = [] 357 saved_montages = [] 358 for event in events: 359 crops = event.load_crops("temp") 360 saved_crops.append([crops[c] for c in bzscan.get_channel_names()]) 361 saved_montages.append(event.load_montage("temp")) 362 363 # Make sure crops are identical 364 for a, b in zip(serial_crops, saved_crops): 365 for a_img, b_img in zip(a, b): 366 assert np.array_equal(a_img, b_img) 367 368 # Montages got JPEG compressed, so 369 # Size comparison: 370 for a, b in zip(serial_montages, saved_montages): 371 assert a.shape == b.shape 372 373 # Visual inspection 374 if SHOW_PLOTS: 375 cv2.imshow("Original", cv2.cvtColor(serial_montages[0], cv2.COLOR_RGB2BGR)) 376 cv2.imshow("Saved", cv2.cvtColor(saved_montages[0], cv2.COLOR_RGB2BGR)) 377 cv2.waitKey(0) 378 cv2.destroyAllWindows() 379 380 # Clean up 381 for file in os.listdir("temp"): 382 os.remove(os.path.join("temp", file)) 383 os.rmdir("temp")