Source code for owl.mcam_data._util

import numpy as np

valid_bayer_patterns = ['rggb', 'bggr', 'grbg', 'gbrg']
DEFAULT_IMAGENAME_FORMAT = r'cam{r:d}_{c:d}.bmp'


[docs] def resize_as_square(images, axes=(2, 3)): """Slice your image retaining the center square. Parameters ---------- images: array-like numpy-like array containing the following leading dimensions `['image_y', 'image_x', 'y', 'x']`. Returns ------- images: array-like With equal dimensions on the 'y' and 'x' dimensions. """ x_axis = axes[1] y_axis = axes[0] shape = images.shape if shape[x_axis] == shape[y_axis]: return images else: to_cut = shape[x_axis] - shape[y_axis] if to_cut > 0: index = x_axis else: index = y_axis if index < 0: index = len(shape) + index to_cut = abs(to_cut) to_cut_start = to_cut // 2 if to_cut_start > 0 or to_cut % 2 != 0: the_slice = slice(to_cut_start, -(to_cut_start + to_cut % 2)) images = images[(slice(None,),) * index + (the_slice,)] return images
[docs] def trim_to_valid(dataset): """Trim the dataset to the valid data. If ``valid_data`` is contained within the dataset, then the dataset is sliced such that the removed data contains only invalid data. Basic slicing is supported, such as contiguous slices, or slices with steps. The slicing is done using the ``image_y`` and ``image_x`` dimensions of the dataset. """ if 'valid_data' not in dataset: return dataset valid_data = dataset.valid_data.compute() valid = valid_data.any() if not valid: raise RuntimeError("Dataset does not contain any valid data.") valid_image_y = np.asarray( valid_data.any(set(valid_data.dims) - set(('image_y',))) ) valid_image_x = np.asarray( valid_data.any(set(valid_data.dims) - set(('image_x',))) ) valid_y = list(valid_image_y) valid_x = list(valid_image_x) start_y = valid_y.index(True) end_y = len(valid_y) - valid_y[::-1].index(True) start_x = valid_x.index(True) end_x = len(valid_x) - valid_x[::-1].index(True) max_len_y = max(end_y - start_y, 1) N_valid_y = np.sum(valid_image_y) # We know for sure that the two ends must be included # So we don't have to look for the starting index for skip_y in reversed(range(max_len_y)[1:]): if np.sum(valid_image_y[start_y:end_y:skip_y]) == N_valid_y: break else: skip_y = 1 max_len_x = max(end_x - start_x, 1) N_valid_x = np.sum(valid_image_x) for skip_x in reversed(range(max_len_x)[1:]): if np.sum(valid_image_x[start_x:end_x:skip_x]) == N_valid_x: break else: skip_x = 1 the_slice_y = slice(start_y, end_y, skip_y) the_slice_x = slice(start_x, end_x, skip_x) return dataset.isel(image_y=the_slice_y, image_x=the_slice_x)
[docs] def get_valid_data(dataset): """Get the valid data from the dataset. If the dataset contains a variable named ``valid_data``, then the variable is used to determine the valid data. If not, then a boolean array of the same shape as the images is returned. """ if 'valid_data' in dataset: valid_data = np.asarray(dataset.valid_data.any( dim=[ d for d in dataset.valid_data.dims if d not in ('image_y', 'image_x') ] )) else: valid_data = np.ones( (dataset.sizes["image_y"], dataset.sizes["image_x"]), dtype=bool ) return valid_data
def remove_invalid_images(dataset, axis=('image_y', 'image_x')): """Remove indices along the give axis that are completely invalid. Parameters ---------- dataset : xarray.Dataset The dataset to be trimmed. Returns ------- xarray.Dataset The trimmed dataset. """ if isinstance(axis, str): axis = (axis,) if 'valid_data' not in dataset: return dataset isel_dict = {} for ax in axis: if ax not in dataset.dims: raise ValueError(f"axis {ax} not in dataset images dims {dataset.dims}") index_array = np.asarray(dataset.valid_data.any( dim=[ d for d in dataset.valid_data.dims if d != ax ] )) isel_dict[ax] = index_array # We rely on outer indexing provided by xarray # See the discussion on how this is not the "basic" indexing # provided by numpy arrays # https://mail.python.org/archives/list/numpy-discussion@python.org/thread/M43RXEN3R7XRZ7ARUWNX6SL4JMH6GZ7R/ # Howevever, some of our datasets are naturally sparse along certain outer dimensions # the cost of calling dataset.isel twice is low enough that we can call it this way. for key, value in isel_dict.items(): dataset = dataset.isel({key: value}) return dataset def get_valid_metadata(dataset, metadata_key): if 'valid_data' not in dataset: # Return the full array, flattened, as it would be if we indexed # it with an array of all boolean values return dataset[metadata_key].data.flatten() # The valid data may not be of the same dimensions of the array # Case #1: # The data_array may come in with some of the image_y or image_x # as constants or dimensions independent of the valid_data # To get through this, we must collapse the valid data first, # Then use that to index the data_array # Case #2: # The data_array may have more dimensions than the variable = dataset[metadata_key] valid_data = dataset.valid_data.broadcast_like(variable) valid_data = valid_data.any( dim=[ d for d in valid_data.dims if d not in variable.dims ] ) valid_data = np.asarray(valid_data) return variable.data[valid_data] def populate_fake_device_dataset(mcam): from ._new import new_dataset from .samples import ( hoechst_gfp_96wellplate, larval_zebrafish_screening_IR, sw620_spheroids, zebrafish_in_a_96wellplate, zebrafish_in_a_96wellplate_inverted_kestrel, zebrafish_screening_morphology_square_wells, ) # By default, the acquisition mode is "noise" but that # causes the GUI to be ugly on the first acquisition. # Since we need to be able to use this for screenshots # I don't want the screenshots to look terrible on the first go # This behavior may change in the future. # mcam._falcon._fake_acquisition_settings['acquisition_mode'] = 'increment' mcam._falcon._fake_acquisition_settings['acquisition_mode'] = 'noise' # Big giant hack to get the fake MCAM to look decent in test scenarios if mcam._falcon.dna_string == "0x4EADBEEFCAFE1010BA5EBA11": # This sample dataset is quite specific to this particular Fake MCAM dataset = zebrafish_in_a_96wellplate() elif mcam._falcon.dna_string == "0x4EADBEEFCAFE1010BA5EDA11": dataset = zebrafish_in_a_96wellplate_inverted_kestrel() elif mcam.serial_number in ["Kestrel0010R"]: dataset = zebrafish_screening_morphology_square_wells() elif mcam.serial_number in ["Kestrel0053R"]: dataset = larval_zebrafish_screening_IR() elif mcam.serial_number in [ "Vireo1101R", "Vireo1107R", "Vireo1109R", "Vireo1111R", # Vireo1108 setup is automation only hardware. "Vireo1108", "Vireo1108R", ]: dataset = sw620_spheroids() elif mcam.serial_number in ["Vireo1112R"]: dataset = hoechst_gfp_96wellplate() elif mcam.serial_number == "Falcon0106R": dataset = new_dataset( N_cameras=mcam.N_cameras, image_shape=(3136, 4224), ) dataset.images.data[...] = 20 dataset.images.data[0:5, 0:5][..., 1::2, 0::2] = 128 dataset.images.data[4:9, 1:6][..., 0::2, 1::2] = 128 else: return mcam._falcon._fake_acquisition_settings['dataset'] = dataset