def test_find_nuclei(): data = read_stack(home('stack.tif')) mask = find_nuclei(data[0][0], um_per_px=0.35) mask_ = read_stack(home('nuclei.tif')) assert (mask == mask_).all()
def test_write_stack(): data = read_stack(stack) saveto = tmp.next() + '.tif' # test compression for compress in (0, 1): save_stack(saveto, data, compress=compress) data_ = read_stack(saveto) assert hash_np(data) == hash_np(data_) # test data types for dtype in (np.bool, np.uint8, np.uint16, np.float32, np.float64): save_stack(saveto, data.astype(dtype)) data_ = read_stack(saveto) if dtype == np.bool: assert data_.max() == 255 else: assert data_.max() == data.astype(dtype).max() if dtype == np.bool: assert data_.dtype == np.uint8 elif dtype == np.float64: assert data_.dtype == np.float32 else: assert data_.dtype == dtype # test resolution # test LUTS, display_ranges os.remove(saveto)
def table_from_nuclei(row, index_names, source='aligned', nuclei='nuclei', channels=None, features=default_features, nucleus_features=default_nucleus_features, nuclei_dilation=None, data=None): """Build Cells DataFrame from Paths DataFrame, list of features, calibrated aligned data, and image with segmented nuclei. :param row: from Paths DataFrame, containing filenames in source and nuclei columns :param source: column with filename of data file, [channels, height, width] :param nuclei: column with filename of segmented nuclei, [height, width] :param channels: names of channels, used to name first column index level :param features: dict of functions accepting regionprops region as argument, key used to name second column index level :param nuclei_dilation: structuring element by which to dilate nuclei image before calling regionprops :param data: [channels, height, width] from which channel data is drawn, otherwise loaded from source :return: """ # prefix to channel-specific features channels = ['channel' + str(i) for i in range(100)] if channels is None else channels # load nuclei file, data segmented = io.read_stack(config.paths.full(row[nuclei])) if data is None: data = io.read_stack(config.paths.full(row[source])) if nuclei_dilation is not None: segmented = skimage.morphology.dilation(segmented, nuclei_dilation) info = [] for region in regionprops(segmented, intensity_image=segmented): info += [{k: v(region) for k, v in nucleus_features.items()}] df = pd.DataFrame(info, index=[list(x) for x in zip(*[list(row.name)] * len(info))]) df['file'] = row[source] df['hash'] = [uuid.uuid4().hex for _ in range(df.shape[0])] df.columns = pd.MultiIndex(labels=zip(*[[0, i] for i in range(len(df.columns))]), levels=[['all'], df.columns], names=['channel', 'feature']) # add channel-specific features if data.ndim == 2: data = data[np.newaxis, :, :] for channel, image in zip(channels, data): channel_regions = regionprops(segmented, intensity_image=image) for name, fcn in features.items(): df[channel, name] = [fcn(r) for r in channel_regions] df.index.names = index_names df = df.set_index(('all', 'label'), append=True) df.index.set_names('label', level=[('all', 'label')], inplace=True) return df
def test_alpha_blend(): tiles = ['tile_%d.tif' % i for i in range(4)] arr = [read_stack(home(t)) for t in tiles] translations = read_registered(home('tiles_registered.txt')) fused = alpha_blend(arr, translations, clip=False) fused_ = read_stack(home('fused.tif')) average_diff = np.abs(fused.astype(float) - fused_.astype(float)).sum() / fused.size assert average_diff < 1.
def test_find_cells(): import skimage.morphology import lasagna.process data = read_stack(home('stack.tif')) nuclei_ = read_stack(home('nuclei.tif')) mask = read_stack(home('mask.tif')) cells = find_cells(nuclei_, mask) cells_ = read_stack(home('cells.tif')) assert (cells == cells_[-1]).all()
def test_read_stack(): data = read_stack(nuclei) assert hash_np(data) == -2955782303036816501 data = read_stack(nuclei_compressed) assert hash_np(data) == -2955782303036816501 data = read_stack(stack) assert data.shape == (3, 4, 511, 626) assert hash_np(data) == 4530181413177493733 # test memory mapping, endian data_ = read_stack(stack, memmap=True) assert (data == data_).all()
def update_illumination(self): self.calibration = pd.DataFrame() channels = self.info['channels'] for dye, files in self.files.items(): data = np.array([io.read_stack(f) for f in files]) for frame, channel in zip(np.median(data, axis=0), channels): # pandas doesn't like initializing with array-like self.calibration.loc[channel, dye] = 'x' self.calibration.loc[channel, dye] = frame self.calibration = self.calibration[sorted(self.calibration, key=lambda x: spectral_order.index(x))] self.calibration_med = self.calibration.applymap(lambda x: np.median(x)) # subtract constant background # normalize to matching dye + channel self.calibration_norm = self.calibration_med.subtract(self.calibration_med['empty'], axis=0) for column in self.calibration_norm: if column != 'empty': self.calibration_norm[column] /= self.calibration_norm.loc[column, column] # compute individual and average illumination correction, save to file self.illumination = pd.Series() for dye in self.calibration.columns: if dye != 'empty': data = self.calibration.loc[dye, dye] data = data - self.calibration.loc[dye, 'empty'] self.illumination[dye] = data / np.percentile(data.flatten(), 99) self.illumination[dye] = data / data.mean() self.illumination_mean = self.illumination.mean() # dump illumination stack stack = np.array([self.illumination_mean] + list(self.illumination)) luts = [io.GRAY] + [spectral_luts[dye] for dye in self.calibration.columns if dye != 'empty'] save_name = os.path.join(os.path.dirname(self.path), 'illumination_correction_%s.tif' % self.name) io.save_hyperstack(save_name, 10000 * stack, luts=luts)
def test_subimage(): data = read_stack(stack) p = 10 data_ = subimage(data, [10, 5, 15, 30], pad=p) assert (data_[..., 5:] == data[..., 0:25, :40]).all() assert (data_ == 0).sum() == 1500
def test_offset(): data = read_stack(stack) offsets = [1, -1, 4, 8] data_ = offset(data, offsets) assert data.shape == data_.shape assert data_[1, 0, 4, 8] == data[0, 1, 0, 0]
def test_feature_table(): features = { 'area': lambda region: region.area, 'bounds': lambda region: region.bbox, 'label': lambda region: np.median(region.intensity_image[region.intensity_image > 0]), } data = read_stack(stack) mask = read_stack(nuclei) df = feature_table(data[0][0], mask, features) df_ = pd.read_pickle(home('feature_table.pkl')) assert (df == df_).all().all()
def update_dead_pixels(self, null_pixels=10): """Pick a threshold so # of background pixels above threshold is about `null_pixels`. """ self.dead_pixels = io.read_stack(self.dead_pixels_file) sigma_factor = np.log(self.dead_pixels.size/null_pixels) self.dead_pixels_std = (self.dead_pixels[self.dead_pixels < self.dead_pixels.mean()]).std() # empirical adjustment self.dead_pixels_threshold = 2.5 * sigma_factor * self.dead_pixels_std + self.dead_pixels.mean() self.dead_pixels_pts = np.where(self.dead_pixels > self.dead_pixels_threshold)
def test_nuclei(): io.initialize_paths('20150717', subset='20X_hyb_and_washes/', lasagna_dir='/Volumes/blainey_lab/David/lasagna/') master = io.DIR['stacks'][0] test_file = io.DIR['stacks'][3] data = io.read_stack(test_file, master=master, memmap=False) process.DOWNSAMPLE = 2 n = process.get_nuclei(data[0, 0, :, :]) return n
def test_montage(): data = read_stack(stack) data = data[..., :400, :500] n = 100 arr = [] for i in range(4): for j in range(5): arr += [data[:, :, i * n:i * n + n, j * n:j * n + n]] assert (montage(arr, shape=(4, 5)) == data).all()
def test_pile(): data = read_stack(stack) arr = [] for n in (30, 40, 50): arr += [data[..., :n, :n]] data_ = pile(arr) # same tiles in vertical stack assert ((data_[..., :30, :30] - data_[0, ..., :30, :30]) == 0).all() # number of padded entries assert (data_ == 0).sum() == 30000
def test_build_feature_table(): features = { 'mean': lambda region: region.intensity_image[region.image].mean(), 'median': lambda region: np.median(region.intensity_image[region.image]), 'max': lambda region: region.intensity_image[region.image].max() } index = (('round', range(1, 4)), ('channel', ('DAPI', 'Cy3', 'A594', 'Cy5'))) data = read_stack(stack) mask = read_stack(nuclei) df = build_feature_table(data, mask, features, index) df.index.name = 'cell' df = df.set_index(['round', 'channel'], append=True).stack().unstack('cell').T df_ = pd.read_pickle(home('build_feature_table.pkl')) assert (df == df_).all().all()
def test_nuclei_stitch(well=(('A2',),0)): io.initialize_paths('20150716', subset='stitched/', lasagna_dir='/Volumes/blainey_lab/David/lasagna/') dict_20X = defaultdict(list) [dict_20X[io.get_well_site(f)].append(f) for f in io.DIR['stacks'] if '20X' in f] test_files = dict_20X[well] print '(well, site) found', dict_20X.keys() print 'from', well, 'loading', test_files data = {f: io.read_stack(f, memmap=False) for f in test_files} offsets = process.register_images(data.values()) C = io.compose_stacks([io.offset_stack(d, offset) for d, offset in zip(data.values(), offsets)]) return data, offsets, C
def test_nuclei_stitch(well=(('A2', ), 0)): io.initialize_paths('20150716', subset='stitched/', lasagna_dir='/Volumes/blainey_lab/David/lasagna/') dict_20X = defaultdict(list) [ dict_20X[io.get_well_site(f)].append(f) for f in io.DIR['stacks'] if '20X' in f ] test_files = dict_20X[well] print '(well, site) found', dict_20X.keys() print 'from', well, 'loading', test_files data = {f: io.read_stack(f, memmap=False) for f in test_files} offsets = process.register_images(data.values()) C = io.compose_stacks( [io.offset(d, offset) for d, offset in zip(data.values(), offsets)]) return data, offsets, C
def update_background(self): self.background = np.median([io.read_stack(f) for f in self.files['empty']], axis=0)