|
| 1 | +============= |
| 2 | +FLIM Analysis |
| 3 | +============= |
| 4 | + |
| 5 | +In this example we will use SciJava Ops within Fiji to perform `FLIM`_ analysis, which is used in many situations including photosensitizer detection and `FRET`_ measurement. |
| 6 | + |
| 7 | +.. image:: https://media.imagej.net/scijava-ops/1.0.0/flim_example_input.gif |
| 8 | + :width: 49% |
| 9 | +.. image:: https://media.imagej.net/scijava-ops/1.0.0/flim_example_pseudocolored.png |
| 10 | + :width: 49% |
| 11 | + |
| 12 | +We use a sample of `FluoCells™ Prepared Slide #1`_, imaged by `Jenu Chacko <https://loci.wisc.edu/staff/chacko-jenu/>`_ using Openscan-LSM and SPwith multiphoton excitation and a 40x WI lens. |
| 13 | + |
| 14 | + 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. |
| 15 | + |
| 16 | +The sample data can be downloaded `here <https://media.imagej.net/scijava-ops/1.0.0/flim_example_data.sdt>`_ and can be loaded into Fiji with `Bio-Formats`_ using ``File → Open``. When presented with the ``Bio-Formats Import Options`` screen, it may be helpful to select ``Metadata viewing → Display metadata`` to determine values necessary for analysis. Then, select ``OK``. The data may take a minute to load. |
| 17 | + |
| 18 | +Within the script, the `Levenberg-Marquardt algorithm <https://en.wikipedia.org/wiki/Levenberg%E2%80%93Marquardt_algorithm>`_ fitting Op of SciJava Ops FLIM is used to fit the data. |
| 19 | + |
| 20 | +Basic analysis |
| 21 | +--------------------- |
| 22 | + |
| 23 | +Script execution requires a number of parameters, which may be useful for adapting this script to other datasets. For this dataset, we use the following values: |
| 24 | + |
| 25 | ++--------------------------------------+-------+ |
| 26 | +| Parameter | Value | |
| 27 | ++======================================+=======+ |
| 28 | +| Time Base | 12.5 | |
| 29 | ++--------------------------------------+-------+ |
| 30 | +| Time Bins | 256 | |
| 31 | ++--------------------------------------+-------+ |
| 32 | +| Lifetime Axis | 2 | |
| 33 | ++--------------------------------------+-------+ |
| 34 | +| Intensity Threshold | 18 | |
| 35 | ++--------------------------------------+-------+ |
| 36 | +| Bin Kernel Radius | 1 | |
| 37 | ++--------------------------------------+-------+ |
| 38 | + |
| 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: |
| 42 | + |
| 43 | +* The first initial fluorescence parameter A\ :subscript:`1` |
| 44 | + |
| 45 | +* The first fluorescence lifetime τ\ :subscript:`1`. |
| 46 | + |
| 47 | +* The pseudocolored result, an HSV image where |
| 48 | + |
| 49 | + * Hue is a function of τ\ :subscript:`1`, where the function is a LUT |
| 50 | + |
| 51 | + * Value is a function of A\ :subscript:`1` |
| 52 | + |
| 53 | +.. image:: https://media.imagej.net/scijava-ops/1.0.0/flim_example_a1.png |
| 54 | + :width: 32% |
| 55 | + |
| 56 | +.. image:: https://media.imagej.net/scijava-ops/1.0.0/flim_example_tau1.png |
| 57 | + :width: 32% |
| 58 | + |
| 59 | +.. image:: https://media.imagej.net/scijava-ops/1.0.0/flim_example_pseudocolored.png |
| 60 | + :width: 32% |
| 61 | + |
| 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% |
| 78 | + |
| 79 | +.. image:: https://media.imagej.net/scijava-ops/1.0.0/flim_example_tau1_roi.png |
| 80 | + :width: 49% |
| 81 | + |
| 82 | +.. image:: https://media.imagej.net/scijava-ops/1.0.0/flim_example_pseudocolored_roi.png |
| 83 | + :width: 49% |
| 84 | + |
| 85 | + |
| 86 | +.. tabs:: |
| 87 | + |
| 88 | + .. code-tab:: scijava-groovy |
| 89 | + |
| 90 | + #@ OpEnvironment ops |
| 91 | + #@ ROIService roiService |
| 92 | + #@ 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 |
| 95 | + #@ 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 |
| 98 | + #@OUTPUT Img A1 |
| 99 | + #@OUTPUT Img Tau1 |
| 100 | + #@OUTPUT Img pseudocolored |
| 101 | + |
| 102 | + import net.imglib2.roi.Regions |
| 103 | + import java.lang.System |
| 104 | + |
| 105 | + // Utility function to collapse all ROIs into a single mask for FLIM fitting |
| 106 | + def getMask() { |
| 107 | + // No ROIs |
| 108 | + if (!roiService.hasROIs(input)) { |
| 109 | + return null |
| 110 | + } |
| 111 | + // 1+ ROIs |
| 112 | + rois = roiService.getROIs(input) |
| 113 | + mask = rois.children()remove(0).data() |
| 114 | + for(roi: rois.children()) { |
| 115 | + mask = mask.or(roi.data()) |
| 116 | + } |
| 117 | + return mask; |
| 118 | + } |
| 119 | + |
| 120 | + import net.imglib2.type.numeric.real.DoubleType |
| 121 | + def getPercentile(img, mask, percentile) { |
| 122 | + if (mask != null) { |
| 123 | + img = Regions.sampleWithRealMask(mask, img) |
| 124 | + } |
| 125 | + return ops.op("stats.percentile").arity2() |
| 126 | + .input(img, percentile) |
| 127 | + .outType(DoubleType.class) |
| 128 | + .apply() |
| 129 | + .getRealFloat() |
| 130 | + } |
| 131 | + |
| 132 | + start = System.currentTimeMillis() |
| 133 | + |
| 134 | + // The FitParams contain a set of reasonable defaults for FLIM curve fitting |
| 135 | + import org.scijava.ops.flim.FitParams |
| 136 | + param = new FitParams() |
| 137 | + param.transMap = input |
| 138 | + param.ltAxis = lifetimeAxis |
| 139 | + param.iThresh = iThresh |
| 140 | + // xInc is the difference (ns) between two bins |
| 141 | + param.xInc = timeBase / timeBins |
| 142 | + |
| 143 | + // Fit curves |
| 144 | + kernel = ops.op("create.kernelSum").arity1().input(1 + 2 * kernelRad).apply() |
| 145 | + lma = ops.op("flim.fitLMA").arity3().input(param, getMask(), kernel).apply() |
| 146 | + |
| 147 | + // The fit results paramMap is a XYC image, with result attributes along the Channel axis |
| 148 | + fittedImg = lma.paramMap |
| 149 | + // For LMA, we have Z, A1, and Tau1 as the three attributes |
| 150 | + A1 = ops.op("transform.hyperSliceView").arity3().input(fittedImg, lifetimeAxis, 1).apply() |
| 151 | + Tau1 = ops.op("transform.hyperSliceView").arity3().input(fittedImg, lifetimeAxis, 2).apply() |
| 152 | + |
| 153 | + // 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").arity3().input(lma, cMin, cMax).apply() |
| 157 | + |
| 158 | + end = System.currentTimeMillis() |
| 159 | + println("Finished fitting in " + (end - start) + " milliseconds") |
| 160 | + |
| 161 | +.. _`Bio-Formats` : https://www.openmicroscopy.org/bio-formats/ |
| 162 | +.. _`FLIM` : https://en.wikipedia.org/wiki/Fluorescence-lifetime_imaging_microscopy |
| 163 | +.. _`FluoCells™ Prepared Slide #1` : https://www.thermofisher.com/order/catalog/product/F36924 |
| 164 | +.. _`FRET` : https://en.wikipedia.org/wiki/F%C3%B6rster_resonance_energy_transfer |
0 commit comments