diff --git a/extensions/chaeo/batch_jobs/20231023_Porto_4ch.py b/extensions/chaeo/batch_jobs/20231023_Porto_4ch.py index 0d99fe5f5267d0ff6969235a4f44222ea478b5aa..1e263ddf8cb834fa0e416773a6adf6f5f6b5c234 100644 --- a/extensions/chaeo/batch_jobs/20231023_Porto_4ch.py +++ b/extensions/chaeo/batch_jobs/20231023_Porto_4ch.py @@ -22,19 +22,18 @@ if __name__ == '__main__': # write single-position TIF color stacks where_proc = Path(where_output) / 'proc' - # for pos in range(0, cf.shape[cf.axes.index('S')]): + + for pos in range(0, cf.shape[cf.axes.index('S')]): # for pos in [0, 50, 100, 150, 200]: - # fname = f'{czi_filepath.stem}_p{pos:02d}.tif' - # write_accessor_data_to_file( - # where_proc / fname, - # get_accessor_from_multiposition_czi(cf, pos) - # ) - # print(f'Wrote file {fname}') + fname = f'{czi_filepath.stem}_p{pos:04d}.tif' + write_accessor_data_to_file( + where_proc / fname, + get_accessor_from_multiposition_czi(cf, pos) + ) + print(f'Wrote file {fname}') px_ilp = Path('c:/Users/rhodes/projects/proj0017-ehcfm-analysis/exp0001/ilastik/px_4ch_02.ilp').__str__() - where_proc = Path('c:/Users/rhodes/projects/proj0017-ehcfm-analysis/exp0001/output/batch-output-20240126-0003/proc') - params = { 'pxmap_threshold': 0.25, 'pxmap_foreground_channel': 0, @@ -55,6 +54,7 @@ if __name__ == '__main__': 'rgb_overlay_channels': (1, None, None), 'rgb_overlay_weights': (0.2, 1.0, 1.0), 'draw_label_on_zstack': True, + 'pxmap_use_all_channels': True, } input_files = get_matching_files(where_proc, 'tif', coord_filter={}) @@ -66,14 +66,13 @@ if __name__ == '__main__': [IlastikPixelClassifierModel(params={'project_file': Path(px_ilp)})], params, catch_and_continue=False, - chunk_size=25, + chunk_size=50, ) write_ecotaxa_tsv_chunked_subdirectories( where_output, 'workflow_data.csv', sample_id=sample_id, - scope_id='EMBL-MS-Zeiss-LSM900' + scope_id='EMBL-MS-Zeiss-LSM900', ) - print('Finished') \ No newline at end of file diff --git a/extensions/chaeo/workflows.py b/extensions/chaeo/workflows.py index 3231ef6befc27cc21bbcb4e14d7db67c16907f79..6adf7a077395f331061754b3061a2f4a2c8af210 100644 --- a/extensions/chaeo/workflows.py +++ b/extensions/chaeo/workflows.py @@ -31,6 +31,7 @@ def get_zmask_meta( zmask_clip: int = None, zmask_filters: Dict = None, zmask_type: str = 'boxes', + pxmap_use_all_channels: bool = False, **kwargs, ) -> tuple: ti = Timer() @@ -41,9 +42,15 @@ def get_zmask_meta( # MIP if no zmask z-index is given, then classify pixels if isinstance(zmask_zindex, int): assert 0 < zmask_zindex < stack.nz - zmask_data = stack.get_one_channel_data(channel=segmentation_channel).data[:, :, :, zmask_zindex] + if pxmap_use_all_channels: + zmask_data = stack.data[:, :, :, zmask_zindex] + else: + zmask_data = stack.get_one_channel_data(channel=segmentation_channel).data[:, :, :, zmask_zindex] else: - zmask_data = stack.get_one_channel_data(channel=segmentation_channel).data.max(axis=-1, keepdims=True) + if pxmap_use_all_channels: + zmask_data = stack.data.max(axis=-1, keepdims=True) + else: + zmask_data = stack.get_one_channel_data(channel=segmentation_channel).data.max(axis=-1, keepdims=True) if zmask_clip: zmask_data = rescale(zmask_data, zmask_clip) mip = InMemoryDataAccessor( @@ -68,7 +75,8 @@ def get_zmask_meta( ti.click('generate_zmasks') # record pixel scale - df['pixel_scale_in_micrometers'] = float(stack.pixel_scale_in_micrometers.get('X')) + px_scale = stack.pixel_scale_in_micrometers.get('X') + df['pixel_scale_in_micrometers'] = float(px_scale) if px_scale is not None else None return ti, stack, fstem, obmask, pxmap, zmask, zmask_meta, df, interm @@ -80,7 +88,7 @@ def export_patches_from_multichannel_zstack( models: List[Model], pxmap_threshold: float, pxmap_foreground_channel: int, - segmentation_channel: int, + segmentation_channel: int, # -1 to use all channels patches_channel: int, zmask_zindex: int = None, # None for MIP, zmask_clip: int = None, @@ -99,6 +107,7 @@ def export_patches_from_multichannel_zstack( export_patch_masks=True, rgb_overlay_channels=(None, None, None), rgb_overlay_weights=(1.0, 1.0, 1.0), + **kwargs, ) -> Dict: pixel_classifier = models[0] @@ -113,6 +122,7 @@ def export_patches_from_multichannel_zstack( zmask_expand_box_by=zmask_expand_box_by, zmask_filters=zmask_filters, zmask_type=zmask_type, + **kwargs, ) if export_pixel_probabilities: diff --git a/tests/test_accessors.py b/tests/test_accessors.py deleted file mode 100644 index 557970ea691b91b228a43e29993bc4068c8d88db..0000000000000000000000000000000000000000 --- a/tests/test_accessors.py +++ /dev/null @@ -1,118 +0,0 @@ -import unittest - -import numpy as np - -from conf.testing import czifile, output_path, monopngfile, rgbpngfile, tifffile, monozstackmask -from model_server.accessors import CziImageFileAccessor, DataShapeError, generate_file_accessor, InMemoryDataAccessor, PngFileAccessor, write_accessor_data_to_file, TifSingleSeriesFileAccessor - -class TestCziImageFileAccess(unittest.TestCase): - - def setUp(self) -> None: - pass - - def test_tiffile_is_correct_shape(self): - tf = generate_file_accessor(tifffile['path']) - - self.assertIsInstance(tf, TifSingleSeriesFileAccessor) - self.assertEqual(tf.shape_dict['Y'], tifffile['h']) - self.assertEqual(tf.shape_dict['X'], tifffile['w']) - self.assertEqual(tf.chroma, tifffile['c']) - self.assertTrue(tf.is_3d()) - self.assertEqual(len(tf.data.shape), 4) - self.assertEqual(tf.shape[0], tifffile['h']) - self.assertEqual(tf.shape[1], tifffile['w']) - - def test_czifile_is_correct_shape(self): - cf = CziImageFileAccessor(czifile['path']) - self.assertEqual(cf.shape_dict['Y'], czifile['h']) - self.assertEqual(cf.shape_dict['X'], czifile['w']) - self.assertEqual(cf.chroma, czifile['c']) - self.assertFalse(cf.is_3d()) - self.assertEqual(len(cf.data.shape), 4) - self.assertEqual(cf.shape[0], czifile['h']) - self.assertEqual(cf.shape[1], czifile['w']) - - def test_get_single_channel_from_zstack(self): - w = 256 - h = 512 - nc = 4 - nz = 11 - c = 3 - cf = InMemoryDataAccessor(np.random.rand(h, w, nc, nz)) - sc = cf.get_one_channel_data(c) - self.assertEqual(sc.shape, (h, w, 1, nz)) - - def test_write_single_channel_tif(self): - ch = 4 - cf = CziImageFileAccessor(czifile['path']) - mono = cf.get_one_channel_data(ch) - self.assertTrue( - write_accessor_data_to_file( - output_path / f'{cf.fpath.stem}_ch{ch}.tif', - mono - ) - ) - self.assertEqual(cf.data.shape[0:2], mono.data.shape[0:2]) - self.assertEqual(cf.data.shape[3], mono.data.shape[2]) - - def test_conform_data_shorter_than_xycz(self): - h = 256 - w = 512 - data = np.random.rand(h, w, 1) - acc = InMemoryDataAccessor(data) - self.assertEqual( - InMemoryDataAccessor.conform_data(data).shape, - (256, 512, 1, 1) - ) - self.assertEqual( - acc.shape_dict, - {'Y': 256, 'X': 512, 'C': 1, 'Z': 1} - ) - - def test_conform_data_longer_than_xycz(self): - data = np.random.rand(256, 512, 12, 8, 3) - with self.assertRaises(DataShapeError): - acc = InMemoryDataAccessor(data) - - - def test_write_multichannel_image_preserve_axes(self): - h = 256 - w = 512 - c = 3 - nz = 10 - - yxcz = (2**8 * np.random.rand(h, w, c, nz)).astype('uint8') - acc = InMemoryDataAccessor(yxcz) - fp = output_path / f'rand3d.tif' - self.assertTrue( - write_accessor_data_to_file(fp, acc) - ) - # need to sort out x,y flipping since np convention yxcz flips axes in 3d tif - self.assertEqual(acc.shape_dict['X'], w, acc.shape_dict) - self.assertEqual(acc.shape_dict['Y'], h, acc.shape_dict) - - # re-open file and check axes order - from tifffile import TiffFile - fh = TiffFile(fp) - self.assertEqual(len(fh.series), 1) - se = fh.series[0] - fh_shape_dict = {se.axes[i]: se.shape[i] for i in range(0, len(se.shape))} - self.assertEqual(fh_shape_dict, acc.shape_dict, 'Axes are not preserved in TIF output') - - def test_read_png(self, pngfile=rgbpngfile): - acc = PngFileAccessor(pngfile['path']) - self.assertEqual(acc.hw, (pngfile['h'], pngfile['w'])) - self.assertEqual(acc.chroma, pngfile['c']) - self.assertEqual(acc.nz, 1) - - def test_read_mono_png(self): - return self.test_read_png(pngfile=monopngfile) - - def test_read_zstack_mono_mask(self): - acc = generate_file_accessor(monozstackmask['path']) - self.assertTrue(acc.is_mask()) - - def test_read_in_pixel_scale_from_czi(self): - cf = CziImageFileAccessor(czifile['path']) - pxs = cf.pixel_scale_in_micrometers - self.assertAlmostEqual(pxs['X'], czifile['um_per_pixel'], places=3) \ No newline at end of file