11from typing import Optional , Tuple
22
3- import numpy as np
4- import uuid
5- import h5py
63import torch
74import torch_em
85import torch_em .self_training as self_training
96from torchvision import transforms
7+ from torch_em .data import RawDatasetWithMasks
108
11- from synapse_net .file_utils import read_mrc
129from .supervised_training import get_2d_model , get_3d_model , get_supervised_loader , _determine_ndim
1310
1411
@@ -31,26 +28,6 @@ def weak_augmentations(p: float = 0.75) -> callable:
3128 ])
3229 return torch_em .transform .raw .get_raw_transform (normalizer = norm , augmentation1 = aug )
3330
34- def drop_mask_channel (x ):
35- x = x [:1 ]
36- return x
37-
38- class ComposedTransform :
39- def __init__ (self , * funcs ):
40- self .funcs = funcs
41-
42- def __call__ (self , x ):
43- for f in self .funcs :
44- x = f (x )
45- return x
46-
47- class ChannelSplitterSampler :
48- def __init__ (self , sampler ):
49- self .sampler = sampler
50-
51- def __call__ (self , x ):
52- raw , mask = x [0 ], x [1 ]
53- return self .sampler (raw , mask )
5431
5532def get_unsupervised_loader (
5633 data_paths : Tuple [str ],
@@ -59,8 +36,11 @@ def get_unsupervised_loader(
5936 batch_size : int ,
6037 n_samples : Optional [int ],
6138 sample_mask_paths : Optional [Tuple [str ]] = None ,
39+ sample_mask_key : Optional [str ] = None ,
40+ bg_mask_paths : Optional [Tuple [str ]] = None ,
41+ bg_mask_key : Optional [str ] = None ,
6242 sampler : Optional [callable ] = None ,
63- exclude_top_and_bottom : bool = False ,
43+ exclude_top_and_bottom : bool = False ,
6444) -> torch .utils .data .DataLoader :
6545 """Get a dataloader for unsupervised segmentation training.
6646
@@ -73,61 +53,57 @@ def get_unsupervised_loader(
7353 batch_size: The batch size for training.
7454 n_samples: The number of samples per epoch. By default this will be estimated
7555 based on the patch_shape and size of the volumes used for training.
76- exclude_top_and_bottom: Whether to exluce the five top and bottom slices to
77- avoid artifacts at the border of tomograms.
7856 sample_mask_paths: The filepaths to the corresponding sample masks for each tomogram.
57+ sample_mask_key: The key to the sample mask dataset inside each file.
58+ bg_mask_paths: The filepaths to the background masks for each tomogram.
59+ bg_mask_key: The key to the background mask dataset inside each file.
7960 sampler: Accept or reject patches based on a condition.
61+ exclude_top_and_bottom: Whether to exclude the five top and bottom slices to
62+ avoid artifacts at the border of tomograms.
8063
8164 Returns:
8265 The PyTorch dataloader.
8366 """
84- # We exclude the top and bottom slices where the tomogram reconstruction is bad.
85- # TODO this seems unneccesary if we have a boundary mask - remove?
8667 if exclude_top_and_bottom :
87- roi = np . s_ [ 5 : - 5 , :, :]
68+ roi = ( slice ( 5 , - 5 ), slice ( None ), slice ( None ))
8869 else :
8970 roi = None
90- # stack tomograms and masks and write to temp files to use as input to RawDataset()
71+
9172 if sample_mask_paths is not None :
9273 assert len (data_paths ) == len (sample_mask_paths ), \
93- f"Expected equal number of data_paths and and sample_masks_paths, got { len (data_paths )} data paths and { len (sample_mask_paths )} mask paths."
94-
95- stacked_paths = []
96- for i , (data_path , mask_path ) in enumerate (zip (data_paths , sample_mask_paths )):
97- raw = read_mrc (data_path )[0 ]
98- mask = read_mrc (mask_path )[0 ]
99- stacked = np .stack ([raw , mask ], axis = 0 )
100-
101- tmp_path = f"/tmp/stacked{ i } _{ uuid .uuid4 ().hex } .h5"
102- with h5py .File (tmp_path , "w" ) as f :
103- f .create_dataset ("raw" , data = stacked , compression = "gzip" )
104- stacked_paths .append (tmp_path )
105-
106- # update variables for RawDataset()
107- data_paths = tuple (stacked_paths )
108- base_transform = torch_em .transform .get_raw_transform ()
109- raw_transform = ComposedTransform (base_transform , drop_mask_channel )
110- sampler = ChannelSplitterSampler (sampler )
111- with_channels = True
112- else :
113- raw_transform = torch_em .transform .get_raw_transform ()
114- with_channels = False
115- sampler = None
74+ f"Expected equal number of data_paths and sample_mask_paths, got { len (data_paths )} and { len (sample_mask_paths )} ."
75+ if bg_mask_paths is not None :
76+ assert len (data_paths ) == len (bg_mask_paths ), \
77+ f"Expected equal number of data_paths and bg_mask_paths, got { len (data_paths )} and { len (bg_mask_paths )} ."
11678
11779 _ , ndim = _determine_ndim (patch_shape )
80+ raw_transform = torch_em .transform .get_raw_transform ()
11881 transform = torch_em .transform .get_augmentations (ndim = ndim )
82+ augmentations = (weak_augmentations (), weak_augmentations ())
11983
12084 if n_samples is None :
12185 n_samples_per_ds = None
12286 else :
12387 n_samples_per_ds = int (n_samples / len (data_paths ))
12488
125- augmentations = (weak_augmentations (), weak_augmentations ())
126-
12789 datasets = [
128- torch_em .data .RawDataset (path , raw_key , patch_shape , raw_transform , transform , roi = roi ,
129- n_samples = n_samples_per_ds , sampler = sampler , ndim = ndim , with_channels = with_channels , augmentations = augmentations )
130- for path in data_paths
90+ RawDatasetWithMasks (
91+ raw_path = data_path ,
92+ raw_key = raw_key ,
93+ patch_shape = patch_shape ,
94+ raw_transform = raw_transform ,
95+ transform = transform ,
96+ roi = roi ,
97+ n_samples = n_samples_per_ds ,
98+ sampler = sampler ,
99+ ndim = ndim ,
100+ augmentations = augmentations ,
101+ sample_mask_path = sample_mask_paths [i ] if sample_mask_paths is not None else None ,
102+ sample_mask_key = sample_mask_key ,
103+ bg_mask_path = bg_mask_paths [i ] if bg_mask_paths is not None else None ,
104+ bg_mask_key = bg_mask_key ,
105+ )
106+ for i , data_path in enumerate (data_paths )
131107 ]
132108 ds = torch .utils .data .ConcatDataset (datasets )
133109
0 commit comments