small-fish-gui 2.0.1__py3-none-any.whl → 2.0.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- small_fish_gui/__init__.py +9 -3
- small_fish_gui/batch/integrity.py +2 -2
- small_fish_gui/batch/pipeline.py +46 -11
- small_fish_gui/batch/prompt.py +102 -41
- small_fish_gui/batch/update.py +26 -13
- small_fish_gui/batch/utils.py +1 -1
- small_fish_gui/gui/__init__.py +1 -0
- small_fish_gui/gui/_napari_widgets.py +418 -6
- small_fish_gui/gui/layout.py +332 -112
- small_fish_gui/gui/napari_visualiser.py +107 -22
- small_fish_gui/gui/prompts.py +161 -48
- small_fish_gui/gui/testing.ipynb +231 -24
- small_fish_gui/gui/tooltips.py +7 -1
- small_fish_gui/hints.py +23 -7
- small_fish_gui/interface/__init__.py +7 -1
- small_fish_gui/interface/default_settings.py +118 -0
- small_fish_gui/interface/image.py +43 -11
- small_fish_gui/interface/settings.json +50 -0
- small_fish_gui/interface/testing.ipynb +4354 -0
- small_fish_gui/interface/user_settings.py +96 -0
- small_fish_gui/main_menu.py +13 -1
- small_fish_gui/pipeline/{_signaltonoise.py → _bigfish_wrapers.py} +59 -7
- small_fish_gui/pipeline/_colocalisation.py +23 -24
- small_fish_gui/pipeline/_preprocess.py +46 -32
- small_fish_gui/pipeline/actions.py +48 -5
- small_fish_gui/pipeline/detection.py +71 -141
- small_fish_gui/pipeline/segmentation.py +360 -268
- small_fish_gui/pipeline/spots.py +3 -3
- small_fish_gui/pipeline/utils.py +5 -1
- small_fish_gui/README.md → small_fish_gui-2.0.3.dist-info/METADATA +50 -2
- small_fish_gui-2.0.3.dist-info/RECORD +46 -0
- {small_fish_gui-2.0.1.dist-info → small_fish_gui-2.0.3.dist-info}/WHEEL +1 -1
- small_fish_gui/.github/workflows/python-publish.yml +0 -39
- small_fish_gui/LICENSE +0 -24
- small_fish_gui/batch/values.txt +0 -65
- small_fish_gui/default_values.py +0 -51
- small_fish_gui/gui/screenshot/general_help_screenshot.png +0 -0
- small_fish_gui/gui/screenshot/mapping_help_screenshot.png +0 -0
- small_fish_gui/gui/screenshot/segmentation_help_screenshot.png +0 -0
- small_fish_gui/illustrations/DetectionVitrine_filtre.png +0 -0
- small_fish_gui/illustrations/DetectionVitrine_signal.png +0 -0
- small_fish_gui/illustrations/FocciVitrine.png +0 -0
- small_fish_gui/illustrations/FocciVitrine_no_spots.png +0 -0
- small_fish_gui/illustrations/Segmentation2D.png +0 -0
- small_fish_gui/illustrations/Segmentation2D_with_labels.png +0 -0
- small_fish_gui/logo.png +0 -0
- small_fish_gui/pipeline/testing.ipynb +0 -3636
- small_fish_gui/requirements.txt +0 -19
- small_fish_gui-2.0.1.dist-info/METADATA +0 -75
- small_fish_gui-2.0.1.dist-info/RECORD +0 -59
- {small_fish_gui-2.0.1.dist-info → small_fish_gui-2.0.3.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,14 +1,29 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Submodule containing custom class for napari widgets
|
|
3
3
|
"""
|
|
4
|
+
import os
|
|
4
5
|
import numpy as np
|
|
5
6
|
import pandas as pd
|
|
6
7
|
import bigfish.detection as detection
|
|
7
|
-
|
|
8
|
+
import bigfish.stack as stack
|
|
9
|
+
from skimage.segmentation import find_boundaries
|
|
10
|
+
from ..pipeline._bigfish_wrapers import _apply_log_filter, _local_maxima_mask
|
|
11
|
+
|
|
12
|
+
from napari.layers import Labels, Points, Image
|
|
13
|
+
from napari.utils.events import Event, EmitterGroup
|
|
8
14
|
from magicgui import magicgui
|
|
15
|
+
from magicgui.widgets import SpinBox, Container
|
|
16
|
+
from bigfish.detection import spots_thresholding, automated_threshold_setting
|
|
17
|
+
from napari.types import LayerDataTuple
|
|
9
18
|
|
|
10
19
|
from abc import ABC, abstractmethod
|
|
11
|
-
from typing import Tuple
|
|
20
|
+
from typing import Tuple, List
|
|
21
|
+
from ..utils import compute_anisotropy_coef
|
|
22
|
+
|
|
23
|
+
from AF_eraser import remove_autofluorescence_RANSACfit
|
|
24
|
+
from pathlib import Path
|
|
25
|
+
from ..interface import open_image
|
|
26
|
+
|
|
12
27
|
|
|
13
28
|
class NapariWidget(ABC) :
|
|
14
29
|
"""
|
|
@@ -25,6 +40,8 @@ class NapariWidget(ABC) :
|
|
|
25
40
|
"""
|
|
26
41
|
pass
|
|
27
42
|
|
|
43
|
+
# Corrector widgets
|
|
44
|
+
|
|
28
45
|
class ClusterWidget(NapariWidget) :
|
|
29
46
|
"""
|
|
30
47
|
Widget for clusters interaction are all init with cluster_layer and single_layer
|
|
@@ -262,9 +279,6 @@ class ClusterMerger(ClusterWidget) :
|
|
|
262
279
|
|
|
263
280
|
return merge_cluster
|
|
264
281
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
282
|
class ClusterUpdater(NapariWidget) :
|
|
269
283
|
"""
|
|
270
284
|
Relaunch clustering algorithm taking into consideration new spots, new clusters and deleted clusters.
|
|
@@ -510,4 +524,402 @@ class ClusterCleaner(ClusterWizard) :
|
|
|
510
524
|
self.cluster_layer.refresh()
|
|
511
525
|
|
|
512
526
|
self.cluster_layer.events.features.connect(delete_empty_cluster)
|
|
513
|
-
|
|
527
|
+
|
|
528
|
+
|
|
529
|
+
|
|
530
|
+
#Detection widgets
|
|
531
|
+
class BackgroundRemover(NapariWidget) :
|
|
532
|
+
def __init__(
|
|
533
|
+
self,
|
|
534
|
+
signal : Image,
|
|
535
|
+
voxel_size : tuple,
|
|
536
|
+
other_image : np.ndarray = None,
|
|
537
|
+
) :
|
|
538
|
+
|
|
539
|
+
self.other_image = other_image
|
|
540
|
+
self.signal_layer = signal
|
|
541
|
+
self.signal_data_raw = np.array(signal.data)
|
|
542
|
+
self.voxel_size = voxel_size
|
|
543
|
+
self.scale = compute_anisotropy_coef(self.voxel_size)
|
|
544
|
+
|
|
545
|
+
self.signal_args = {
|
|
546
|
+
"name" : "raw signal",
|
|
547
|
+
"colormap" : 'green',
|
|
548
|
+
"scale" : self.scale,
|
|
549
|
+
"blending" : 'additive'
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
self.events = EmitterGroup(source=self.signal_layer, auto_connect=False, background_substraction_event = None)
|
|
553
|
+
|
|
554
|
+
super().__init__()
|
|
555
|
+
if self.other_image is None : self.disable_channel() #Image stack is None when image stack is not is_multichannel
|
|
556
|
+
self.reset_widget = self._create_reset_button()
|
|
557
|
+
|
|
558
|
+
def disable_channel(self) :
|
|
559
|
+
self.widget.channel.enabled = False
|
|
560
|
+
|
|
561
|
+
def _create_widget(self) :
|
|
562
|
+
@magicgui(
|
|
563
|
+
channel = {'min' : 0, 'max' : 0 if self.other_image is None else self.other_image.shape[0] - 1},
|
|
564
|
+
max_trial = {'min' : 0},
|
|
565
|
+
)
|
|
566
|
+
def remove_background(
|
|
567
|
+
background_path : Path,
|
|
568
|
+
channel : int,
|
|
569
|
+
max_trial : int = 100,
|
|
570
|
+
)-> LayerDataTuple :
|
|
571
|
+
|
|
572
|
+
print("Substracting background ...", end="", flush=True)
|
|
573
|
+
self.gui = remove_background
|
|
574
|
+
|
|
575
|
+
if os.path.isfile(background_path) :
|
|
576
|
+
background = open_image(str(background_path))
|
|
577
|
+
elif self.other_image is None :
|
|
578
|
+
raise FileNotFoundError(f"{background_path} is not a valid file.")
|
|
579
|
+
else :
|
|
580
|
+
background = self.other_image[channel]
|
|
581
|
+
if not background.shape == self.signal_data_raw.shape : raise ValueError(f"Shape missmatch between signal and background : {self.signal_data_raw.shape} ; {background.shape}")
|
|
582
|
+
|
|
583
|
+
result, score = remove_autofluorescence_RANSACfit(
|
|
584
|
+
signal=self.signal_data_raw.copy(),
|
|
585
|
+
background=background,
|
|
586
|
+
max_trials=max_trial
|
|
587
|
+
)
|
|
588
|
+
|
|
589
|
+
print("\rBackground substraction done.")
|
|
590
|
+
self.events.background_substraction_event(new_signal_array = result)
|
|
591
|
+
|
|
592
|
+
return (result, self.signal_args, 'image')
|
|
593
|
+
return remove_background
|
|
594
|
+
|
|
595
|
+
def _create_reset_button(self) :
|
|
596
|
+
|
|
597
|
+
@magicgui(call_button= "Reset signal")
|
|
598
|
+
def reset_signal() -> LayerDataTuple :
|
|
599
|
+
self.events.background_substraction_event(new_signal_array = self.signal_data_raw)
|
|
600
|
+
return (self.signal_data_raw, self.signal_args, 'image')
|
|
601
|
+
return reset_signal
|
|
602
|
+
|
|
603
|
+
|
|
604
|
+
class SpotDetector(NapariWidget) :
|
|
605
|
+
"""
|
|
606
|
+
Widget aimed at helping user to set detection parameters : threshold, spot radius and so on...
|
|
607
|
+
"""
|
|
608
|
+
|
|
609
|
+
def __init__(
|
|
610
|
+
self,
|
|
611
|
+
image: np.ndarray,
|
|
612
|
+
default_threshold : int,
|
|
613
|
+
default_spot_size : tuple,
|
|
614
|
+
default_kernel_size : tuple,
|
|
615
|
+
default_min_distance : tuple,
|
|
616
|
+
voxel_size : tuple,
|
|
617
|
+
background_remover_instance : BackgroundRemover,
|
|
618
|
+
) :
|
|
619
|
+
|
|
620
|
+
self.image = image
|
|
621
|
+
self.voxel_size = voxel_size
|
|
622
|
+
self.dim = len(voxel_size)
|
|
623
|
+
self.default_threshold = default_threshold
|
|
624
|
+
self.spot_radius = default_spot_size
|
|
625
|
+
self.kernel_size = default_kernel_size
|
|
626
|
+
self.min_distance = default_min_distance
|
|
627
|
+
self._update_filtered_image()
|
|
628
|
+
self.maximum_threshold = self.filtered_image.max()
|
|
629
|
+
self.do_update = False
|
|
630
|
+
|
|
631
|
+
super().__init__()
|
|
632
|
+
background_remover_instance.events.background_substraction_event.connect(self.on_background_updated)
|
|
633
|
+
|
|
634
|
+
def _update_filtered_image(self) :
|
|
635
|
+
|
|
636
|
+
print("Re-computing filtered image with new parameters : ...", end="", flush=True)
|
|
637
|
+
self.filtered_image = _apply_log_filter(
|
|
638
|
+
image=self.image,
|
|
639
|
+
voxel_size=self.voxel_size,
|
|
640
|
+
spot_radius=self.spot_radius,
|
|
641
|
+
log_kernel_size=self.kernel_size
|
|
642
|
+
)
|
|
643
|
+
print("\rRe-computing filtered image with new parameters : done")
|
|
644
|
+
|
|
645
|
+
self.local_maxima = _local_maxima_mask(
|
|
646
|
+
image_filtered=self.filtered_image,
|
|
647
|
+
voxel_size=self.voxel_size,
|
|
648
|
+
spot_radius=self.spot_radius,
|
|
649
|
+
minimum_distance=self.min_distance
|
|
650
|
+
)
|
|
651
|
+
|
|
652
|
+
def _create_widget(self) :
|
|
653
|
+
|
|
654
|
+
dim = len(self.voxel_size)
|
|
655
|
+
if dim == 2 :
|
|
656
|
+
tuple_hint = Tuple[int,int]
|
|
657
|
+
else :
|
|
658
|
+
tuple_hint = Tuple[int,int,int]
|
|
659
|
+
|
|
660
|
+
if not self.default_threshold is None :
|
|
661
|
+
default_threshold = min(self.default_threshold, self.filtered_image.max())
|
|
662
|
+
else :
|
|
663
|
+
default_threshold = None
|
|
664
|
+
|
|
665
|
+
@magicgui(
|
|
666
|
+
threshold = {"widget_type" : SpinBox, "min" : 0, "value" : default_threshold, "max" : self.filtered_image.max() + 1},
|
|
667
|
+
spot_radius = {"label" : "spot radius(zyx)", "value" : self.spot_radius},
|
|
668
|
+
kernel_size = {"label" : "LoG kernel size(zyx)"},
|
|
669
|
+
minimum_distance = {"label" : "Distance min between spots"},
|
|
670
|
+
)
|
|
671
|
+
def find_spots(
|
|
672
|
+
threshold : int,
|
|
673
|
+
spot_radius : tuple_hint,
|
|
674
|
+
kernel_size : tuple_hint,
|
|
675
|
+
minimum_distance : tuple_hint,
|
|
676
|
+
) -> List[LayerDataTuple] :
|
|
677
|
+
|
|
678
|
+
if (np.array(spot_radius) < 0).any() :
|
|
679
|
+
raise ValueError("Spot radius : set value > 0 (0 to ignore argument)")
|
|
680
|
+
|
|
681
|
+
if (np.array(kernel_size) < 0).any() :
|
|
682
|
+
raise ValueError("Spot radius : set value > 0 (0 to ignore argument)")
|
|
683
|
+
|
|
684
|
+
if (np.array(minimum_distance) < 0).any() :
|
|
685
|
+
raise ValueError("Spot radius : set value > 0 (0 to ignore argument)")
|
|
686
|
+
|
|
687
|
+
if isinstance(spot_radius, tuple) :
|
|
688
|
+
if not all(spot_radius) : spot_radius = None #any value set to 0
|
|
689
|
+
if isinstance(kernel_size, tuple) :
|
|
690
|
+
if not all(kernel_size) : kernel_size = None #any value set to 0
|
|
691
|
+
if isinstance(minimum_distance, tuple) :
|
|
692
|
+
if not all(minimum_distance) : minimum_distance = None #any value set to 0
|
|
693
|
+
|
|
694
|
+
if spot_radius != self.spot_radius :
|
|
695
|
+
self.spot_radius = spot_radius
|
|
696
|
+
self.do_update = True
|
|
697
|
+
if kernel_size != self.kernel_size :
|
|
698
|
+
self.kernel_size = kernel_size
|
|
699
|
+
self.do_update = True
|
|
700
|
+
if minimum_distance != self.min_distance :
|
|
701
|
+
self.min_distance = minimum_distance
|
|
702
|
+
self.do_update = True
|
|
703
|
+
|
|
704
|
+
try :
|
|
705
|
+
if self.do_update :
|
|
706
|
+
self._update_filtered_image()
|
|
707
|
+
self.do_update = False
|
|
708
|
+
self.widget.threshold.max = self.filtered_image.max() + 1
|
|
709
|
+
|
|
710
|
+
print("Computing automated threshold : ...", end="", flush=True)
|
|
711
|
+
if threshold == 0 :
|
|
712
|
+
threshold = automated_threshold_setting(
|
|
713
|
+
self.filtered_image,
|
|
714
|
+
mask_local_max=self.local_maxima
|
|
715
|
+
)
|
|
716
|
+
self.widget.threshold.value = threshold
|
|
717
|
+
print("\rComputing automated threshold : done.")
|
|
718
|
+
|
|
719
|
+
spots = spots_thresholding(
|
|
720
|
+
image=self.filtered_image,
|
|
721
|
+
mask_local_max=self.local_maxima,
|
|
722
|
+
threshold=threshold
|
|
723
|
+
)[0]
|
|
724
|
+
except ValueError as e :
|
|
725
|
+
print(str(e))
|
|
726
|
+
|
|
727
|
+
|
|
728
|
+
scale = compute_anisotropy_coef(self.voxel_size)
|
|
729
|
+
|
|
730
|
+
spot_layer_args = {
|
|
731
|
+
'size': 5,
|
|
732
|
+
'scale' : scale,
|
|
733
|
+
'face_color' : 'transparent',
|
|
734
|
+
'border_color' : 'red',
|
|
735
|
+
'symbol' : 'disc',
|
|
736
|
+
'opacity' : 0.7,
|
|
737
|
+
'blending' : 'translucent',
|
|
738
|
+
'name': 'single spots',
|
|
739
|
+
'visible' : True,
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
filtered_image_layer_args = {
|
|
743
|
+
"colormap" : 'gray',
|
|
744
|
+
"scale" : scale,
|
|
745
|
+
"blending" : 'additive',
|
|
746
|
+
"name" : "filtered image"
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
return [
|
|
750
|
+
(self.filtered_image, filtered_image_layer_args, 'image'),
|
|
751
|
+
(spots, spot_layer_args, 'points')
|
|
752
|
+
]
|
|
753
|
+
|
|
754
|
+
return find_spots
|
|
755
|
+
|
|
756
|
+
def on_background_updated(self, event):
|
|
757
|
+
print("Background was updated — recomputing filtered image...")
|
|
758
|
+
self.image = event.new_signal_array
|
|
759
|
+
self.do_update = True
|
|
760
|
+
self.widget()
|
|
761
|
+
|
|
762
|
+
def get_detection_parameters(self) :
|
|
763
|
+
detection_parameters = {"threshold" : self.widget.threshold.value}
|
|
764
|
+
if self.spot_radius is not None :
|
|
765
|
+
detection_parameters.update({
|
|
766
|
+
"spot_size" : self.spot_radius,
|
|
767
|
+
"spot_size_z" : self.spot_radius[0] if self.dim == 3 else None,
|
|
768
|
+
"spot_size_y" : self.spot_radius[0 + (self.dim==3)],
|
|
769
|
+
"spot_size_x" : self.spot_radius[1 + (self.dim==3)]
|
|
770
|
+
})
|
|
771
|
+
if self.kernel_size is not None :
|
|
772
|
+
detection_parameters.update({
|
|
773
|
+
"log_kernel_size" : self.kernel_size,
|
|
774
|
+
"log_kernel_size_z" : self.kernel_size[0] if self.dim == 3 else None,
|
|
775
|
+
"log_kernel_size_y" : self.kernel_size[0 + (self.dim==3)],
|
|
776
|
+
"log_kernel_size_x" : self.kernel_size[1 + (self.dim==3)]
|
|
777
|
+
})
|
|
778
|
+
if self.min_distance is not None :
|
|
779
|
+
detection_parameters.update({
|
|
780
|
+
"minimum_distance" : self.min_distance,
|
|
781
|
+
"minimum_distance" : self.min_distance[0] if self.dim == 3 else None,
|
|
782
|
+
"minimum_distance" : self.min_distance[0 + (self.dim==3)],
|
|
783
|
+
"minimum_distance" : self.min_distance[1 + (self.dim==3)],
|
|
784
|
+
})
|
|
785
|
+
|
|
786
|
+
return detection_parameters
|
|
787
|
+
|
|
788
|
+
|
|
789
|
+
|
|
790
|
+
|
|
791
|
+
|
|
792
|
+
class DenseRegionDeconvolver(NapariWidget) :
|
|
793
|
+
"""
|
|
794
|
+
Widget for interactive detection. Create 2 layes : Labels layer representing dense region that could be deconvoluted and Points layer with deconvoluted spots
|
|
795
|
+
"""
|
|
796
|
+
def __init__(
|
|
797
|
+
self,
|
|
798
|
+
image : Image,
|
|
799
|
+
spots : Points,
|
|
800
|
+
alpha : float,
|
|
801
|
+
beta : float,
|
|
802
|
+
gamma : float,
|
|
803
|
+
spot_radius : tuple,
|
|
804
|
+
kernel_size : tuple,
|
|
805
|
+
voxel_size : tuple
|
|
806
|
+
) :
|
|
807
|
+
|
|
808
|
+
self.image = image
|
|
809
|
+
self.alpha = alpha
|
|
810
|
+
self.beta = beta
|
|
811
|
+
self.gamma = gamma
|
|
812
|
+
self.spots = spots
|
|
813
|
+
self.spot_radius = spot_radius
|
|
814
|
+
self.kernel_size = kernel_size
|
|
815
|
+
self.voxel_size = voxel_size
|
|
816
|
+
self.update_dense_regions()
|
|
817
|
+
super().__init__()
|
|
818
|
+
|
|
819
|
+
def update_dense_regions(self) :
|
|
820
|
+
dense_regions, spot_out_regions,max_size = detection.get_dense_region(
|
|
821
|
+
image=self.image.data,
|
|
822
|
+
spots=self.spots.data,
|
|
823
|
+
voxel_size = self.voxel_size,
|
|
824
|
+
beta=self.beta,
|
|
825
|
+
spot_radius=self.spot_radius
|
|
826
|
+
)
|
|
827
|
+
del spot_out_regions,max_size
|
|
828
|
+
|
|
829
|
+
mask = np.zeros(shape=self.image.data.shape, dtype= np.int16)
|
|
830
|
+
for label, region in enumerate(dense_regions) :
|
|
831
|
+
reg_im = region.image
|
|
832
|
+
coordinates = np.argwhere(reg_im)
|
|
833
|
+
z,y,x = coordinates.T
|
|
834
|
+
min_z,min_y,min_x,*_ = region.bbox
|
|
835
|
+
z += min_z
|
|
836
|
+
y += min_y
|
|
837
|
+
x += min_x
|
|
838
|
+
|
|
839
|
+
mask[z,y,x] = label + 1
|
|
840
|
+
|
|
841
|
+
self.dense_regions = mask
|
|
842
|
+
|
|
843
|
+
def _create_widget(self) :
|
|
844
|
+
|
|
845
|
+
dim = len(self.voxel_size)
|
|
846
|
+
tuple_hint = Tuple[int,int] if dim == 2 else Tuple[int,int,int]
|
|
847
|
+
tuple_dummy = tuple(0 for i in range(dim))
|
|
848
|
+
|
|
849
|
+
@magicgui
|
|
850
|
+
def dense_region_deconvolution(
|
|
851
|
+
alpha : float = self.alpha,
|
|
852
|
+
beta : float = self.beta,
|
|
853
|
+
gamma : float = self.gamma,
|
|
854
|
+
spot_radius : tuple_hint = tuple_dummy if self.spot_radius is None else self.spot_radius,
|
|
855
|
+
kernel_size : tuple_hint = tuple_dummy if self.kernel_size is None else self.kernel_size,
|
|
856
|
+
) -> List[LayerDataTuple] :
|
|
857
|
+
|
|
858
|
+
if (np.array(spot_radius) < 0).any() :
|
|
859
|
+
raise ValueError("Spot radius : set value > 0 (0 to ignore argument)")
|
|
860
|
+
if (np.array(kernel_size) < 0).any() :
|
|
861
|
+
raise ValueError("kernel size : set value > 0 (0 to ignore argument)")
|
|
862
|
+
|
|
863
|
+
if isinstance(spot_radius,tuple) :
|
|
864
|
+
if not all(spot_radius) : spot_radius = None #any value set to 0
|
|
865
|
+
if isinstance(kernel_size,tuple) :
|
|
866
|
+
if not all(kernel_size) : kernel_size = None #any value set to 0
|
|
867
|
+
|
|
868
|
+
self.do_update = False
|
|
869
|
+
if spot_radius != self.spot_radius :
|
|
870
|
+
self.spot_radius = spot_radius
|
|
871
|
+
self.do_update = True
|
|
872
|
+
if beta != self.beta :
|
|
873
|
+
self.beta = beta
|
|
874
|
+
self.do_update=True
|
|
875
|
+
if self.do_update :
|
|
876
|
+
print("Updating dense regions...", end="", flush=True)
|
|
877
|
+
self.update_dense_regions()
|
|
878
|
+
print("\rUpdating dense regions : done.")
|
|
879
|
+
self.alpha = alpha
|
|
880
|
+
self.gamma = gamma
|
|
881
|
+
self.kernel_size = kernel_size
|
|
882
|
+
|
|
883
|
+
print("Decomposing dense regions...", end="", flush=True)
|
|
884
|
+
spots, _dense_region, _reference_spot = detection.decompose_dense(
|
|
885
|
+
image= self.image.data,
|
|
886
|
+
spots= self.spots.data,
|
|
887
|
+
voxel_size=self.voxel_size,
|
|
888
|
+
spot_radius=self.spot_radius,
|
|
889
|
+
kernel_size=self.kernel_size,
|
|
890
|
+
alpha=self.alpha,
|
|
891
|
+
beta=self.beta,
|
|
892
|
+
gamma=self.gamma
|
|
893
|
+
)
|
|
894
|
+
print("\rDecomposing dense regions : done")
|
|
895
|
+
del _dense_region, _reference_spot
|
|
896
|
+
|
|
897
|
+
scale = compute_anisotropy_coef(self.voxel_size)
|
|
898
|
+
spot_layer_args = {
|
|
899
|
+
'size': 5,
|
|
900
|
+
'scale' : scale,
|
|
901
|
+
'face_color' : 'transparent',
|
|
902
|
+
'border_color' : 'blue',
|
|
903
|
+
'symbol' : 'disc',
|
|
904
|
+
'opacity' : 0.7,
|
|
905
|
+
'blending' : 'translucent',
|
|
906
|
+
'name': 'decovoluted spots',
|
|
907
|
+
'visible' : True,
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
dense_region_args = {
|
|
911
|
+
"scale" : scale,
|
|
912
|
+
"name": "Dense regions",
|
|
913
|
+
"colormap" : ["red"] * self.dense_regions.max()
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
return [(self.dense_regions, dense_region_args, 'labels'), (spots, spot_layer_args, 'points')]
|
|
917
|
+
return dense_region_deconvolution
|
|
918
|
+
|
|
919
|
+
def get_detection_parameters(self) :
|
|
920
|
+
return {
|
|
921
|
+
"alpha" : self.alpha,
|
|
922
|
+
"beta" : self.beta,
|
|
923
|
+
"gamma" : self.gamma
|
|
924
|
+
}
|
|
925
|
+
|