Skip to content

Commit 928f330

Browse files
Merge pull request #130 from computational-cell-analytics/revision2
Update vesicle inference
2 parents 408b807 + 1f3ad5f commit 928f330

File tree

7 files changed

+356
-33
lines changed

7 files changed

+356
-33
lines changed

doc/start_page.md

Lines changed: 49 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,12 @@ For more options supported by the IMOD exports, please run `synapse_net.export_t
147147

148148
> Note: to use these commands you have to install IMOD.
149149
150+
SynapseNet also provides two CLI comamnds for training models, one for supervised network training (see [Supervised Training](#supervised-training) for details) and one for domain adaptation (see [Domain Adaptation](#domain-adaptation) for details).
151+
150152

151153
## Python Library
152154

153-
Using the `synapse_net` python library offers the most flexibility for using the SynapseNet functionality.
155+
Using the `synapse_net` python library offers the most flexibility for using SynapseNet's functionality.
154156
You can find an example analysis pipeline implemented with SynapseNet [here](https://github.com/computational-cell-analytics/synapse-net/blob/main/examples/analysis_pipeline.py).
155157

156158
We offer different functionality for segmenting and analyzing synapses in electron microscopy:
@@ -161,21 +163,62 @@ We offer different functionality for segmenting and analyzing synapses in electr
161163

162164
Please refer to the module documentation below for a full overview of our library's functionality.
163165

166+
### Supervised Training
167+
168+
SynapseNet provides functionality for training a UNet for segmentation tasks using supervised learning.
169+
In this case, you have to provide data **and** (manual) annotations for the structure(s) you want to segment.
170+
This functionality is implemented in `synapse_net.training.supervised_training`. You can find an example script that shows how to use it [here](https://github.com/computational-cell-analytics/synapse-net/blob/main/examples/network_training.py).
171+
172+
We also provide a command line function to run supervised training: `synapse_net.run_supervised_training`. Run
173+
```bash
174+
synapse_net.run_supervised_training -h
175+
```
176+
for more information and instructions on how to use it.
177+
164178
### Domain Adaptation
165179

166-
We provide functionality for domain adaptation. It implements a special form of neural network training that can improve segmentation for data from a different condition (e.g. different sample preparation, electron microscopy technique or different specimen), **without requiring additional annotated structures**.
180+
SynapseNet provides functionality for (unsupervised) domain adaptation.
181+
This functionality is implemented through a student-teacher training approach that can improve segmentation for data from a different condition (for example different sample preparation, imaging technique, or different specimen), **without requiring additional annotated structures**.
167182
Domain adaptation is implemented in `synapse_net.training.domain_adaptation`. You can find an example script that shows how to use it [here](https://github.com/computational-cell-analytics/synapse-net/blob/main/examples/domain_adaptation.py).
168183

169-
> Note: Domain adaptation only works if the initial model you adapt already finds some of the structures in the data from a new condition. If it does not work you will have to train a network on annotated data.
184+
We also provide a command line function to run domain adaptation: `synapse_net.run_domain_adaptation`. Run
185+
```bash
186+
synapse_net.run_domain_adaptation -h
187+
```
188+
for more information and instructions on how to use it.
170189

171-
### Network Training
190+
> Note: Domain adaptation only works if the initial model already finds some of the structures in the data from a new condition. If it does not work you will have to train a network on annotated data.
172191
173-
We also provide functionality for 'regular' neural network training. In this case, you have to provide data **and** manual annotations for the structure(s) you want to segment.
174-
This functionality is implemented in `synapse_net.training.supervised_training`. You can find an example script that shows how to use it [here](https://github.com/computational-cell-analytics/synapse-net/blob/main/examples/network_training.py).
175192

176193
## Segmentation for the CryoET Data Portal
177194

178195
We have published segmentation results for tomograms of synapses stored in the [CryoET Data Portal](https://cryoetdataportal.czscience.com/). So far we have made the following depositions:
179196
- [CZCDP-10330](https://cryoetdataportal.czscience.com/depositions/10330): Contains synaptic vesicle segmentations for over 50 tomograms of synaptosomes. The segmentations were made with a model domain adapted to the synaptosome tomograms.
180197

181198
The scripts for the submissions can be found in [scripts/cryo/cryo-et-portal](https://github.com/computational-cell-analytics/synapse-net/tree/main/scripts/cryo/cryo-et-portal).
199+
200+
201+
## Community Data Submission
202+
203+
We are looking to extend and improve the SynapseNet models by training on more annotated data from electron tomography or (volume) electron microscopy.
204+
For this, we plan to collect data from community submissions.
205+
206+
If you are using SynapseNet for a task where it does not perform well, or if you would like to use it for a new segmentation task not offered by it, and have annotations for your data, then you can submit this data to us, so that we can use it to train our next version of improved models.
207+
To do this, please create an [issue on github](https://github.com/computational-cell-analytics/synapse-net/issues) and:
208+
- Use a title "Data submission: ..." ("..." should be a title for your data, e.g. "smooth ER in electron tomography")
209+
- Briefly describe your data and add an image that shows the microscopy data and the segmentation masks you have.
210+
- Make sure to describe:
211+
- The imaging modality and the structure(s) that you have segmented.
212+
- How many images and annotations you have / can submit and how you have created the annotations.
213+
- You should submit at least 5 images or crops and 20 annotated objects. If you are unsure if you have enough data please go ahead and create the issue / post and we can discuss the details.
214+
- Which data-format your images and annotations are stored in. We recommend using either `tif`, `mrc`, or `ome.zarr` files.
215+
- Please indicate that you are willing to share the data for training purpose (see also next paragraph).
216+
217+
Once you have created the post / issue, we will check if your data is suitable for submission or discuss with you how it could be extended to be suitable. Then:
218+
- We will share an agreement for data sharing. You can find **a draft** [here](https://docs.google.com/document/d/1vf5Efp5EJcS1ivuWM4f3pO5kBqEZfJcXucXL5ot0eqg/edit?usp=sharing).
219+
- You will be able to choose how you want to submit / publish your data.
220+
- Share it under a CC0 license. In this case, we will use the data for re-training and also make it publicly available as soon as the next model versions become available.
221+
- Share it for training with the option to publish it later. For example, if your data is unpublished and you want to only published once the respective publication is available. In this case, we will use the data for re-training, but not make it freely available yet. We will check with you peridiodically to see if your data can now be published.
222+
- Share it for training only. In this case, we will re-train the model on it, but not make it publicly available.
223+
- We encourage you to choose the first option (making the data available under CC0).
224+
- We will then send you a link to upload your data, after you have agreed to these terms.

scripts/cooper/revision/az_prediction.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def run_prediction(model, name, split_folder, version, split_names, in_path):
2424

2525
for fname in tqdm(file_names):
2626
if in_path:
27-
input_path=os.path.join(in_path, name, fname)
27+
input_path = os.path.join(in_path, name, fname)
2828
else:
2929
input_path = os.path.join(INPUT_ROOT, name, fname)
3030
print(f"segmenting {input_path}")
@@ -50,15 +50,14 @@ def run_prediction(model, name, split_folder, version, split_names, in_path):
5050
print(f"{output_key_seg} already saved")
5151
else:
5252
f.create_dataset(output_key_seg, data=seg, compression="lzf")
53-
5453

5554

5655
def get_model(version):
5756
assert version in (3, 4, 5, 6, 7)
5857
split_folder = get_split_folder(version)
5958
if version == 3:
6059
model_path = os.path.join(split_folder, "checkpoints", "3D-AZ-model-TEM_STEM_ChemFix_wichmann-v3")
61-
elif version ==6:
60+
elif version == 6:
6261
model_path = "/mnt/ceph-hdd/cold/nim00007/models/AZ/v6/"
6362
elif version == 7:
6463
model_path = "/mnt/lustre-emmy-hdd/usr/u12095/synapse_net/models/ConstantinAZ/checkpoints/v7/"
@@ -79,15 +78,15 @@ def main():
7978
args = parser.parse_args()
8079

8180
if args.model_path:
82-
model = load_model(model_path)
81+
model = load_model(args.model_path)
8382
else:
8483
model = get_model(args.version)
8584

8685
split_folder = get_split_folder(args.version)
8786

8887
for name in args.names:
8988
run_prediction(model, name, split_folder, args.version, args.splits, args.input)
90-
89+
9190
print("Finished segmenting!")
9291

9392

scripts/cooper/revision/common.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ def get_split_folder(version):
6565
if version == 3:
6666
split_folder = "splits"
6767
elif version == 6:
68-
split_folder= "/mnt/ceph-hdd/cold/nim00007/new_AZ_train_data/splits"
68+
split_folder = "/mnt/ceph-hdd/cold/nim00007/new_AZ_train_data/splits"
6969
else:
7070
split_folder = "models_az_thin"
7171
return split_folder

setup.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
"synapse_net.run_segmentation = synapse_net.tools.cli:segmentation_cli",
1717
"synapse_net.export_to_imod_points = synapse_net.tools.cli:imod_point_cli",
1818
"synapse_net.export_to_imod_objects = synapse_net.tools.cli:imod_object_cli",
19+
"synapse_net.run_supervised_training = synapse_net.training.supervised_training:main",
20+
"synapse_net.run_domain_adaptation = synapse_net.training.domain_adaptation:main",
1921
],
2022
"napari.manifest": [
2123
"synapse_net = synapse_net:napari.yaml",

synapse_net/inference/vesicles.py

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import time
2+
import warnings
23
from typing import Dict, List, Optional, Tuple, Union
34

45
import elf.parallel as parallel
@@ -8,6 +9,7 @@
89

910
from synapse_net.inference.util import apply_size_filter, get_prediction, _Scaler
1011
from synapse_net.inference.postprocessing.vesicles import filter_border_objects, filter_border_vesicles
12+
from skimage.segmentation import relabel_sequential
1113

1214

1315
def distance_based_vesicle_segmentation(
@@ -148,6 +150,10 @@ def segment_vesicles(
148150
return_predictions: Whether to return the predictions (foreground, boundaries) alongside the segmentation.
149151
scale: The scale factor to use for rescaling the input volume before prediction.
150152
exclude_boundary: Whether to exclude vesicles that touch the upper / lower border in z.
153+
exclude_boundary_vesicles: Whether to exlude vesicles on the boundary that have less than the full diameter
154+
inside of the volume. This is an alternative to post-processing with `exclude_boundary` that filters
155+
out less vesicles at the boundary and is better suited for volumes with small context in z.
156+
If `exclude_boundary` is also set to True, then this option will have no effect.
151157
mask: An optional mask that is used to restrict the segmentation.
152158
153159
Returns:
@@ -181,26 +187,23 @@ def segment_vesicles(
181187
foreground, boundaries, verbose=verbose, min_size=min_size, **kwargs
182188
)
183189

184-
if exclude_boundary:
190+
if exclude_boundary and exclude_boundary_vesicles:
191+
warnings.warn(
192+
"You have set both 'exclude_boundary' and 'exclude_boundary_vesicles' to True."
193+
"The 'exclude_boundary_vesicles' option will have no effect."
194+
)
185195
seg = filter_border_objects(seg)
186-
if exclude_boundary_vesicles:
187-
seg_ids = filter_border_vesicles(seg)
188-
# Step 1: Zero out everything not in seg_ids
189-
seg[~np.isin(seg, seg_ids)] = 0
190-
191-
# Step 2: Relabel remaining IDs to be consecutive starting from 1
192-
unique_ids = np.unique(seg)
193-
unique_ids = unique_ids[unique_ids != 0] # Exclude background (0)
194196

195-
label_map = {old_label: new_label for new_label, old_label in enumerate(unique_ids, start=1)}
197+
elif exclude_boundary:
198+
seg = filter_border_objects(seg)
196199

197-
# Apply relabeling using a temp array (to avoid large ints in-place)
198-
new_seg = np.zeros_like(seg, dtype=np.int32)
199-
for old_label, new_label in label_map.items():
200-
new_seg[seg == old_label] = new_label
200+
elif exclude_boundary_vesicles:
201+
# Filter the vesicles that are at the z-border with less than their full diameter.
202+
seg_ids = filter_border_vesicles(seg)
201203

202-
# Final step: replace original seg with relabelled and casted version
203-
seg = new_seg
204+
# Remove everything not in seg ids and relable the remaining IDs consecutively.
205+
seg[~np.isin(seg, seg_ids)] = 0
206+
seg = relabel_sequential(seg)[0]
204207

205208
seg = scaler.rescale_output(seg, is_segmentation=True)
206209

0 commit comments

Comments
 (0)