├── MSSR_1.0.0 ├── 220118MSSR.ipynb ├── MSSR_1.0.0.jar └── MSSR_User_Manual.pdf ├── MSSR_2.0.0.R ├── MSSR_2.0.0.jar ├── MSSR_2.0.0.py ├── MSSR_2.0.0_matlab.rar ├── MSSR_User_Manual.pdf ├── README.md ├── readme_resources ├── Installation.png ├── MSSR_Plugin.png └── Usage.png └── test_image.tif /MSSR_1.0.0/220118MSSR.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "id": "9457e740", 7 | "metadata": {}, 8 | "outputs": [], 9 | "source": [ 10 | "import numpy as np\n", 11 | "import scipy\n", 12 | "import matplotlib.pyplot as plt\n", 13 | "import napari\n", 14 | "from skimage.io import imread\n", 15 | "import math\n", 16 | "import scipy.interpolate as interpolate" 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": 2, 22 | "id": "7af12aa1", 23 | "metadata": {}, 24 | "outputs": [], 25 | "source": [ 26 | "def bicInter(img, amp, mesh):\n", 27 | " width, height = img.shape\n", 28 | " x=np.linspace(1, width, width)\n", 29 | " y=np.linspace(1, height, height)\n", 30 | " imgInter=interpolate.interp2d(x, y, img, kind='cubic')\n", 31 | " x2=np.linspace(1, width, width*amp)\n", 32 | " y2=np.linspace(1, height, height*amp)\n", 33 | " Z2 = imgInter(x2, y2)\n", 34 | " if mesh:\n", 35 | " Z2 = meshing(Z2, amp)\n", 36 | " return Z2" 37 | ] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "execution_count": 3, 42 | "id": "29089a3d", 43 | "metadata": {}, 44 | "outputs": [], 45 | "source": [ 46 | "#Mesh compensation\n", 47 | "def meshing(img, amp):\n", 48 | " width, height = img.shape\n", 49 | " desp = math.ceil(amp/2)\n", 50 | " imgPad = np.pad(img, desp, 'symmetric')\n", 51 | " imgS1 = imgPad[0:width, desp:height+desp]\n", 52 | " imgS2 = imgPad[(desp*2):width+(desp*2), desp:height+desp]\n", 53 | " imgS3 = imgPad[desp:width+desp, 0:height]\n", 54 | " imgS4 = imgPad[desp:width+desp, (desp*2):height+(desp*2)]\n", 55 | " imgF = (img + imgS1 + imgS2 + imgS3 + imgS4) / 5\n", 56 | " return imgF" 57 | ] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": 4, 62 | "id": "596c5ff6", 63 | "metadata": {}, 64 | "outputs": [], 65 | "source": [ 66 | "#Spatial MSSR\n", 67 | "def MSSR(img, psf, amp, order, mesh):\n", 68 | "# img = np.rot90(img, 1)\n", 69 | "# print(img[10,10])\n", 70 | " hs = round(0.4*psf*amp)\n", 71 | " maxValueImgOr = (max(map(max, img)))\n", 72 | " if(amp > 1):\n", 73 | " img = bicInter(img, amp, mesh)\n", 74 | " width, height = img.shape\n", 75 | " xPad = np.pad(img, hs, 'symmetric')\n", 76 | " M = np.zeros((width,height))\n", 77 | " for i in range(-hs, hs+1):\n", 78 | " for j in range(-hs, hs+1):\n", 79 | " if i!=0 or j!=0:\n", 80 | " xThis = xPad[hs+i:width+hs+i, hs+j:height+hs+j]\n", 81 | " M = np.maximum(M, np.absolute(img-xThis))\n", 82 | " \n", 83 | " weightAccum = np.zeros((width,height))\n", 84 | " yAccum = np.zeros((width,height))\n", 85 | " \n", 86 | " for i in range(-hs, hs+1):\n", 87 | " for j in range(-hs, hs+1):\n", 88 | " if i!=0 or j!=0:\n", 89 | " spatialkernel = np.exp(-(pow(i,2)+pow(j,2))/pow((hs),2))\n", 90 | " xThis = xPad[hs+i:width+hs+i, hs+j:height+hs+j]\n", 91 | " xDiffSq0 = pow((img-xThis)/M,2)\n", 92 | " intensityKernel = np.exp(-xDiffSq0)\n", 93 | "\n", 94 | " weightThis = spatialkernel*intensityKernel\n", 95 | " weightAccum = weightAccum + weightThis\n", 96 | " yAccum = yAccum + (xThis*weightThis)\n", 97 | " \n", 98 | " MS = img - (yAccum/weightAccum)\n", 99 | " MS[MS < 0] = 0\n", 100 | " MS[np.isnan(MS)] = 0\n", 101 | " \n", 102 | " I3 = MS/(max(map(max, MS)))\n", 103 | " x3 = img/(max(map(max, img)))\n", 104 | " for i in range(order):\n", 105 | " I4 = x3 - I3\n", 106 | " I5 = max(map(max, I4)) - I4\n", 107 | " I5 = I5/max(map(max, I5))\n", 108 | " I6 = I5*I3\n", 109 | " I7 = I6/max(map(max, I6))\n", 110 | " x3 = I3\n", 111 | " I3 = I7\n", 112 | " I3[np.isnan(I3)] = 0\n", 113 | "# I3 = np.rot90(I3, 3)\n", 114 | " IMSSR = I3*maxValueImgOr\n", 115 | " return I3" 116 | ] 117 | }, 118 | { 119 | "cell_type": "code", 120 | "execution_count": 5, 121 | "id": "d7a76c8d", 122 | "metadata": {}, 123 | "outputs": [], 124 | "source": [ 125 | "#Temporal MSSR\n", 126 | "def TMSSR(img, psf, amp, order, mesh):\n", 127 | " nFrames, width, height = img.shape\n", 128 | " imgMSSR = np.zeros((nFrames,width*amp,height*amp))\n", 129 | " for nI in range(nFrames):\n", 130 | " imgMSSR[nI, :, :] = MSSR(img_raw[nI], psf, amp, order, mesh)\n", 131 | " return imgMSSR" 132 | ] 133 | }, 134 | { 135 | "cell_type": "code", 136 | "execution_count": 6, 137 | "id": "c65004c8", 138 | "metadata": {}, 139 | "outputs": [], 140 | "source": [ 141 | "#Temporal Product Mean\n", 142 | "def TPM(img):\n", 143 | " nFrames, width, height = img.shape\n", 144 | " SumTPM = np.zeros((width,height))\n", 145 | " iTPM = np.zeros((width,height))\n", 146 | " for i in range(nFrames):\n", 147 | " SumTPM = SumTPM + img[i]\n", 148 | " for i in range(nFrames):\n", 149 | " iTPM = iTPM + (SumTPM * img[i])\n", 150 | " return iTPM" 151 | ] 152 | }, 153 | { 154 | "cell_type": "code", 155 | "execution_count": 7, 156 | "id": "cce9ebe8", 157 | "metadata": {}, 158 | "outputs": [], 159 | "source": [ 160 | "#Auto-Cummulants\n", 161 | "def TRAC(img, k):\n", 162 | " nFrames, width, height = img.shape\n", 163 | " avg = np.mean(img, 0)\n", 164 | " d0 = np.absolute(img - avg)\n", 165 | " d1 = d0[1:nFrames, :, :]\n", 166 | " d2 = d0[2:nFrames, :, :]\n", 167 | " d3 = d0[3:nFrames, :, :]\n", 168 | " if k == 2:\n", 169 | " trac = np.mean(d0[1:nFrames, :, :]*d1,0)\n", 170 | " elif k == 3:\n", 171 | " trac = np.mean(d0[2:nFrames, :, :]*d1[1:nFrames, :, :]*d2,0)\n", 172 | " else:\n", 173 | " t1 = np.mean(d0[3:nFrames, :, :]*d1[2:nFrames, :, :]*d2[1:nFrames, :, :]*d3,0)\n", 174 | " t2 = np.mean(d0[3:nFrames, :, :]*d1[2:nFrames, :, :],0)*np.mean(d2[1:nFrames, :, :]*d3,0)\n", 175 | " t3 = np.mean(d0[3:nFrames, :, :]*d2[1:nFrames, :, :],0)*np.mean(d1[2:nFrames, :, :]*d3,0)\n", 176 | " t4 = np.mean(d0[3:nFrames, :, :]*d3,0)*np.mean(d1[2:nFrames, :, :]*d2[1:nFrames, :, :],0)\n", 177 | " trac = np.absolute(t1-t2-t3-t4)\n", 178 | " return trac" 179 | ] 180 | }, 181 | { 182 | "cell_type": "code", 183 | "execution_count": 8, 184 | "id": "147c15c3", 185 | "metadata": {}, 186 | "outputs": [], 187 | "source": [ 188 | "#Parameters\n", 189 | "amp = 5\n", 190 | "psf = 3\n", 191 | "order = 0\n", 192 | "mesh = True" 193 | ] 194 | }, 195 | { 196 | "cell_type": "code", 197 | "execution_count": 9, 198 | "id": "8bef9f10", 199 | "metadata": {}, 200 | "outputs": [ 201 | { 202 | "data": { 203 | "text/plain": [ 204 | "" 205 | ] 206 | }, 207 | "execution_count": 9, 208 | "metadata": {}, 209 | "output_type": "execute_result" 210 | } 211 | ], 212 | "source": [ 213 | "img_raw = imread('raw7_100_PSFCHECK_561_DONUTS_33MS_5POWERL.tif')\n", 214 | "\n", 215 | "if 'viewer' not in globals():\n", 216 | " viewer = napari.Viewer()\n", 217 | "viewer.add_image(img_raw, colormap = 'magma')\n", 218 | "\n", 219 | "imgRawMean = np.mean(img_raw, 0)\n", 220 | "viewer.add_image(imgRawMean, colormap = 'magma')\n", 221 | "imgAmpMean = bicInter(imgRawMean, amp, False)\n", 222 | "viewer.add_image(imgAmpMean, colormap = 'magma')" 223 | ] 224 | }, 225 | { 226 | "cell_type": "code", 227 | "execution_count": 10, 228 | "id": "867a5f36", 229 | "metadata": {}, 230 | "outputs": [ 231 | { 232 | "data": { 233 | "text/plain": [ 234 | "" 235 | ] 236 | }, 237 | "execution_count": 10, 238 | "metadata": {}, 239 | "output_type": "execute_result" 240 | }, 241 | { 242 | "data": { 243 | "image/png": "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\n", 244 | "text/plain": [ 245 | "
" 246 | ] 247 | }, 248 | "metadata": { 249 | "needs_background": "light" 250 | }, 251 | "output_type": "display_data" 252 | } 253 | ], 254 | "source": [ 255 | "plt.imshow(imgAmpMean)" 256 | ] 257 | }, 258 | { 259 | "cell_type": "code", 260 | "execution_count": 11, 261 | "id": "4b0bb042", 262 | "metadata": {}, 263 | "outputs": [], 264 | "source": [ 265 | "#Computing Temporal MSSR\n", 266 | "imgMSSR = TMSSR(img_raw, psf, amp, order, mesh)\n", 267 | "#print(imgMSSR.shape)\n" 268 | ] 269 | }, 270 | { 271 | "cell_type": "code", 272 | "execution_count": 12, 273 | "id": "5ef6a416", 274 | "metadata": {}, 275 | "outputs": [ 276 | { 277 | "data": { 278 | "text/plain": [ 279 | "" 280 | ] 281 | }, 282 | "execution_count": 12, 283 | "metadata": {}, 284 | "output_type": "execute_result" 285 | } 286 | ], 287 | "source": [ 288 | "iMean = np.mean(imgMSSR, 0)\n", 289 | "viewer.add_image(iMean, colormap = 'magma')\n", 290 | "\n", 291 | "iVar = np.var(imgMSSR, 0)\n", 292 | "viewer.add_image(iVar, colormap = 'magma')\n", 293 | "\n", 294 | "iTPM = TPM(imgMSSR)\n", 295 | "viewer.add_image(iTPM, colormap = 'magma')\n", 296 | "\n", 297 | "iTRAC2 = TRAC(imgMSSR, 2)\n", 298 | "viewer.add_image(iTRAC2, colormap = 'magma')\n", 299 | "iTRAC3 = TRAC(imgMSSR, 3)\n", 300 | "viewer.add_image(iTRAC3, colormap = 'magma')\n", 301 | "iTRAC4 = TRAC(imgMSSR, 4)\n", 302 | "viewer.add_image(iTRAC4, colormap = 'magma')" 303 | ] 304 | }, 305 | { 306 | "cell_type": "code", 307 | "execution_count": null, 308 | "id": "53273ca2", 309 | "metadata": {}, 310 | "outputs": [], 311 | "source": [] 312 | } 313 | ], 314 | "metadata": { 315 | "kernelspec": { 316 | "display_name": "Python 3 (ipykernel)", 317 | "language": "python", 318 | "name": "python3" 319 | }, 320 | "language_info": { 321 | "codemirror_mode": { 322 | "name": "ipython", 323 | "version": 3 324 | }, 325 | "file_extension": ".py", 326 | "mimetype": "text/x-python", 327 | "name": "python", 328 | "nbconvert_exporter": "python", 329 | "pygments_lexer": "ipython3", 330 | "version": "3.9.9" 331 | } 332 | }, 333 | "nbformat": 4, 334 | "nbformat_minor": 5 335 | } 336 | -------------------------------------------------------------------------------- /MSSR_1.0.0/MSSR_1.0.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adanog/MSSR/77b20b16269487f8c3d2333e52e08f31a676b108/MSSR_1.0.0/MSSR_1.0.0.jar -------------------------------------------------------------------------------- /MSSR_1.0.0/MSSR_User_Manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adanog/MSSR/77b20b16269487f8c3d2333e52e08f31a676b108/MSSR_1.0.0/MSSR_User_Manual.pdf -------------------------------------------------------------------------------- /MSSR_2.0.0.R: -------------------------------------------------------------------------------- 1 | library(FCSlib) 2 | library(akima) 3 | library(matlab) 4 | 5 | # Stack analysis 6 | tMSSR <- function(img, amp, psf, order, mesh = TRUE, intNorm = TRUE){#, excOL = FALSE, OutLiersTh = 0.3){ 7 | di <- dim(img) 8 | MSSRDFinal <- array(data = NA, dim = c(di[1]*amp, di[2]*amp, di[3])) 9 | for(i in 1:dim(img)[3]){ 10 | MSSRDFinal[,,i] <- sfMSSR(img = img[, , i], amp = amp, psf = psf, order = order, mesh = mesh, 11 | intNorm = intNorm) 12 | } 13 | return(MSSRDFinal) 14 | } 15 | # Single frame analysis 16 | sfMSSR <- function(img, amp, psf, order, mesh = TRUE, intNorm = TRUE) { 17 | di <- dim(img) 18 | hs <- round(0.5*psf*amp) 19 | if(hs<1){ 20 | hs <- 1 21 | } 22 | if(amp > 1){ 23 | AMP <- bicubic.grid(x = 1:di[1], y = 1:di[2], z = img, nx = di[1]*amp, ny = di[2]*amp)$z 24 | if(mesh){ 25 | AMP <- meshing(img = AMP, desp = ceiling(amp/2)) 26 | } 27 | } else{ 28 | AMP <- img 29 | } 30 | xPad <- padarray(AMP, c(hs, hs), "symmetric", "both") 31 | 32 | M <- array(data = 0, dim = dim(AMP)) 33 | di <- dim(M) 34 | for(i in -hs:hs){ 35 | for(j in -hs:hs){ 36 | if((i!=0 || j!=0) && (sqrt(i^2 + j^2) <= hs)){ 37 | xThis <- xPad[(hs+i+1):(di[1]+hs+i), (hs+j+1):(di[2]+hs+j)] 38 | M = pmax(M, abs(AMP - xThis)) 39 | } 40 | } 41 | } 42 | 43 | weightAccum <- yAccum <- array(data = 0, dim = dim(AMP)) 44 | for(i in -hs:hs){ 45 | for(j in -hs:hs){ 46 | if((i!=0 || j!=0) && (sqrt(i^2 + j^2) <= hs)){ 47 | spatialKernel <- exp(-(i^2 + j^2) / (hs^2)) 48 | xThis <- xPad[(hs+i+1):(di[1]+hs+i), (hs+j+1):(di[2]+hs+j)] 49 | xDiffSq0 <- ((AMP - xThis) / M)^2 50 | intensityKernel <- exp(-xDiffSq0) 51 | 52 | weightThis <- spatialKernel * intensityKernel 53 | weightAccum <- weightAccum + weightThis 54 | yAccum <- yAccum + (xThis * weightThis) 55 | } 56 | } 57 | } 58 | 59 | MS <- AMP - (yAccum / weightAccum) 60 | MS[which(MS<0)] <- 0 61 | MS[which(is.na(MS))] <- 0 62 | 63 | I0 <- MS / max(MS) 64 | I3 <- I0 65 | x3 <- AMP / max(AMP) 66 | if(order>0){ 67 | for(i in 1:order){ 68 | I4 <- x3 - I3 69 | I5 <- max(I4) - I4 70 | I5 <- I5 / max(I5) 71 | I6 <- I5 * I3 72 | I7 <- I6 / max(I6) 73 | x3 <- I3 74 | I3 <- I7 75 | } 76 | } 77 | IMSSRD <- rot90(I3,3) 78 | if(intNorm){ 79 | IMSSRD <- IMSSRD*AMP# Intensity Normalization 80 | } 81 | return(IMSSRD) 82 | } 83 | excludeOutliers <- function(IMSSRD, OutLiersTh){ 84 | th = (100-OutLiersTh)/100 85 | 86 | IMSSRD <- IMSSRD*max(AMP) 87 | # print(min(IMSSRD)) 88 | # print(max(IMSSRD)) 89 | x <- seq(min(IMSSRD),max(IMSSRD), 1) 90 | Fn <- ecdf(IMSSRD) 91 | f <- Fn(x) 92 | x[which(f>th)] 93 | mnX <- min(x[which(f>th)]) 94 | IMSSRD[which(IMSSRD>mnX)] <- mnX 95 | IMSSRD <- IMSSRD/max(AMP) 96 | 97 | x <- seq(min(AMP),max(AMP), 1) 98 | Fn <- ecdf(AMP) 99 | f <- Fn(x) 100 | x[which(f>th)] 101 | mnX <- min(x[which(f>th)]) 102 | AMP[which(AMP>mnX)] <- mnX 103 | } 104 | # Mesh Compensation 105 | meshing <- function(img, desp){ 106 | img <- padarray(img, c(desp, desp), "symmetric", "both") # Genera una matriz reflejada en todas las dimensiones 107 | di <- dim(img) 108 | imgHD <- rbind(img[(di[1]-desp):di[1],], img[1:(di[1]-desp-1),]) 109 | imgHI <- rbind(img[(desp+1):di[1],], img[1:(desp),]) 110 | 111 | imgVD <- cbind(img[, (di[2]-desp):di[2]], img[, 1:(di[2]-desp-1)]) 112 | imgVI <- cbind(img[, (desp+1):di[2]], img[, 1:(desp)]) 113 | 114 | imgHVC <- (img + (imgHD) + (imgHI) + (imgVD) + (imgVI)) / (5) 115 | return(imgHVC[(desp+1):(di[1]-desp), (desp+1):(di[2]-desp)]) 116 | } 117 | # Temporal pixel-wise analysis 118 | TPM <- function(img){ 119 | di <- dim(img) 120 | SumTPM <- array(data = 0, dim = di[1:2]) 121 | iTPM <- array(data = 0, dim = di[1:2]) 122 | for(i in 1:di[3]){ 123 | SumTPM <- SumTPM + img[,,i] 124 | } 125 | for(i in 1:di[3]){ 126 | iTPM <- iTPM + (img[,,i] * SumTPM) 127 | } 128 | return(iTPM) 129 | } 130 | imVar<-function(img){ 131 | di<-dim(img) 132 | X<-di[1] 133 | Y<-di[2] 134 | Ivar<-array(NA, dim = c(X,Y)) 135 | for(i in 1:(X)){ 136 | for(j in 1:(Y)){ 137 | Ivar[i,j]<-var(img[i,j,], na.rm = T) 138 | } 139 | } 140 | return(Ivar) 141 | } 142 | imMean<-function(img){ 143 | di<-dim(img) 144 | if(length(di)!=3) return(img) 145 | if(di[3]<2) return(img) 146 | X<-di[1] 147 | Y<-di[2] 148 | Imean<-array(NA, dim = c(X,Y)) 149 | for(i in 1:(X)){ 150 | for(j in 1:(Y)){ 151 | Imean[i,j]<-mean(img[i,j,], na.rm = T) 152 | } 153 | } 154 | return(Imean) 155 | } -------------------------------------------------------------------------------- /MSSR_2.0.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adanog/MSSR/77b20b16269487f8c3d2333e52e08f31a676b108/MSSR_2.0.0.jar -------------------------------------------------------------------------------- /MSSR_2.0.0.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import math 3 | import scipy.interpolate as interpolate 4 | from napari.layers import Image, Labels, Layer, Points 5 | import matplotlib.pyplot as plt 6 | 7 | #Bicubic Interpolation 8 | def bicInter(img, amp, mesh): 9 | width, height = img.shape 10 | y=np.linspace(1, width, width) 11 | x=np.linspace(1, height, height) 12 | imgInter=interpolate.interp2d(x, y, img, kind='cubic') 13 | y2=np.linspace(1, width, width*amp) 14 | x2=np.linspace(1, height, height*amp) 15 | Z2 = imgInter(x2, y2) 16 | if mesh: 17 | Z2 = meshing(Z2, amp) 18 | return Z2 19 | 20 | #Fourier Interpolation 21 | def ftInterp(img, amp, mesh): 22 | width, height = img.shape 23 | mdX = math.ceil(width/2) + 1 24 | mdY = math.ceil(height/2) + 1 25 | 26 | extraBorder = math.ceil(amp/2) 27 | Nwidth = (width*amp) + extraBorder 28 | Nheight = (height*amp) + extraBorder 29 | 30 | lnX = len(np.arange((mdX),width)) 31 | lnY = len(np.arange((mdY),height)) 32 | 33 | imgFt = np.fft.fft2(img) 34 | imgFt = imgFt * (Nwidth/width) * (Nheight/height) 35 | # imgFt = imgFt * amp * amp 36 | 37 | fM = np.zeros((Nwidth, Nheight), dtype=complex) 38 | fM[0:mdX, 0:mdY] = imgFt[0:mdX, 0:mdY]; #izq sup cuadrante 39 | fM[0:mdX, (Nheight-lnY):Nheight] = imgFt[0:mdX, (mdY):height]; #der sup cuadrante 40 | fM[(Nwidth-lnX):Nwidth, 0:mdY] = imgFt[(mdX):width, 0:mdY]; #izq inf cuadrante 41 | fM[(Nwidth-lnX):Nwidth, (Nheight-lnY):Nheight] = imgFt[(mdX):width, (mdY):height]; #der inf cuadrante 42 | 43 | Z2 = (np.fft.ifft2(fM)).real 44 | Z2 = Z2[0:(width*amp), 0:(height*amp)] 45 | if mesh: 46 | Z2 = meshing(Z2, amp) 47 | return Z2 48 | 49 | #Mesh compensation 50 | def meshing(img, amp): 51 | width, height = img.shape 52 | desp = math.ceil(amp/2) 53 | imgPad = np.pad(img, desp, 'symmetric') 54 | imgS1 = imgPad[0:width, desp:height+desp] 55 | imgS2 = imgPad[(desp*2):width+(desp*2), desp:height+desp] 56 | imgS3 = imgPad[desp:width+desp, 0:height] 57 | imgS4 = imgPad[desp:width+desp, (desp*2):height+(desp*2)] 58 | imgF = (img + imgS1 + imgS2 + imgS3 + imgS4) / 5 59 | return imgF 60 | 61 | #Spatial MSSR 62 | def sfMSSR(img, fwhm, amp, order, mesh = True, ftI = False, intNorm = True): 63 | hs = round(0.5*fwhm*amp) 64 | if hs < 1: 65 | hs = 1 66 | maxValueImgOr = (max(map(max, img))) 67 | if(amp > 1 and not ftI): 68 | img = bicInter(img, amp, mesh) 69 | elif(amp > 1 and ftI): 70 | img = ftInterp(img, amp, mesh) 71 | width, height = img.shape 72 | xPad = np.pad(img, hs, 'symmetric') 73 | M = np.zeros((width,height)) 74 | for i in range(-hs, hs+1): 75 | for j in range(-hs, hs+1): 76 | if i!=0 or j!=0: 77 | xThis = xPad[hs+i:width+hs+i, hs+j:height+hs+j] 78 | M = np.maximum(M, np.absolute(img-xThis)) 79 | 80 | weightAccum = np.zeros((width,height)) 81 | yAccum = np.zeros((width,height)) 82 | 83 | for i in range(-hs, hs+1): 84 | for j in range(-hs, hs+1): 85 | if i!=0 or j!=0: 86 | spatialkernel = np.exp(-(pow(i,2)+pow(j,2))/pow((hs),2)) 87 | xThis = xPad[hs+i:width+hs+i, hs+j:height+hs+j] 88 | xDiffSq0 = pow((img-xThis)/M,2) 89 | intensityKernel = np.exp(-xDiffSq0) 90 | 91 | weightThis = spatialkernel*intensityKernel 92 | weightAccum = weightAccum + weightThis 93 | yAccum = yAccum + (xThis*weightThis) 94 | 95 | MS = img - (yAccum/weightAccum) 96 | MS[MS < 0] = 0 97 | MS[np.isnan(MS)] = 0 98 | 99 | I3 = MS/(max(map(max, MS))) 100 | x3 = img/(max(map(max, img))) 101 | for i in range(order): 102 | I4 = x3 - I3 103 | I5 = max(map(max, I4)) - I4 104 | I5 = I5/max(map(max, I5)) 105 | I6 = I5*I3 106 | I7 = I6/max(map(max, I6)) 107 | x3 = I3 108 | I3 = I7 109 | I3[np.isnan(I3)] = 0 110 | if intNorm: 111 | IMSSR = I3*img 112 | else: 113 | IMSSR = I3 114 | return IMSSR 115 | 116 | #Temporal MSSR 117 | def tMSSR(img_layer, fwhm, amp, order, mesh = True, ftI = False, intNorm = True): 118 | img=np.array(img_layer.data) 119 | nFrames, width, height = img.shape 120 | imgMSSR = np.zeros((nFrames,width*amp,height*amp)) 121 | for nI in range(nFrames): 122 | print("Image " + str(nI+1)) 123 | imgMSSR[nI, :, :] = sfMSSR(img[nI], fwhm, amp, order, mesh, ftI, intNorm) 124 | return imgMSSR 125 | 126 | #Mean 127 | def tMean(img): 128 | return np.mean(img, 0) 129 | 130 | #Variance 131 | def tVar(img): 132 | return np.var(img, 0) 133 | 134 | #Temporal Product Mean 135 | def TPM(img): 136 | nFrames, width, height = img.shape 137 | SumTPM = np.zeros((width,height)) 138 | iTPM = np.zeros((width,height)) 139 | for i in range(nFrames): 140 | SumTPM = SumTPM + img[i] 141 | for i in range(nFrames): 142 | iTPM = iTPM + (SumTPM * img[i]) 143 | return iTPM 144 | 145 | #Auto-Cummulants 146 | def TRAC(img, k): 147 | nFrames, width, height = img.shape 148 | avg = np.mean(img, 0) 149 | d0 = np.absolute(img - avg) 150 | d1 = d0[1:nFrames, :, :] 151 | d2 = d0[2:nFrames, :, :] 152 | d3 = d0[3:nFrames, :, :] 153 | if k == 2: 154 | trac = np.mean(d0[1:nFrames, :, :]*d1,0) 155 | elif k == 3: 156 | trac = np.mean(d0[2:nFrames, :, :]*d1[1:nFrames, :, :]*d2,0) 157 | else: 158 | t1 = np.mean(d0[3:nFrames, :, :]*d1[2:nFrames, :, :]*d2[1:nFrames, :, :]*d3,0) 159 | t2 = np.mean(d0[3:nFrames, :, :]*d1[2:nFrames, :, :],0)*np.mean(d2[1:nFrames, :, :]*d3,0) 160 | t3 = np.mean(d0[3:nFrames, :, :]*d2[1:nFrames, :, :],0)*np.mean(d1[2:nFrames, :, :]*d3,0) 161 | t4 = np.mean(d0[3:nFrames, :, :]*d3,0)*np.mean(d1[2:nFrames, :, :]*d2[1:nFrames, :, :],0) 162 | trac = np.absolute(t1-t2-t3-t4) 163 | return trac 164 | 165 | #Empirical cumulative distribution function 166 | def ecdf(data): 167 | """ Compute ECDF """ 168 | data = np.reshape(data, -1) 169 | x = np.sort(data) 170 | n = len(x) 171 | y = np.arange(1, n+1) / n 172 | return(x,y) 173 | 174 | #Exclude Outliers 175 | def excOutliers(data, th): 176 | th = (100 - th)/100 177 | x, f = ecdf(data) 178 | found = np.where(f > th) 179 | mnX = x[found[0][0]]; 180 | data = np.where(data >= mnX, mnX, data) 181 | return data 182 | -------------------------------------------------------------------------------- /MSSR_2.0.0_matlab.rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adanog/MSSR/77b20b16269487f8c3d2333e52e08f31a676b108/MSSR_2.0.0_matlab.rar -------------------------------------------------------------------------------- /MSSR_User_Manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adanog/MSSR/77b20b16269487f8c3d2333e52e08f31a676b108/MSSR_User_Manual.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MSSR Plugin Documentation 2 | 3 | DOI 4 | 5 | # Detailed Method Description: 6 | 7 | For an in-depth explanation of the MSSR method, refer to the article: 8 | 9 | Torres-García, E., Pinto-Cámara, R., Linares, A. et al. Extending resolution within a single imaging frame. Nat Commun 13, 7452 (2022). 10 | https://doi.org/10.1038/s41467-022-34693-9 11 | 12 | If this software has been useful in your research, please consider citing the above publication. 13 | 14 | 15 | # Accompanying Files 16 | 17 | This README.txt file is provided alongside the following resources: 18 | 19 | • MSSR_2.0.0.jar plugin in the ijplugin folder. 20 | • A demonstration dataset: test_image.tif (a laser lithography dataset containing doughnut-shaped structures combined in a single stack). 21 | • A copy of the license: LICENSE.txt. 22 | • An R script: MSSR_2.0.0.R. 23 | • A Python script: MSSR_2.0.0.py. 24 | • A Matlab script package: MSSR_2.0.0_matlab.rar. 25 | 26 | 27 | # System requirements 28 | 29 | Plugin Requirements: 30 | The MSSR_2.0.0.jar plugin requires an installation of ImageJ. 31 | Full instruction for the installation of ImageJ can be found at: 32 | https://imagej.nih.gov/ij/download.html 33 | 34 | • Tested on: Windows 10x86, Linux Ubuntu 20.04.4 LTS. 35 | • Compatible with ImageJ versions 1.48 or higher. 36 | 37 | Script Requirements: 38 | 39 | • R script compatibility: R 4.1.1. 40 | • Python script compatibility: Python 3.10.4. 41 | • Matlab script compatibility: Matlab R2021b (64-bit). 42 | 43 | 44 | ------------------- 45 | # Minimum Hardware Specifications and Estimated Execution Time 46 | 47 | Minimum Requirements: 48 | 49 | • CPU: Intel(R) Core i5 (3rd generation) 50 | • RAM: 4GB 51 | • Graphics: Integrated Intel(R) HD Graphics 2500 52 | 53 | Example Execution Times 54 | 55 | For a dataset of 32x32 with 100 images (Amplification: 5, FWHM: 3, Order: 1): 56 | 57 | | Iterpolation | Seconds | 58 | | :---: | :---: | 59 | | Bicubic | 32 | 60 | | Fourier | 42 | 61 | 62 | For a dataset of 64x64 with 100 images (Amplification: 5, FWHM: 3, Order: 1): 63 | 64 | | Iterpolation | Seconds | 65 | | :---: | :---: | 66 | | Bicubic | 114 | 67 | | Fourier | 165 | 68 | 69 | ------------------- 70 | # Installation guide 71 | 72 | To install the MSSR plugin, first ensure you have the latest version of FIJI installed (https://fiji.sc/). Additionally, the CLIJ, CLIJ2, and CLIJx packages must be installed, as explained in the CLIJ2 documentation (https://clij.github.io/clij2-docs/installationInFiji) (Figure panel c). 73 | 74 | 75 | Plugin Installation Options: 76 | 77 | 1. Through FIJI: Select Plugins -> Install -> MSSR_2.0.0.jar. 78 | 2. Manual Installation: Place the MSSR_2.0.0.jar file in the FIJI plugins folder. 79 | 80 | Estimated installation time is approximately 2-5 minutes, excluding download times. 81 | 82 | 83 | 84 | Figure 1. Installing MSSR plugin on FIJI/ImageJ. 85 | 86 | ------------------- 87 | # MSSR Plugin Overview 88 | 89 | The MSSR plugin provides two main analysis options: 90 | 91 | * MSSR Analysis: Performs the primary processing for either sf-MSSRn or t-MSSRn. 92 | * Temporal Analysis: Conducts temporal analysis for a selected Point Temporal Function (PTF) for t-MSSRn processing. 93 | 94 | In what follows the main parameters available for MSSR analysis computation will be explained, hence, description will be centered on the use of the MSSR Analysis tab of the MSSR plugin. 95 | 96 | 97 | MSSR Analysis Parameters (Figure panel b.1): 98 | 99 | The following parameters must be defined for the analysis: 100 | 101 | * AMP: Defines the upscaling factor for image size. 102 | * FWHM: Sets the number of pixels covering the Full Width at Half Maximum (FWHM) of the imaging lens’s Point Spread Function (PSF). 103 | * Order: Determines the number of MSSR iterations to enhance image resolution. 104 | 105 | The plugin offers the option of computing 𝑠𝑓−𝑀𝑆𝑆𝑅𝑛, or both 𝑠𝑓−𝑀𝑆𝑆𝑅𝑛 and 𝑡−𝑀𝑆𝑆𝑅𝑛. The temporal analysis is enabled when selecting the option “MSSR Temporal analysis” (Figure panel b.3) where the user can choose one of five available PTFs: Mean, Variance (Var), Temporal Product Mean (TPM), Coefficient Variation, Auto-cumulant Function of order 2-4 (SOFI 2-4). 106 | 107 | Additional Features: 108 | 109 | 110 | * FWHM Computation: Provides an estimation of the Rayleigh criterion based on optical parameters (Figure panel c). 111 | * Interpolation Type: Offers ‘Bicubic’ as the default option for image magnification. 112 | * Mesh Minimization: Reduces mesh artifacts from bicubic interpolation (Figure panel b.2. 113 | * GPU Computing: Enables GPU processing for enhanced performance (Figure panel b.2). 114 | * Intensity Normalization: Allows pixel-wise scaling of MSSR images with the magnified original image (Figure panel b.2). 115 | * Image Selection: Allows choosing an image or stack for analysis (Figure panel b.3). 116 | * Batch Analysis: Enables automatic processing of all images in a selected folder (Figure panel b.3). 117 | 118 | 119 | 120 | 121 | Figure 2. MSSR usage and parameters 122 | 123 | ------------------- 124 | # Usage instructions 125 | 126 | 1. Open ImageJ. 127 | 2. Load the dataset test_image.tif. 128 | 3. Go to Plugins -> MSSR -> MSSR Analysis to open the analysis window. 129 | 4. Define the desired parameters and enable any additional features. 130 | 5. Click “OK” to start the analysis. 131 | 132 | After processing, the output images will display in the interface. Temporal analysis will produce an additional image of the temporal stack projection if selected. 133 | 134 | ------------------- 135 | # Demo 136 | 137 | To demonstrate the plugin: 138 | 139 | 1. Open the image of interest in ImageJ, ensuring it is the active window. 140 | 2. Specify the analysis parameters as needed. 141 | 3. If temporal analysis is selected, two images will be generated: the processed stack and the temporal stack projection. 142 | 143 | The plugin supports multidimensional stacks of any bit depth, with output images saved in 32-bit format. 144 | 145 | 146 | 147 | Figure 3. A demo of MSSR processing. 148 | -------------------------------------------------------------------------------- /readme_resources/Installation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adanog/MSSR/77b20b16269487f8c3d2333e52e08f31a676b108/readme_resources/Installation.png -------------------------------------------------------------------------------- /readme_resources/MSSR_Plugin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adanog/MSSR/77b20b16269487f8c3d2333e52e08f31a676b108/readme_resources/MSSR_Plugin.png -------------------------------------------------------------------------------- /readme_resources/Usage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adanog/MSSR/77b20b16269487f8c3d2333e52e08f31a676b108/readme_resources/Usage.png -------------------------------------------------------------------------------- /test_image.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adanog/MSSR/77b20b16269487f8c3d2333e52e08f31a676b108/test_image.tif --------------------------------------------------------------------------------