Skip to content

Commit 4009690

Browse files
committed
1 parent bc24da1 commit 4009690

File tree

1 file changed

+140
-0
lines changed

1 file changed

+140
-0
lines changed
Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
#@ ImageJ ij
2+
3+
'''
4+
Note that this script requires a Python environment that includes StarDist and Cellpose
5+
StarDist currently only supports NumPy 1.x, which necessitates using TensorFlow 2.15 or earlier
6+
TensorFlow 2.15 itself requires python 3.11 or earlier
7+
8+
You can rebuild your Python environment by using:
9+
Edit > Options > Python…
10+
11+
The following configuration was used to develop this script:
12+
13+
--Conda dependencies--
14+
python=3.11
15+
numpy=1.26.4
16+
17+
--Pip dependencies--
18+
tensorflow==2.15
19+
cellpose==4.0.6
20+
stardist==0.9.0
21+
csbdeep==0.8.0
22+
'''
23+
24+
import sys
25+
import imagej.convert as convert
26+
import numpy as np
27+
import matplotlib.pyplot as plt
28+
from cellpose import models
29+
from csbdeep.utils import normalize
30+
from stardist.models import StarDist2D
31+
import scyjava as sj
32+
33+
def filter_index_image(narr:np.ndarray, min_size:int, max_size:int):
34+
"""
35+
Filter an index image's labels with a pixel size range.
36+
"""
37+
unique = np.unique(narr)
38+
for label in unique:
39+
if label == 0:
40+
# skip the background
41+
continue
42+
43+
# create a crop for each label
44+
bbox = get_bounding_box(np.where(narr == label))
45+
bbox_crop = narr[bbox[0]:bbox[2] + 1, bbox[1]:bbox[3] + 1].copy()
46+
bbox_crop[bbox_crop != label] = 0
47+
48+
# get the number of pixels in label
49+
bbox_crop = bbox_crop.astype(bool)
50+
label_size = np.sum(bbox_crop)
51+
52+
if not min_size <= label_size <= max_size:
53+
narr[narr == label] = 0
54+
55+
return narr
56+
57+
def get_bounding_box(indices: np.ndarray):
58+
"""
59+
Get the bounding box coordinates from a the label indices.
60+
"""
61+
# get min and max bounds of indices array
62+
min_row = np.min(indices[0])
63+
min_col = np.min(indices[1])
64+
max_row = np.max(indices[0])
65+
max_col = np.max(indices[1])
66+
67+
return (min_row, min_col, max_row, max_col)
68+
69+
# open image data and convert to Python from Java
70+
#TODO does this connection need to be closed?
71+
data = ij.io().open('https://media.imagej.net/pyimagej/3d/hela_a3g.tif')
72+
xdata = ij.py.from_java(data)
73+
74+
# show the first channel
75+
ij.ui().show("nucleus", ij.py.to_java(xdata[:, :, 0]))
76+
77+
# show the second channel
78+
ij.ui().show("cytoplasm", ij.py.to_java(xdata[:, :, 1] * 125))
79+
80+
# run StarDist on nuclei channel
81+
model = StarDist2D.from_pretrained('2D_versatile_fluo')
82+
nuc_labels, _ = model.predict_instances(normalize(xdata[:, :, 0]))
83+
84+
# run Cellpose on cytoplasm (grayscale)
85+
model = models.CellposeModel(gpu=False, model_type='cyto')
86+
ch = [0, 0]
87+
cyto_labels = model.eval(xdata[:, :, 1].data, channels=ch, diameter=72.1)
88+
89+
# show the stardist results
90+
ij.ui().show("StarDist results", ij.py.to_java(nuc_labels))
91+
ij.IJ.run("mpl-viridis", "");
92+
93+
# show the second channel
94+
ij.ui().show("Cellpose results", ij.py.to_java(cyto_labels[0]))
95+
ij.IJ.run("mpl-viridis", "");
96+
97+
# filter the stardist results and display
98+
filter_index_image(nuc_labels, 500, 10000)
99+
ij.ui().show("StarDist filtered", ij.py.to_java(nuc_labels))
100+
ij.IJ.run("mpl-viridis", "");
101+
102+
# ensure ROI Manager exists
103+
rm = ij.RoiManager.getInstance()
104+
if rm is None:
105+
ij.IJ.run("ROI Manager...")
106+
rm = ij.RoiManager.getInstance()
107+
108+
# Reset the ROI manager
109+
rm.reset()
110+
111+
# convert to ImgLib2 ROI in a ROITree
112+
nuc_roi_tree = convert.index_img_to_roi_tree(ij, nuc_labels)
113+
cyto_roi_tree = convert.index_img_to_roi_tree(ij, cyto_labels[0])
114+
115+
# print the contents of the ROITree (nuclear ROIs)
116+
len(nuc_roi_tree.children())
117+
for i in range(len(nuc_roi_tree.children())):
118+
print(nuc_roi_tree.children().get(i).data())
119+
120+
# display the input data, select channel 2 and enhance the contrast
121+
data_title = "hela_a3g.tif"
122+
ij.ui().show(data_title, data)
123+
imp = ij.WindowManager.getImage(data_title)
124+
imp.setC(2)
125+
ij.IJ.run(imp, "Enhance Contrast", "saturated=0.35")
126+
127+
# convert a single ImgLib2 roi to a legacy ImageJ ROI with the ConvertService.
128+
imglib_polygon_roi = nuc_roi_tree.children().get(0).data()
129+
ij_polygon_roi = ij.convert().convert(imglib_polygon_roi, sj.jimport('ij.gui.PolygonRoi'))
130+
print(type(ij_polygon_roi))
131+
132+
# convert index images to ImageJ ROI in RoiManager
133+
#TODO any way to color the selections? We can use Colors... but it appears to be global and the last one run wins
134+
#ij.IJ.run(imp, "Colors...", "foreground=blue background=black selection=red");
135+
convert.index_img_to_roi_manager(ij, nuc_labels)
136+
convert.index_img_to_roi_manager(ij, cyto_labels[0])
137+
138+
#TODO this pops an unnecessary display at the end but if I don't make it the last line the ROIs don't show
139+
rm.moveRoisToOverlay(imp)
140+
rm.runCommand(imp, "Show All")

0 commit comments

Comments
 (0)