Skip to content

Commit f3c51b8

Browse files
committed
Append color and scale bars to FLIM example
1 parent cfd86a1 commit f3c51b8

File tree

1 file changed

+102
-37
lines changed

1 file changed

+102
-37
lines changed

docs/ops/doc/examples/example_flim_analysis.rst

Lines changed: 102 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ In this example we will use SciJava Ops within Fiji to perform `FLIM`_ analysis,
66

77
.. image:: https://media.imagej.net/scijava-ops/1.0.0/flim_example_input.gif
88
:width: 49%
9-
.. image:: https://media.imagej.net/scijava-ops/1.0.0/flim_example_pseudocolored.png
9+
.. image:: https://media.imagej.net/scijava-ops/1.0.0/flim_example_pseudocolored_annotated.png
1010
:width: 49%
1111

12-
We use a sample of `FluoCells™ Prepared Slide #1`_, imaged by `Jenu Chacko`_ using `Openscan-LSM`_ and SPC180 electronics with multiphoton excitation and a 40x WI lens.
12+
We use a sample of `FluoCells™ Prepared Slide #1`_, imaged by `Jenu Chacko`_ using `Openscan-LSM`_ and SPC180 electronics with multiphoton excitation and a 40x WI lens. **Notably, the full field for this image is 130 microns in each axial dimension**.
1313

1414
FluoCells™ Prepared Slide #1 contains bovine pulmonary artery endothelial cells (BPAEC). MitoTracker™ Red CMXRos was used to stain the mitochondria in the live cells, with accumulation dependent upon membrane potential. Following fixation and permeabilization, F-actin was stained with Alexa Fluor™ 488 phalloidin, and the nuclei were counterstained with the blue-fluorescent DNA stain DAPI.
1515

@@ -36,17 +36,15 @@ Script execution requires a number of parameters, which may be useful for adapti
3636
| Bin Kernel Radius | 1 |
3737
+--------------------------------------+-------+
3838

39-
The script above will display the fit results, as well as a *pseudocolored* output image. To visualize , it should be contrasted using ImageJ's B&C plugin (``Ctrl + Shift + C``). Using that plugin, the minimum and maximum can be set by selecting the ``Set`` option, and providing ``0`` as the minimum and ``3`` as the maximum.
40-
41-
The results are shown in the panels below, and are described from left to right:
39+
The script above will display the fit results, as well as a *pseudocolored* output image. The results are shown in the panels below, and are described from left to right:
4240

4341
* The first initial fluorescence parameter A\ :subscript:`1`
4442

45-
* The first fluorescence lifetime τ\ :subscript:`1`.
43+
* The first fluorescence lifetime τ\ :subscript:`1` (contrasted using ImageJ's B&C plugin (``Ctrl + Shift + C``), by selecting the ``Set`` option and providing ``0`` as the minimum and ``3`` as the maximum).
4644

4745
* The pseudocolored result, an HSV image where
4846

49-
* Hue is a function of τ\ :subscript:`1`, where the function is a LUT
47+
* Hue and Saturation are a function of τ\ :subscript:`1`, where the function is a LUT provided optionally by the user. The LUT used by `TRI2`_ is used by default, and is also used explicitly in this use case.
5048

5149
* Value is a function of A\ :subscript:`1`
5250

@@ -59,29 +57,18 @@ The results are shown in the panels below, and are described from left to right:
5957
.. image:: https://media.imagej.net/scijava-ops/1.0.0/flim_example_pseudocolored.png
6058
:width: 32%
6159

62-
The pseudocolored result shows a clear separation of fluorophores, which could be segmented and further processed.
63-
64-
Subsampling Within ROIs
65-
-----------------------
66-
67-
Curve fitting can be an intensive process, requiring significant resources to process larger datasets. For this reason, there can be significant benefit in restricting computation to Regions of Interest (ROIs), and SciJava Ops FLIM allows ROIs to restrict computation for all fitting Ops.
68-
69-
The provided script allows users to specify ROIs by drawing selections using the ImageJ UI. These selections are converted to ImgLib2 ``RealMask`` objects, which are then optionally passed to the Op.
70-
71-
In the panels below, we show script execution with computation restricted to the area around a single cell. In the top left panel, we can see the original dataset, annotated with an elliptical selection using the ImageJ UI. In the top right, bottom left, and bottom right panels, we see the A\ :subscript:`1` component, τ\ :subscript:`1` component, and pseudocolored results, respectively, all limited to the area within the selection.
72-
73-
.. image:: https://media.imagej.net/scijava-ops/1.0.0/flim_example_input_roi.png
74-
:width: 49%
75-
76-
.. image:: https://media.imagej.net/scijava-ops/1.0.0/flim_example_a1_roi.png
77-
:width: 49%
7860

79-
.. image:: https://media.imagej.net/scijava-ops/1.0.0/flim_example_tau1_roi.png
80-
:width: 49%
61+
Additionally, the script outputs ``tLow`` and ``tHigh``, ``Double``\ s describing the 5th and 95th percentiles respectively, across all τ\ :subscript:`1`. Lifetime parameters outside of the range ``[tLow, tHigh]`` are clipped to the nearest bound in the pseudocolored image.
8162

82-
.. image:: https://media.imagej.net/scijava-ops/1.0.0/flim_example_pseudocolored_roi.png
83-
:width: 49%
63+
+--------------------------------------+---------------------+
64+
| Result | Value |
65+
+======================================+=====================+
66+
| ``tLow`` | 1.87000572681427 |
67+
+--------------------------------------+---------------------+
68+
| ``tHigh`` | 2.3314802646636963 |
69+
+--------------------------------------+---------------------+
8470

71+
The pseudocolored result shows a clear separation of fluorophores, which could be segmented and further processed.
8572

8673
.. tabs::
8774

@@ -90,17 +77,23 @@ In the panels below, we show script execution with computation restricted to the
9077
#@ OpEnvironment ops
9178
#@ ROIService roiService
9279
#@ Img input
93-
#@ Float (description="The total time (ns) (timeBase in metadata)", label = "Time Base") timeBase
94-
#@ Integer (description="The number of time bins (timeBins in metadata)", label = "Time Bins") timeBins
80+
#@ Float (description="The total time (ns) (timeBase in metadata)", label = "Time Base", value=12.5) timeBase
81+
#@ Integer (description="The number of time bins (timeBins in metadata)", label = "Time Bins", value=512) timeBins
9582
#@ Integer (description="The index of the lifetime axis (from metadata)", label = "Lifetime Axis", value=2) lifetimeAxis
96-
#@ Float (description="The minimal pixel intensity (across all time bins) threshold for fitting", label = "Intensity Threshold") iThresh
97-
#@ Integer (description="The radius of the binning kernel", label = "Bin Kernel Radius", value=0, min=0) kernelRad
83+
#@ Float (description="The minimal pixel intensity (across all time bins) threshold for fitting", label = "Intensity Threshold", value = 18) iThresh
84+
#@ Integer (description="The radius of the binning kernel", label = "Bin Kernel Radius", value=1, min=0) kernelRad
9885
#@OUTPUT Img A1
9986
#@OUTPUT Img Tau1
10087
#@OUTPUT Img pseudocolored
88+
#@OUTPUT Double tLow
89+
#@OUTPUT Double tHigh
10190

102-
import net.imglib2.roi.Regions
10391
import java.lang.System
92+
import net.imglib2.roi.Regions
93+
import net.imglib2.type.numeric.real.DoubleType
94+
95+
import org.scijava.ops.flim.FitParams
96+
import org.scijava.ops.flim.Pseudocolor
10497

10598
// Utility function to collapse all ROIs into a single mask for FLIM fitting
10699
def getMask() {
@@ -117,7 +110,6 @@ In the panels below, we show script execution with computation restricted to the
117110
return mask;
118111
}
119112

120-
import net.imglib2.type.numeric.real.DoubleType
121113
def getPercentile(img, mask, percentile) {
122114
if (mask != null) {
123115
img = Regions.sampleWithRealMask(mask, img)
@@ -132,7 +124,6 @@ In the panels below, we show script execution with computation restricted to the
132124
start = System.currentTimeMillis()
133125

134126
// The FitParams contain a set of reasonable defaults for FLIM curve fitting
135-
import org.scijava.ops.flim.FitParams
136127
param = new FitParams()
137128
param.transMap = input
138129
param.ltAxis = lifetimeAxis
@@ -151,17 +142,91 @@ In the panels below, we show script execution with computation restricted to the
151142
Tau1 = ops.op("transform.hyperSliceView").input(fittedImg, lifetimeAxis, 2).apply()
152143

153144
// Finally, generate a pseudocolored result
154-
cMin = getPercentile(Tau1, mask, 5.0)
155-
cMax = getPercentile(Tau1, mask, 95.0)
156-
pseudocolored = ops.op("flim.pseudocolor").input(lma, cMin, cMax).apply()
145+
tLow = getPercentile(Tau1, mask, 5.0)
146+
tHigh = getPercentile(Tau1, mask, 95.0)
147+
pseudocolored = ops.op("flim.pseudocolor").input(lma, tLow, tHigh, null, null, Pseudocolor.tri2()).apply()
157148

158149
end = System.currentTimeMillis()
159150
println("Finished fitting in " + (end - start) + " milliseconds")
160151

152+
Adding Calibration and Scale Bars
153+
---------------------------------
154+
155+
To attach quantitative meaning to the pseudocolored image, we must add calibration and scale bars. We add each within ImageJ using a second SciJava script using the following parameters. Note that ``tLow`` and ``tHigh`` are outputs from the previous script.
156+
157+
With 130 microns across each direction in the dataset, we have 512/130~3.938 pixels per micron.
158+
159+
+--------------------------------------+---------------------+
160+
| Parameter | Value |
161+
+======================================+=====================+
162+
| tLow | 1.87000572681427 |
163+
+--------------------------------------+---------------------+
164+
| tHigh | 2.3314802646636963 |
165+
+--------------------------------------+---------------------+
166+
| Pixels Per Micron | 3.938461538 |
167+
+--------------------------------------+---------------------+
168+
169+
The results are shown in the panels below. The left panel shows panel 56 of the original image, contrasted using ImageJ's Brightness and Contrast tool, and the right panel shows the **annotated**, pseudocolored results.
170+
171+
.. image:: https://media.imagej.net/scijava-ops/1.0.0/flim_example_input_56.png
172+
:width: 49%
173+
174+
.. image:: https://media.imagej.net/scijava-ops/1.0.0/flim_example_pseudocolored_annotated.png
175+
:width: 49%
176+
177+
.. tabs::
178+
179+
.. code-tab:: scijava-groovy
180+
181+
#@ ImagePlus Tau1
182+
#@ ImagePlus pseudocolored
183+
#@ Double (description="Lower bound of clip range in Tau1", label = "Tau Low", value = 1.87000572681427) tLow
184+
#@ Double (description="Upper bound of clip range in Tau1", label = "Tau High", value = 2.3314802646636963) tHigh
185+
#@ Double (description="The number of pixels per micron", label = "Pixels per Micron", value = 3.938461538) ppm
186+
187+
import org.scijava.ops.flim.Pseudocolor
188+
import ij.process.LUT
189+
import ij.IJ
190+
191+
// The pseudocolored image uses lifetime values between tLow and tHigh
192+
// for an accurate calibration bar, we must also restrict display
193+
// values to that range.
194+
Tau1 = Tau1.clone()
195+
Tau1.setDisplayRange(tLow, tHigh)
196+
197+
// Set the LUT & Calibration Bar
198+
rgb = Pseudocolor.tri2().getValues()
199+
lut = new LUT(rgb[0], rgb[1], rgb[2])
200+
Tau1.setLut(lut)
201+
IJ.run(Tau1, "Calibration Bar...", "location=[Upper Right] fill=Black label=Yellow number=5 decimal=2 font=12 zoom=1 overlay");
202+
203+
// Set the scale & Scale Bar
204+
IJ.run(Tau1, "Set Scale...", "distance=" + ppm + " known=1 unit=µm");
205+
IJ.run(Tau1, "Scale Bar...", "width=20 height=20 color=Yellow background=Black horizontal bold overlay");
206+
// Finally, copy the Overlay over to the pseudocolored image
207+
pseudocolored.setOverlay(Tau1.getOverlay())
208+
209+
Subsampling Within ROIs
210+
-----------------------
211+
212+
Curve fitting can be an intensive process, requiring significant resources to process larger datasets. For this reason, there can be significant benefit in restricting computation to Regions of Interest (ROIs), and SciJava Ops FLIM allows ROIs to restrict computation for all fitting Ops.
213+
214+
The provided script allows users to specify ROIs by drawing selections using the ImageJ UI. These selections are converted to ImgLib2 ``RealMask`` objects, which are then optionally passed to the Op.
215+
216+
In the panels below, we show the results of executing both scripts with computation restricted to the area around a single cell. The left panel shows slide 56 of the input data, annotated with an elliptical ROI drawn using ImageJ's elliptical selection tool and contrasted using ImageJ's Brightness and Contrast tool. The right panel shows the pseudocolored result, annotated with color and scale bars, with computation limited to the selected ellipse.
217+
218+
.. image:: https://media.imagej.net/scijava-ops/1.0.0/flim_example_input_56_roi.png
219+
:width: 49%
220+
221+
.. image:: https://media.imagej.net/scijava-ops/1.0.0/flim_example_pseudocolored_annotated_roi.png
222+
:width: 49%
223+
224+
161225
.. _`Bio-Formats` : https://www.openmicroscopy.org/bio-formats/
162226
.. _`FLIM` : https://en.wikipedia.org/wiki/Fluorescence-lifetime_imaging_microscopy
163227
.. _`FluoCells™ Prepared Slide #1` : https://www.thermofisher.com/order/catalog/product/F36924
164228
.. _`FRET` : https://en.wikipedia.org/wiki/F%C3%B6rster_resonance_energy_transfer
165229
.. _`Jenu Chacko` : https://loci.wisc.edu/staff/chacko-jenu/
166230
.. _`Levenberg-Marquardt algorithm` : https://en.wikipedia.org/wiki/Levenberg%E2%80%93Marquardt_algorithm
167231
.. _`Openscan-LSM` : https://github.com/openscan-lsm
232+
.. _`TRI2` : https://app.assembla.com/spaces/ATD_TRI/wiki/Home

0 commit comments

Comments
 (0)