Source code for megafish.utils

import os
import shutil
import re
import numpy as np


[docs] def natural_sort(list_to_sort): """ Sorts a list of strings in natural order, where numerical values are ordered as numbers, not as individual characters. Args: list_to_sort (list of str): The list of strings to be sorted. Returns: list of str: A new list sorted in natural order. Example: natural_sort(['file2.txt', 'file10.txt', 'file1.txt']) -> ['file1.txt', 'file2.txt', 'file10.txt'] """ def _natural_keys(text): # Split text into components: numbers are converted to integers, others remain as strings def _atoi(text): return int(text) if text.isdigit() else text return [_atoi(c) for c in re.split(r"(\d+)", text)] # Sort the list using the natural key function return sorted(list_to_sort, key=_natural_keys)
[docs] def get_tile_yx(n_tile_y, n_tile_x, scan_type): """ Generates a list of (y, x) coordinates for tiles scanned according to a specified pattern. Args: n_tile_y (int): The number of tiles in the y direction. n_tile_x (int): The number of tiles in the x direction. scan_type (str): The scanning pattern type, e.g., "snake_up_right" or "snake_right_down". Returns: list of tuple: A list of (y, x) coordinates for each tile. Raises: ValueError: If the scan_type is not supported. """ # Horizontal snake if scan_type == "snake_right_down": tile_x = [np.arange(n_tile_x) if i % 2 == 0 else np.arange( n_tile_x)[::-1] for i in range(n_tile_y)] tile_y = np.repeat(np.arange(n_tile_y), n_tile_x) elif scan_type == "snake_left_down": tile_x = [np.arange(n_tile_x)[::-1] if i % 2 == 0 else np.arange(n_tile_x) for i in range(n_tile_y)] tile_y = np.repeat(np.arange(n_tile_y), n_tile_x) elif scan_type == "snake_right_up": tile_x = [np.arange(n_tile_x) if i % 2 == 0 else np.arange( n_tile_x)[::-1] for i in range(n_tile_y)] tile_y = np.repeat(np.arange(n_tile_y)[::-1], n_tile_x) elif scan_type == "snake_left_up": tile_x = [np.arange(n_tile_x)[::-1] if i % 2 == 0 else np.arange(n_tile_x) for i in range(n_tile_y)] tile_y = np.repeat(np.arange(n_tile_y)[::-1], n_tile_x) # Vertical snake elif scan_type == "snake_up_right": tile_y = [np.arange(n_tile_y)[::-1] if i % 2 == 0 else np.arange(n_tile_y) for i in range(n_tile_x)] tile_x = np.repeat(np.arange(n_tile_x), n_tile_y) elif scan_type == "snake_up_left": tile_y = [np.arange(n_tile_y)[::-1] if i % 2 == 0 else np.arange(n_tile_y) for i in range(n_tile_x)] tile_x = np.repeat(np.arange(n_tile_x)[::-1], n_tile_y) elif scan_type == "snake_down_right": tile_y = [np.arange(n_tile_y) if i % 2 == 0 else np.arange( n_tile_y)[::-1] for i in range(n_tile_x)] tile_x = np.repeat(np.arange(n_tile_x), n_tile_y) elif scan_type == "snake_down_left": tile_y = [np.arange(n_tile_y) if i % 2 == 0 else np.arange( n_tile_y)[::-1] for i in range(n_tile_x)] tile_x = np.repeat(np.arange(n_tile_x)[::-1], n_tile_y) # Row scan elif scan_type == "row_right_down": tile_x = np.tile(np.arange(n_tile_x), n_tile_y) tile_y = np.repeat(np.arange(n_tile_y), n_tile_x) elif scan_type == "row_left_down": tile_x = np.tile(np.arange(n_tile_x)[::-1], n_tile_y) tile_y = np.repeat(np.arange(n_tile_y), n_tile_x) elif scan_type == "row_right_up": tile_x = np.tile(np.arange(n_tile_x), n_tile_y) tile_y = np.repeat(np.arange(n_tile_y)[::-1], n_tile_x) elif scan_type == "row_left_up": tile_x = np.tile(np.arange(n_tile_x)[::-1], n_tile_y) tile_y = np.repeat(np.arange(n_tile_y)[::-1], n_tile_x) # Column scan elif scan_type == "column_down_right": tile_y = np.tile(np.arange(n_tile_y), n_tile_x) tile_x = np.repeat(np.arange(n_tile_x), n_tile_y) elif scan_type == "column_down_left": tile_y = np.tile(np.arange(n_tile_y), n_tile_x) tile_x = np.repeat(np.arange(n_tile_x)[::-1], n_tile_y) elif scan_type == "column_up_right": tile_y = np.tile(np.arange(n_tile_y)[::-1], n_tile_x) tile_x = np.repeat(np.arange(n_tile_x), n_tile_y) elif scan_type == "column_up_left": tile_y = np.tile(np.arange(n_tile_y)[::-1], n_tile_x) tile_x = np.repeat(np.arange(n_tile_x)[::-1], n_tile_y) else: raise ValueError("Unsupported scan_type") # Flatten the lists if they were created with list comprehensions if isinstance(tile_y, list): tile_y = np.concatenate(tile_y) if isinstance(tile_x, list): tile_x = np.concatenate(tile_x) return list(zip(tile_y, tile_x))
[docs] def get_round_cycle(n_round, n_cycle): """ Generates a list of (round, cycle) pairs for each round and cycle. Args: n_round (int): The number of rounds. n_cycle (int): The number of cycles. Returns: list of tuple: A list of (round, cycle) pairs for each round and cycle. """ return [(round_, cycle) for round_ in range(n_round) for cycle in range(n_cycle)]
[docs] def copy_groups(src_dir, zarr_path, groups): for group in groups: print("Copying: " + group) sample_name = os.path.splitext(os.path.basename(zarr_path))[0] src_path = os.path.join(src_dir, sample_name + ".zarr", group) dst_path = os.path.join(zarr_path, group) shutil.copytree(src_path, dst_path)