• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

angelolab / cell_classification / 5943061665

22 Aug 2023 07:11PM UTC coverage: 79.006% (-2.4%) from 81.434%
5943061665

Pull #65

github

web-flow
Merge 950cf388d into cbd1d19a3
Pull Request #65: Prediction notebook

566 of 735 branches covered (77.01%)

Branch coverage included in aggregate %.

287 of 287 new or added lines in 3 files covered. (100.0%)

1357 of 1699 relevant lines covered (79.87%)

0.8 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/cell_classification/viewer_widget.py
1
import os
×
2
import ipywidgets as widgets
×
3
from IPython.display import display
×
4
from io import BytesIO
×
5
from skimage import io
×
6
from copy import copy
×
7
import numpy as np
×
8
from natsort import natsorted
×
9

10

11
class NimbusViewer(object):
×
12
    def __init__(self, input_dir, output_dir, img_width='600px'):
×
13
        """Viewer for Nimbus application.
14
        Args:
15
            input_dir (str): Path to directory containing individual channels of multiplexed images
16
            output_dir (str): Path to directory containing output of Nimbus application.
17
            img_width (str): Width of images in viewer.
18
        """
19
        self.image_width = img_width
×
20
        self.input_dir = input_dir
×
21
        self.output_dir = output_dir
×
22
        self.fov_names = [os.path.basename(p) for p in os.listdir(output_dir) if \
×
23
                          os.path.isdir(os.path.join(output_dir, p))]
24
        self.fov_names = natsorted(self.fov_names)
×
25
        self.update_button = widgets.Button(description="Update Image")
×
26
        self.update_button.on_click(self.update_button_click)
×
27

28
        self.fov_select = widgets.Select(
×
29
            options=self.fov_names,
30
            description='FOV:',
31
            disabled=False
32
        )
33
        self.fov_select.observe(self.select_fov, names='value')
×
34

35
        self.red_select = widgets.Select(
×
36
            options=[],
37
            description='Red:',
38
            disabled=False
39
        )
40
        self.green_select = widgets.Select(
×
41
            options=[],
42
            description='Green:',
43
            disabled=False
44
        )
45
        self.blue_select = widgets.Select(
×
46
            options=[],
47
            description='Blue:',
48
            disabled=False
49
        )
50
        self.input_image = widgets.Image()
×
51
        self.output_image = widgets.Image()
×
52

53
    def select_fov(self, change):
×
54
        """Selects fov to display.
55
        Args:
56
            change (dict): Change dictionary from ipywidgets.
57
        """
58
        fov_path = os.path.join(self.output_dir, self.fov_select.value)
×
59
        channels = [
×
60
            ch for ch in os.listdir(fov_path) if os.path.isfile(os.path.join(fov_path, ch))
61
        ]
62
        self.red_select.options = natsorted(channels)
×
63
        self.green_select.options = natsorted(channels)
×
64
        self.blue_select.options = natsorted(channels)
×
65

66
    def create_composite_image(self, path_dict):
×
67
        """Creates composite image from input paths.
68
        Args:
69
            path_dict (dict): Dictionary of paths to images.
70
        Returns:
71
            composite_image (np.array): Composite image.
72
        """
73
        output_image = []
×
74
        img = None
×
75
        for k, p in path_dict.items():
×
76
            if p:
×
77
                img = io.imread(p)
×
78
                output_image.append(img)
×
79
            if p is None:
×
80
                non_none = [p for p in path_dict.values() if p]
×
81
                if not img:
×
82
                    img = io.imread(non_none[0])
×
83
                output_image.append(img*0)
×
84

85
        composite_image = np.stack(output_image, axis=-1)
×
86
        return composite_image
×
87

88
    def layout(self):
×
89
        """Creates layout for viewer."""
90
        channel_selectors = widgets.VBox([
×
91
            self.red_select,
92
            self.green_select,
93
            self.blue_select
94
        ])
95
        self.input_image.layout.width = self.image_width
×
96
        self.output_image.layout.width = self.image_width
×
97
        viewer_html = widgets.HTML("<h2>Select files</h2>")
×
98
        input_html = widgets.HTML("<h2>Input</h2>")
×
99
        output_html = widgets.HTML("<h2>Nimbus Output</h2>")
×
100

101
        layout = widgets.HBox([
×
102
            widgets.VBox([
103
                viewer_html,
104
                self.fov_select,
105
                channel_selectors,
106
                self.update_button
107
            ]),
108
        widgets.VBox([
109
            input_html,
110
            self.input_image
111
        ]),
112
        widgets.VBox([
113
            output_html,
114
            self.output_image
115
        ])
116
        ])
117
        display(layout)
×
118

119
    def search_for_similar(self, select_value):
×
120
        """Searches for similar filename in input directory.
121
        Args:
122
            select_value (str): Filename to search for.
123
        Returns:
124
            similar_path (str): Path to similar filename.
125
        """
126
        in_f_path = os.path.join(self.input_dir, self.fov_select.value)
×
127
        # search for similar filename in in_f_path
128
        in_f_files = [
×
129
            f for f in os.listdir(in_f_path) if os.path.isfile(os.path.join(in_f_path, f))
130
        ]
131
        similar_path = None
×
132
        for f in in_f_files:
×
133
            if select_value.split(".")[0]+"." in f:
×
134
                similar_path = os.path.join(self.input_dir, self.fov_select.value, f)
×
135
        return similar_path
×
136

137
    def update_img(self, image_viewer, composite_image):
×
138
        """Updates image in viewer by saving it as png and loading it with the viewer widget.
139
        Args:
140
            image_viewer (ipywidgets.Image): Image widget to update.
141
            composite_image (np.array): Composite image to display.
142
        """
143
        # Convert composite image to bytes and assign it to the output_image widget
144
        with BytesIO() as output_buffer:
×
145
            io.imsave(output_buffer, composite_image, format="png")
×
146
            output_buffer.seek(0)
×
147
            image_viewer.value = output_buffer.read()
×
148

149
    def update_composite(self):
×
150
        """Updates composite image in viewer."""
151
        path_dict = {
×
152
            "red": None,
153
            "green": None,
154
            "blue": None
155
        }
156
        in_path_dict = copy(path_dict)
×
157
        if self.red_select.value:
×
158
            path_dict["red"] = os.path.join(
×
159
                self.output_dir, self.fov_select.value, self.red_select.value
160
            )
161
            in_path_dict["red"] = self.search_for_similar(self.red_select.value)
×
162
        if self.green_select.value:
×
163
            path_dict["green"] = os.path.join(
×
164
                self.output_dir, self.fov_select.value, self.green_select.value
165
            )
166
            in_path_dict["green"] = self.search_for_similar(self.green_select.value)
×
167
        if self.blue_select.value:
×
168
            path_dict["blue"] = os.path.join(
×
169
                self.output_dir, self.fov_select.value, self.blue_select.value
170
            )
171
            in_path_dict["blue"] = self.search_for_similar(self.blue_select.value)
×
172
        non_none = [p for p in path_dict.values() if p]
×
173
        if not non_none:
×
174
            return
×
175
        composite_image = self.create_composite_image(path_dict)
×
176
        in_composite_image = self.create_composite_image(in_path_dict)
×
177
        in_composite_image = in_composite_image / np.quantile(
×
178
            in_composite_image, 0.999, axis=(0,1)
179
        )
180
        in_composite_image = np.clip(in_composite_image*255, 0, 255).astype(np.uint8)
×
181
        # update image viewers
182
        self.update_img(self.input_image, in_composite_image)
×
183
        self.update_img(self.output_image, composite_image)
×
184

185
    def update_button_click(self, button):
×
186
        """Updates composite image in viewer when update button is clicked."""
187
        self.update_composite()
×
188
    
189
    def display(self):
×
190
        """Displays viewer."""
191
        self.select_fov(None)
×
192
        self.layout()
×
193
        self.update_composite() 
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc