def test_sino_rytov(): myframe = sys._getframe() sino = get_test_data_set_sino(rytov=True) ryt = odtbrain.sinogram_as_rytov(sino) twopi = 2*np.pi if WRITE_RES: write_results(myframe, ryt) # When moving from unwrap to skimage, there was an offset introduced. # Since this particular array is not flat at the borders, there is no # correct way here. We just subtract 2PI. # 2019-04-18: It turns out that on Windows, this is not the case. # Hence, we only subtract 2PI if the minimum of the array is above # 2PI.. if ryt.imag.min() > twopi: ryt.imag -= twopi assert np.allclose(np.array(ryt).flatten().view( float), get_results(myframe)) # Check the 3D result with the 2D result. They should be the same except # for a multiple of 2PI offset, because odtbrain._align_unwrapped # subtracts the background such that the median phase change is closest # to zero. # 2D A ryt2d = odtbrain.sinogram_as_rytov(sino[:, :, 0]) assert np.allclose(0, negative_modulo_rest_imag( ryt2d - ryt[:, :, 0], twopi).view(float), atol=1e-6) # 2D B ryt2d2 = odtbrain.sinogram_as_rytov(sino[:, 0, :]) assert np.allclose(0, negative_modulo_rest_imag( ryt2d2 - ryt[:, 0, :], twopi).view(float), atol=1e-6)
def test_correct_reproduce(): myframe = sys._getframe() sino, angles = create_test_sino_3d(Nx=10, Ny=10) p = get_test_parameter_set(1)[0] sryt = odtbrain.sinogram_as_rytov(uSin=sino, u0=1, align=False) f = odtbrain.backpropagate_3d(sryt, angles, padval=0, dtype=np.float64, copy=False, **p) fc = odtbrain.apple.correct(f=f, res=p["res"], nm=p["nm"], enforce_envelope=.95, max_iter=100, min_diff=0.01) fo = cutout(fc) fo = np.array(fo, dtype=np.complex128) if WRITE_RES: write_results(myframe, fo) data = fo.flatten().view(float) assert np.allclose(data, get_results(myframe))
sino, angles, phantom, cfg = \ load_data("fdtd_3d_sino_A180_R6.500.tar.lzma") A = angles.shape[0] print("Example: Backpropagation from 3D FDTD simulations") print("Refractive index of medium:", cfg["nm"]) print("Measurement position from object center:", cfg["lD"]) print("Wavelength sampling:", cfg["res"]) 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
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)) am = np.abs(sino/u0)
## 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()
nmed = cfg["nmed"] ncyl = cfg["ncyl"] 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.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 % .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,
# t_SinoDeembeding = t_SinoInterp # t_Reconstruction = iradon_sart(np.abs(t_SinoInterp.transpose()) - np.abs(t_SinoBack.transpose()), theta=t_Theta, relaxation=0.1) # t_Reconstruction = iradon_sart(np.abs(t_Sino.transpose()), theta=t_Theta, relaxation=0.1) print(np.min(np.abs(t_SinoDeembeding))) print(np.max(np.abs(t_SinoDeembeding))) print(np.mean(np.abs(t_SinoDeembeding))) # t_Reconstruction = iradon_sart(np.abs(t_SinoDeembeding.transpose()), theta=t_Theta, relaxation=0.01) # t_Reconstruction = iradon_sart(np.abs(t_SinoDeembeding.transpose())*-1, theta=t_Theta, relaxation=0.01, clip=[0.02,0.04]) # for i in range(50): # t_Reconstruction = iradon_sart(np.abs(t_SinoDeembeding.transpose()), theta=t_Theta, relaxation=0.01) # t_Reconstruction = iradon(t_SinoDeembeding.transpose(), filter="ramp" ,interpolation="cubic", circle=False, theta=t_Theta) # u_sinR = odt.sinogram_as_rytov(t_SinoSudutInterp / t_SinoBack) u_sinR = odt.sinogram_as_rytov(t_SinoDeembeding) 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) ## Interpolasi multivariate # t_InterpVal = 100 # x = np.linspace(0, t_SensorInterp-1, t_SensorInterp) # y = np.linspace(0, t_SensorInterp-1, t_SensorInterp) # X, Y = np.meshgrid(x, y) # px = np.random.choice(x, t_InterpVal) # py = np.random.choice(y, t_InterpVal) # print(t_Reconstruction.flatten().shape)
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) # prepare plot vmin = np.min(np.array([phantom, nB.real, nR50.real, nR.real]))
nmed = cfg["nmed"] ncyl = cfg["ncyl"] 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 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)
medium_index = 1.335 # initialize cell phantom phantom = cellsino.phantoms.SimpleCell() # initialize sinogram with geometric parameters 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)
## Interpolation # t_NX, t_NY = t_Data.shape # t_X = t_Data[0] # t_DataInterp ## Backprojection # t_Reconstruction = iradon_sart(t_Data) # t_Reconstruction = iradon(t_Data, filter="ramp" ,interpolation="linear", circle=True, output_size=73*2) # for i in range(20): # t_Reconstruction = iradon_sart(t_Data, image=t_Reconstruction) ## Backpropagation # u_sinR = odt.sinogram_as_rytov(t_SinoInterp.reshape(t_SudutProj, t_SensorInterp), u0=t_DataBackground) # u_sinR = odt.sinogram_as_rytov(t_SinoInterp.reshape(t_SudutProj, t_SensorInterp)) u_sinR = odt.sinogram_as_rytov(t_SinoInterp) # for x_back in range(72): # for y_back in range(72): # if t_DataBackground[x_back,y_back] == 0. : # t_DataBackground[x_back, y_back] = 1. # u_sinR = t_SinoInterp.reshape(t_SudutProj, t_SensorInterp)/t_DataBackground # u_sinR = t_SinoInterp.reshape(t_SudutProj, t_SensorInterp) t_Theta = np.linspace(0., 360., t_SudutProj, endpoint=False) # t_Reconstruction = iradon(t_DataInterp.transpose(), filter="ramp" ,interpolation="linear", circle=True, theta=t_Theta) # t_Reconstruction = iradon(t_DataInterp.transpose(), filter="ramp" ,interpolation="linear", circle=False, theta=t_Theta) # t_Reconstruction = radontea.backproject(t_DataInterp.transpose(), t_Theta) t_Reconstruction = radontea.fan.radon_fan(t_DataInterp.transpose(), det_size=9, det_spacing=2) print(t_Reconstruction.shape) # t_Reconstruction = iradon_sart(t_DataInterp.transpose(), theta=t_Theta, relaxation=0.01) # for i in range(10):
if autofocus: Ex, d = nrefocus.autofocus(Ex, cfg["nm"], cfg["res"], (-1.5*cfg["lD"]*cfg["res"],0), ret_d=True) lD = 0 print("Autofocusing distance [px]: ", d) else: lD = cfg["lD"]*cfg["res"] # 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()
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
cfg = {} for l in info.readlines(): l = l.decode() if l.count("=") == 1: key, val = l.split("=") cfg[key.strip()] = float(val.strip()) print("Example: Backpropagation from 2d FDTD simulations") print("Refractive index of medium:", cfg["nm"]) print("Measurement position from object center:", cfg["lD"]) print("Wavelength sampling:", cfg["res"]) print("Performing backpropagation.") ## 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"])
# Reconstruction angles angles = np.linspace(0, 2 * np.pi, A, endpoint=False) # Perform focusing Ex = nrefocus.refocus( Ex, d=-cfg["lD"] * cfg["res"], nm=cfg["nm"], res=cfg["res"], ) # Create sinogram 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))