def test_odt_to_ri(): myframe = sys._getframe() f, res, nm = get_test_data_set() ri = odtbrain.odt_to_ri(f=f, res=res, nm=nm) if WRITE_RES: write_results(myframe, ri) assert np.allclose(np.array(ri).flatten().view( float), get_results(myframe)) # Also test 2D version ri2d = odtbrain.odt_to_ri(f=f[0], res=res, nm=nm) assert np.allclose(ri2d, ri[0])
## Setup background t_RealBack = float('-1.60175172169E-02') t_ImagBack = float('-1.85142597885E-02') t_ComplexBack = t_RealBack + 1j*t_ImagBack # t_SinoBack = np.tile(t_ComplexBack, t_SudutProj*t_SensorInterp).reshape(t_SudutProj, t_SensorInterp) t_SinoBack = np.tile(t_ComplexBack, t_SudutInterp*t_SensorInterp).reshape(t_SudutInterp, t_SensorInterp) # print(t_SinoBack) ## Prep for Reconstruksi Citra t_Theta = np.linspace(0., 360., t_SudutInterp, endpoint=False) ## Do Fasa background corrected t_SinoCorrected = t_SinoSudutInterp/t_SinoBack ## Do backpropagate 2D u_sinR = odt.sinogram_as_rytov(t_SinoCorrected) angles = np.linspace(0, 2*np.pi, t_SudutInterp, endpoint=False) res = 9.0 nmed = 2.4 lD = 1.0 fR = odt.backpropagate_2d(u_sinR, angles, res, nmed, lD * res) nR = odt.odt_to_ri(fR, res, nmed) ## plot data fig, (ax1) = plt.subplots(1, 1) ax1.imshow(ndimage.median_filter(nR.real*-1, size=7)) ax1.set_xlabel('pixel') ax1.set_ylabel('pixel') plt.show()
rad_px = radius * res phantom = np.array(((Y - lC * res)**2 + X**2) < rad_px**2, dtype=np.float) * (ncyl - nmed) + nmed u_sinR = odt.sinogram_as_rytov(sino / u0) # Rytov 200 projections # remove 50 projections from total of 250 projections remove200 = np.argsort(angles % .0002)[:50] angles200 = np.delete(angles, remove200, axis=0) u_sinR200 = np.delete(u_sinR, remove200, axis=0) ph200 = unwrap.unwrap(np.angle(sino / u0)) ph200[remove200] = 0 fR200 = odt.backpropagate_2d(u_sinR200, angles200, res, nmed, lD * res) nR200 = odt.odt_to_ri(fR200, res, nmed) fR200nw = odt.backpropagate_2d(u_sinR200, angles200, res, nmed, lD * res, weight_angles=False) nR200nw = odt.odt_to_ri(fR200nw, res, nmed) # Rytov 50 projections remove50 = np.argsort(angles % .0002)[:200] angles50 = np.delete(angles, remove50, axis=0) u_sinR50 = np.delete(u_sinR, remove50, axis=0) ph50 = unwrap.unwrap(np.angle(sino / u0)) ph50[remove50] = 0
lD = cfg["lD"] # measurement distance in wavelengths lC = cfg["lC"] # displacement from center of image size = cfg["size"] res = cfg["res"] # px/wavelengths A = cfg["A"] # number of projections x = np.arange(size) - size / 2 X, Y = np.meshgrid(x, x) rad_px = radius * res phantom = np.array(((Y - lC * res)**2 + X**2) < rad_px**2, dtype=np.float) * (ncyl - nmed) + nmed # Born u_sinB = (sino / u0 * u0_single - u0_single) # fake born fB = odt.backpropagate_2d(u_sinB, angles, res, nmed, lD * res) nB = odt.odt_to_ri(fB, res, nmed) # Rytov u_sinR = odt.sinogram_as_rytov(sino / u0) fR = odt.backpropagate_2d(u_sinR, angles, res, nmed, lD * res) nR = odt.odt_to_ri(fR, res, nmed) # Rytov 50 u_sinR50 = odt.sinogram_as_rytov((sino / u0)[::5, :]) fR50 = odt.backpropagate_2d(u_sinR50, angles[::5], res, nmed, lD * res) nR50 = odt.odt_to_ri(fR50, res, nmed) # Plot sinogram phase and amplitude ph = odt.sinogram_as_radon(sino / u0) am = np.abs(sino / u0)
print("Performing tilted backpropagation.") # Determine tilted axis tilted_axis = [0, np.cos(cfg["tilt_yz"]), np.sin(cfg["tilt_yz"])] # Perform tilted backpropagation f_tilt = odt.backpropagate_3d_tilted( uSin=sinoRytov, angles=angles, res=cfg["res"], nm=cfg["nm"], lD=cfg["lD"], tilted_axis=tilted_axis, ) # compute refractive index n from object function n_naiv = odt.odt_to_ri(f_naiv, res=cfg["res"], nm=cfg["nm"]) n_tilt = odt.odt_to_ri(f_tilt, res=cfg["res"], nm=cfg["nm"]) sx, sy, sz = n_tilt.shape px, py, pz = phantom.shape sino_phase = np.angle(sino) # compare phantom and reconstruction in plot fig, axes = plt.subplots(2, 3, figsize=(8, 4.5)) kwri = {"vmin": n_tilt.real.min(), "vmax": n_tilt.real.max()} kwph = {"vmin": sino_phase.min(), "vmax": sino_phase.max(), "cmap": "coolwarm"} # Sinogram axes[0, 0].set_title("phase projection") phmap = axes[0, 0].imshow(sino_phase[A // 2, :, :], **kwph)
X, Y = np.meshgrid(x, x) rad_px = radius * res phantom = np.array(((Y - lC * res)**2 + X**2) < rad_px**2, dtype=np.float) * (ncyl - nmed) + nmed u_sinR = odt.sinogram_as_rytov(sino / u0) # Rytov 100 projections evenly distributed removeeven = np.argsort(angles % .002)[:150] angleseven = np.delete(angles, removeeven, axis=0) u_sinReven = np.delete(u_sinR, removeeven, axis=0) pheven = odt.sinogram_as_radon(sino / u0) pheven[removeeven] = 0 fReven = odt.backpropagate_2d(u_sinReven, angleseven, res, nmed, lD * res) nReven = odt.odt_to_ri(fReven, res, nmed) fRevennw = odt.backpropagate_2d(u_sinReven, angleseven, res, nmed, lD * res, weight_angles=False) nRevennw = odt.odt_to_ri(fRevennw, res, nmed) # Rytov 100 projections more than 180 removemiss = 249 - \ np.concatenate((np.arange(100), 100 + np.arange(150)[::3])) anglesmiss = np.delete(angles, removemiss, axis=0) u_sinRmiss = np.delete(u_sinR, removemiss, axis=0) phmiss = odt.sinogram_as_radon(sino / u0) phmiss[removemiss] = 0
X,Y = np.meshgrid(x,x) rad_px = radius*res phantom = np.array(((Y-lC*res)**2+X**2)<rad_px**2, dtype=np.float)*(ncyl-nmed)+nmed u_sinR = odt.sinogram_as_rytov(sino/u0) # Rytov 200 projections # remove 50 projections from total of 250 projections remove200 = np.argsort(angles % .002)[:50] angles200 = np.delete(angles, remove200, axis=0) u_sinR200 = np.delete(u_sinR, remove200, axis=0) ph200 = unwrap.unwrap(np.angle(sino/u0)) ph200[remove200] = 0 fR200 = odt.backpropagate_2d(u_sinR200, angles200, res, nmed, lD*res) nR200 = odt.odt_to_ri(fR200, res, nmed) fR200nw = odt.backpropagate_2d(u_sinR200, angles200, res, nmed, lD*res, weight_angles=False) nR200nw = odt.odt_to_ri(fR200nw, res, nmed) # Rytov 50 projections remove50 = np.argsort(angles % .002)[:200] angles50 = np.delete(angles, remove50, axis=0) u_sinR50 = np.delete(u_sinR, remove50, axis=0) ph50 = unwrap.unwrap(np.angle(sino/u0)) ph50[remove50] = 0 fR50 = odt.backpropagate_2d(u_sinR50, angles50, res, nmed, lD*res) nR50 = odt.odt_to_ri(fR50, res, nmed) fR50nw = odt.backpropagate_2d(u_sinR50, angles50, res, nmed, lD*res, weight_angles=False) nR50nw = odt.odt_to_ri(fR50nw, res, nmed)
u_sin = np.tile(Ex.flat, A).reshape(A, int(cfg["size"]), int(cfg["size"])) # Apply the Rytov approximation u_sinR = odt.sinogram_as_rytov(u_sin) # Backpropagation fR = odt.backpropagate_3d(uSin=u_sinR, angles=angles, res=cfg["res"], nm=cfg["nm"], lD=0, padfac=2.1, save_memory=True) # RI computation nR = odt.odt_to_ri(fR, cfg["res"], cfg["nm"]) # Plotting fig, axes = plt.subplots(2, 3, figsize=(8, 5)) axes = np.array(axes).flatten() # field axes[0].set_title("Mie field phase") axes[0].set_xlabel("detector x") axes[0].set_ylabel("detector y") axes[0].imshow(np.angle(Ex), cmap="coolwarm") axes[1].set_title("Mie field amplitude") axes[1].set_xlabel("detector x") axes[1].set_ylabel("detector y") axes[1].imshow(np.abs(Ex), cmap="gray") # line plot
h5file = pathlib.Path(tdir) / "series.h5" with qpimage.QPSeries(h5file=h5file, h5mode="r") as qps: qp0 = qps[0] meta = qp0.meta sino = np.zeros((len(qps), qp0.shape[0], qp0.shape[1]), dtype=np.complex) for ii in range(len(qps)): sino[ii] = qps[ii].field # perform backgpropagation u_sinR = odt.sinogram_as_rytov(sino) res = meta["wavelength"] / meta["pixel size"] nm = meta["medium index"] fR = odt.backpropagate_3d(uSin=u_sinR, angles=angles, res=res, nm=nm) ri = odt.odt_to_ri(fR, res, nm) # plot results ext = meta["pixel size"] * 1e6 * 70 kw = { "vmin": ri.real.min(), "vmax": ri.real.max(), "extent": [-ext, ext, -ext, ext] } fig, axes = plt.subplots(1, 3, figsize=(8, 2.5)) axes[0].imshow(ri[70, :, :].real, **kw) axes[0].set_xlabel("x [µm]") axes[0].set_ylabel("y [µm]") x = np.linspace(-ext, ext, 140) axes[1].plot(x, ri[70, :, 70], label="line plot x=0")
def backpropagate_sinogram( sinogram, angles, approx, res, nm, ld=0, ): """Backpropagate a 2D or 3D sinogram Parameters ---------- sinogram: complex ndarray The scattered field data angles: 1d ndarray The angles at which the sinogram data were recorded approx: str Approximation to use, one of ["radon", "born", "rytov"] res: float Size of vacuum wavelength in pixels nm: float Refractive index of surrounding medium ld: float Reconstruction distance. Values !=0 only make sense for the Born approximation (which itself is not very usable). See the ODTbrain documentation for more information. Returns ------- ri: ndarray The 2D or 3D reconstructed refractive index """ sshape = len(sinogram.shape) assert sshape in [2, 3], "sinogram must have dimension 2 or 3" uSin = sinogram assert approx in ["radon", "born", "rytov"] if approx == "rytov": uSin = odt.sinogram_as_rytov(uSin) elif approx == "radon": uSin = odt.sinogram_as_radon(uSin) if approx in ["born", "rytov"]: # Perform reconstruction with ODT if sshape == 2: f = odt.backpropagate_2d(uSin, angles=angles, res=res, nm=nm, lD=ld) else: f = odt.backpropagate_3d(uSin, angles=angles, res=res, nm=nm, lD=ld) ri = odt.odt_to_ri(f, res, nm) else: # Perform reconstruction with OPT # works in 2d and 3d f = rt.backproject(uSin, angles=angles) ri = odt.opt_to_ri(f, res, nm) return ri
# Create sinogram u_sin = np.tile(Ex.flat,A).reshape(A, cfg["size"], cfg["size"]) # Apply the Rytov approximation u_sinR = odt.sinogram_as_rytov(u_sin) # Backpropagation fR = odt.backpropagate_3d(uSin = u_sinR, angles = angles, res = cfg["res"], nm = cfg["nm"], lD = lD, padfac=2.1) # RI computation nR = odt.odt_to_ri(fR, cfg["res"], cfg["nm"]) # Plotting fig, axes = plt.subplots(2, 3, figsize=(12,8), dpi=300) axes = np.array(axes).flatten() # field axes[0].set_title("Mie field phase") axes[0].set_xlabel("xD") axes[0].set_ylabel("yD") axes[0].imshow(np.angle(Ex), cmap=plt.cm.coolwarm) # @UndefinedVariable axes[1].set_title("Mie field amplitude") axes[1].set_xlabel("xD") axes[1].set_ylabel("yD") axes[1].imshow(np.abs(Ex), cmap=plt.cm.gray) # @UndefinedVariable # line plot
## Apply the Rytov approximation sinoRytov = odt.sinogram_as_rytov(sino) ## perform backpropagation to obtain object function f f = odt.backpropagate_2d( uSin=sinoRytov, angles=angles, res=cfg["res"], nm=cfg["nm"], lD=cfg["lD"]*cfg["res"] ) ## compute refractive index n from object function n = odt.odt_to_ri(f, res=cfg["res"], nm=cfg["nm"]) ## compare phantom and reconstruction in plot fig, axes = plt.subplots(1, 3, figsize=(12,4), dpi=300) axes[0].set_title("FDTD phantom") axes[0].imshow(phantom, vmin=phantom.min(), vmax=phantom.max()) sino_phase = np.unwrap(np.angle(sino), axis=1) axes[0].set_xlabel("x") axes[0].set_ylabel("y") axes[1].set_title("phase sinogram") axes[1].imshow(sino_phase, vmin=sino_phase.min(), vmax=sino_phase.max(), aspect=sino.shape[1]/sino.shape[0], cmap=plt.cm.coolwarm) # @UndefinedVariable
## Perform tilted backpropagation f_name_tilt = "f_tilt2.npy" if not os.path.exists(f_name_tilt): f_tilt = odt.backpropagate_3d_tilted( uSin=sinoRytov, angles=angles, res=cfg["res"], nm=cfg["nm"], lD=cfg["lD"], tilted_axis=tilted_axis, ) np.save(f_name_tilt, f_tilt) else: f_tilt = np.load(f_name_tilt) ## compute refractive index n from object function n_tilt = odt.odt_to_ri(f_tilt, res=cfg["res"], nm=cfg["nm"]) sx, sy, sz = n_tilt.shape px, py, pz = phantom.shape sino_phase = np.angle(sino) ## compare phantom and reconstruction in plot fig, axes = plt.subplots(1, 3, figsize=(12,3.5), dpi=300) kwri = {"vmin": n_tilt.real.min(), "vmax": n_tilt.real.max()} kwph = {"vmin": sino_phase.min(), "vmax": sino_phase.max(), "cmap":plt.cm.coolwarm} # @UndefinedVariable # Sinorgam axes[0].set_title("phase projection")
sino = cellsino.Sinogram(phantom=phantom, wavelength=wavelength, pixel_size=pixel_size, grid_size=grid_size) # compute sinogram (field according to Rytov approximation and fluorescence) sino = sino.compute(angles=angles, propagator="rytov", mode="field") # reconstruction of refractive index sino_rytov = odt.sinogram_as_rytov(sino) f = odt.backpropagate_3d(uSin=sino_rytov, angles=angles, res=wavelength / pixel_size, nm=medium_index) ri = odt.odt_to_ri(f=f, res=wavelength / pixel_size, nm=medium_index) # apple core correction fc = odt.apple.correct(f=f, res=wavelength / pixel_size, nm=medium_index, method="sh") ric = odt.odt_to_ri(f=fc, res=wavelength / pixel_size, nm=medium_index) # plotting idx = ri.shape[2] // 2 # log-scaled power spectra ft = np.log(1 + np.abs(np.fft.fftshift(np.fft.fftn(ri)))) ftc = np.log(1 + np.abs(np.fft.fftshift(np.fft.fftn(ric))))
lD = cfg["lD"] # measurement distance in wavelengths lC = cfg["lC"] # displacement from center of image size = cfg["size"] res = cfg["res"] # px/wavelengths A = cfg["A"] # number of projections #phantom = np.loadtxt(arc.open("mie_phantom.txt")) x = np.arange(size)-size/2.0 X,Y = np.meshgrid(x,x) rad_px = radius*res phantom = np.array(((Y-lC*res)**2+X**2)<rad_px**2, dtype=np.float)*(ncyl-nmed)+nmed # Born u_sinB = (sino/u0*u0_single-u0_single) #fake born fB = odt.backpropagate_2d(u_sinB, angles, res, nmed, lD*res) nB = odt.odt_to_ri(fB, res, nmed) # Rytov u_sinR = odt.sinogram_as_rytov(sino/u0) fR = odt.backpropagate_2d(u_sinR, angles, res, nmed, lD*res) nR = odt.odt_to_ri(fR, res, nmed) # Rytov 50 u_sinR50 = odt.sinogram_as_rytov((sino/u0)[::5,:]) fR50 = odt.backpropagate_2d(u_sinR50, angles[::5], res, nmed, lD*res) nR50 = odt.odt_to_ri(fR50, res, nmed) # Plot sinogram phase and amplitude ph = unwrap.unwrap(np.angle(sino/u0))
sino = cellsino.Sinogram(phantom=phantom, wavelength=wavelength, pixel_size=pixel_size, grid_size=grid_size) # compute sinogram (field according to Rytov approximation and fluorescence) sino_field, sino_fluor = sino.compute(angles=angles, propagator="rytov") # reconstruction of refractive index sino_rytov = odt.sinogram_as_rytov(sino_field) potential = odt.backpropagate_3d(uSin=sino_rytov, angles=angles, res=wavelength/pixel_size, nm=medium_index) ri = odt.odt_to_ri(f=potential, res=wavelength/pixel_size, nm=medium_index) # reconstruction of fluorescence fl = rt.backproject_3d(sinogram=sino_fluor, angles=angles) # reference for comparison rimod, flmod = phantom.draw(grid_size=ri.shape, pixel_size=pixel_size) # plotting idx = 150 plt.figure(figsize=(7, 5.5))
print("Number of projections:", A) print("Performing backpropagation.") # Apply the Rytov approximation sinoRytov = odt.sinogram_as_rytov(sino) # perform backpropagation to obtain object function f f = odt.backpropagate_3d(uSin=sinoRytov, angles=angles, res=cfg["res"], nm=cfg["nm"], lD=cfg["lD"] ) # compute refractive index n from object function n = odt.odt_to_ri(f, res=cfg["res"], nm=cfg["nm"]) sx, sy, sz = n.shape px, py, pz = phantom.shape sino_phase = np.angle(sino) # compare phantom and reconstruction in plot fig, axes = plt.subplots(2, 3, figsize=(8, 4)) kwri = {"vmin": n.real.min(), "vmax": n.real.max()} kwph = {"vmin": sino_phase.min(), "vmax": sino_phase.max(), "cmap": "coolwarm"} # Phantom axes[0, 0].set_title("FDTD phantom center") rimap = axes[0, 0].imshow(phantom[px // 2], **kwri)
x = np.arange(size)-size/2.0 X,Y = np.meshgrid(x,x) rad_px = radius*res phantom = np.array(((Y-lC*res)**2+X**2)<rad_px**2, dtype=np.float)*(ncyl-nmed)+nmed u_sinR = odt.sinogram_as_rytov(sino/u0) # Rytov 100 projections evenly distributed removeeven = np.argsort(angles % .002)[:150] angleseven = np.delete(angles, removeeven, axis=0) u_sinReven = np.delete(u_sinR, removeeven, axis=0) pheven = unwrap.unwrap(np.angle(sino/u0)) pheven[removeeven] = 0 fReven = odt.backpropagate_2d(u_sinReven, angleseven, res, nmed, lD*res) nReven = odt.odt_to_ri(fReven, res, nmed) fRevennw = odt.backpropagate_2d(u_sinReven, angleseven, res, nmed, lD*res, weight_angles=False) nRevennw = odt.odt_to_ri(fRevennw, res, nmed) # Rytov 100 projections more than 180 removemiss = 249 - np.concatenate((np.arange(100), 100+np.arange(150)[::3])) anglesmiss = np.delete(angles, removemiss, axis=0) u_sinRmiss = np.delete(u_sinR, removemiss, axis=0) phmiss = unwrap.unwrap(np.angle(sino/u0)) phmiss[removemiss] = 0 fRmiss = odt.backpropagate_2d(u_sinRmiss, anglesmiss, res, nmed, lD*res) nRmiss = odt.odt_to_ri(fRmiss, res, nmed) fRmissnw = odt.backpropagate_2d(u_sinRmiss, anglesmiss, res, nmed, lD*res, weight_angles=False) nRmissnw = odt.odt_to_ri(fRmissnw, res, nmed)