def plot(method, strength=None): # test distribution source = SampleImage(n=2 * rmax - 1).image / scale Isrc, _ = Ibeta(source) Inorm = (Isrc**2).sum() # simulated projection fith Poissonian noise proj, _ = rbasex_transform(source, direction='forward') proj[proj < 0] = 0 proj = np.random.RandomState(0).poisson(proj) # (reproducible, see NEP 19) # reconstructed image and intensity if strength is None: reg = method else: reg = (method, strength) im, distr = rbasex_transform(proj, reg=reg) I, _ = distr.Ibeta() # plot... fig = plt.figure(figsize=(7, 3.5), frameon=False) # image plt.subplot(121) fig = plt.imshow(rescaleI(im), vmin=-vlim, vmax=vlim, cmap='bwr') plt.axis('off') plt.text(0, 2 * rmax, method, va='top') # intensity ax = plt.subplot2grid((3, 2), (0, 1), rowspan=2) ax.plot(Isrc, c='r', lw=1) ax.plot(I, c='k', lw=1) ax.set_xlim((0, rmax)) ax.set_ylim(Ilim) # error plt.subplot(326) plt.axhline(c='r', lw=1) plt.plot(I - Isrc, c='b', lw=1) plt.xlim((0, rmax)) plt.ylim(dIlim) # finish plt.subplots_adjust(left=0, right=0.97, wspace=0.1, bottom=0.08, top=0.98, hspace=0.5)
def test_rbasex_zeros(): rmax = 11 n = 2 * rmax - 1 im = np.zeros((n, n), dtype='float') fwd_im, fwd_distr = rbasex_transform(im, direction='forward') assert fwd_im.shape == (n, n) assert fwd_distr.r.shape == (rmax,) inv_im, inv_distr = rbasex_transform(im) assert inv_im.shape == (n, n) assert inv_distr.r.shape == (rmax,)
def rmse(method, strengths=None): if strengths is None: _, distr = rbasex_transform(proj, reg=method, out=None) I, _ = distr.Ibeta() return ((I - Isrc)**2).sum() / Inorm err = np.empty_like(strengths, dtype=float) for n, strength in enumerate(strengths): _, distr = rbasex_transform(proj, reg=(method, strength), out=None) I, _ = distr.Ibeta() err[n] = ((I - Isrc)**2).sum() / Inorm return err
def test_rbasex_gaussian(): """Check an isotropic gaussian solution for rBasex""" rmax = 100 sigma = 30 n = 2 * rmax - 1 ref = GaussianAnalytical(n, rmax, symmetric=True, sigma=sigma) # images as direct products src = ref.func * ref.func[:, None] proj = ref.abel * ref.func[:, None] # (vertical is not Abel-transformed) fwd_im, fwd_distr = rbasex_transform(src, direction='forward') # whole image assert_allclose(fwd_im, proj, rtol=0.02, atol=0.001) # radial intensity profile (without r = 0) assert_allclose(fwd_distr.harmonics()[0, 1:], ref.abel[rmax:], rtol=0.02, atol=5e-4) inv_im, inv_distr = rbasex_transform(proj) # whole image assert_allclose(inv_im, src, rtol=0.02, atol=0.02) # radial intensity profile (without r = 0) assert_allclose(inv_distr.harmonics()[0, 1:], ref.func[rmax:], rtol=0.02, atol=1e-4)
def run_orders(odd=False): """ Test angular orders using Gaussian peaks by comparison with hansenlaw. """ maxorder = 6 sigma = 5.0 # Gaussian sigma step = 6 * sigma # distance between peak centers for order in range(maxorder + 1): rmax = int((order + 2) * step) if odd: if order == 0: continue # 0th order cannot be odd height = 2 * rmax + 1 else: # even only if order % 2: continue # skip odd height = rmax + 1 # coordinates (Q0 or right half): x = np.arange(float(rmax + 1)) y = rmax - np.arange(float(height))[:, None] # radius r = np.sqrt(x**2 + y**2) # cos, sin r[rmax, 0] = np.inf c = y / r s = x / r r[rmax, 0] = 0 # Gaussian peak with one cossin angular term def peak(i): m = i # cos power k = (order - m) & ~1 # sin power (round down to even) return c ** m * s ** k * \ np.exp(-(r - (i + 1) * step) ** 2 / (2 * sigma**2)) # create source distribution src = peak(0) for i in range(1, order + 1): if not odd and i % 2: continue # skip odd src += peak(i) # reference forward transform abel = hansenlaw_transform(src, direction='forward', hold_order=1) param = ', order = {}, odd = {}, '.format(order, odd) # test forward transform for mode in ['clean', 'cached']: if mode == 'clean': cache_cleanup() proj, _ = rbasex_transform(src, origin=(rmax, 0), order=order, odd=odd, direction='forward', out='fold') assert_allclose(proj, abel, rtol=0.003, atol=0.4, err_msg='-> forward' + param + mode) # test inverse transforms for reg in [None, ('L2', 1), ('diff', 1), ('SVD', 1 / rmax)]: for mode in ['clean', 'cached']: if mode == 'clean': cache_cleanup() recon, _ = rbasex_transform(abel, origin=(rmax, 0), order=order, odd=odd, reg=reg, out='fold') recon[rmax-2:rmax+3, :2] = 0 # exclude pixels near center assert_allclose(recon, src, atol=0.03, err_msg='-> reg = ' + str(reg) + param + mode)
def run_out(odd=False): """ Test some output shapes. """ sigma = 5.0 # Gaussian sigma step = int(6 * sigma) # distance between peak centers rmax = (2 + 2) * step size = 2 * rmax + 1 # coordinates (full image): x = np.arange(float(size)) - rmax y = rmax - np.arange(float(size))[:, None] # radius r = np.sqrt(x**2 + y**2) # cos r[rmax, rmax] = np.inf c = y / r r[rmax, rmax] = 0 # Gaussian peak with one cos^n angular term def peak(i): n = i if odd else 2 * i return c ** n * \ np.exp(-(r - (i + 1) * step) ** 2 / (2 * sigma**2)) # create source distribution src = peak(0) + peak(1) # reference forward transform abel = Transform(src, direction='forward', method='hansenlaw', transform_options={'hold_order': 1}).transform param = '-> odd = {}, '.format(odd) # Test forward transform: # rmax < MIN => larger 'same' proj, _ = rbasex_transform(src, rmax=rmax - step, odd=odd, direction='forward', out='same') assert_allclose(proj, abel, rtol=0.005, atol=0.2, err_msg=param + 'rmax < MIN, out = same') # cropped, rmax = HOR < VER -> same crop = (slice(3 * step, -step // 2), slice(3 * step, -step)) proj, _ = rbasex_transform(src[crop], origin=(step, step), odd=odd, direction='forward', out='same') assert_allclose(proj, abel[crop], rtol=0.005, atol=0.2, err_msg=param + 'rmax = HOR < VER, out = same') # cropped, rmax = VER < HOR -> same crop = (slice(step, -3 * step), slice(3 * step, -step // 2)) proj, _ = rbasex_transform(src[crop], origin=(3 * step, step), odd=odd, direction='forward', out='same') assert_allclose(proj, abel[crop], rtol=0.0003, atol=0.3, err_msg=param + 'rmax = VER < HOR, out = same') # cropped, rmax = VER > HOR -> same crop = (slice(3 * step, -step // 2), slice(3 * step, -step)) proj, _ = rbasex_transform(src[crop], origin=(step, step), rmax='MAX', odd=odd, direction='forward', out='same') assert_allclose(proj, abel[crop], rtol=0.005, atol=0.2, err_msg=param + 'rmax = VER > HOR, out = same') # cropped, rmax = HOR > VER -> same crop = (slice(step, -3 * step), slice(3 * step, -step // 2)) proj, _ = rbasex_transform(src[crop], origin=(3 * step, step), rmax='MAX', odd=odd, direction='forward', out='same') assert_allclose(proj, abel[crop], rtol=0.0003, atol=0.3, err_msg=param + 'rmax = HOR > VER, out = same') # cropped, rmax = rmax -> full crop = (slice(3 * step, -step), slice(3 * step, -step)) # (in multiples of step: VER^2 + HOR^2 = 2 * 3^2 > rmax^2 = 4^2) proj, _ = rbasex_transform(src[crop], origin=(step, step), rmax=rmax, odd=odd, direction='forward', out='full') assert_allclose(proj, abel, rtol=0.002, atol=0.3, err_msg=param + 'rmax = rmax, out = full')
def test_rbasex_pos(): """ Test positive regularization as in run_orders(). """ sigma = 5.0 # Gaussian sigma step = 6 * sigma # distance between peak centers for order in [0, 1, 2, 4, 6]: rmax = int((order + 2) * step) if order == 1: # odd rmax += int(step) # 3 peaks instead of 2 height = 2 * rmax + 1 else: # even only height = rmax + 1 # coordinates (Q0 or right half): x = np.arange(float(rmax + 1)) y = rmax - np.arange(float(height))[:, None] # radius r = np.sqrt(x**2 + y**2) # cos, sin r[rmax, 0] = np.inf c = y / r s = x / r r[rmax, 0] = 0 # Gaussian peak with one cossin angular term def peak(i, isotropic=False): if isotropic: return np.exp(-(r - (i + 1) * step) ** 2 / (2 * sigma**2)) m = i # cos power k = (order - m) & ~1 # sin power (round down to even) return c ** m * s ** k * \ np.exp(-(r - (i + 1) * step) ** 2 / (2 * sigma**2)) # create source distribution src = peak(0) if order == 1: # special case src += (1 + c) * peak(1, True) # 1 + cos >= 0 src += (1 - c) * peak(2, True) # 1 - cos >= 0 else: # other even orders for i in range(2, order + 1, 2): src += peak(i) # array for nonnegativity test (with some tolerance) zero = np.full_like(src, -1e-15) # reference forward transform abel = hansenlaw_transform(src, direction='forward', hold_order=1) # with some noise abel += 0.05 * np.random.RandomState(0).rand(*abel.shape) param = '-> order = {}, '.format(order) # test inverse transform for mode in ['clean', 'cached']: if mode == 'clean': cache_cleanup() recon, _ = rbasex_transform(abel, origin=(rmax, 0), order=order, reg='pos', out='fold') recon[rmax-3:rmax+4, :2] = 0 # exclude pixels near center assert_allclose(recon, src, atol=0.05, err_msg=param + mode) # check nonnegativity assert_array_less(zero, recon)
import numpy as np import matplotlib.pyplot as plt from abel.tools.analytical import SampleImage from abel.tools.vmi import Ibeta from abel.rbasex import rbasex_transform # test distribution rmax = 200 scale = 10000 source = SampleImage(n=2 * rmax - 1).image / scale Isrc, _ = Ibeta(source) Inorm = (Isrc**2).sum() # simulated projection fith Poissonian noise proj, _ = rbasex_transform(source, direction='forward') proj[proj < 0] = 0 proj = np.random.RandomState(0).poisson(proj) # (reproducible, see NEP 19) # calculate relative RMS error for given regularization parameters def rmse(method, strengths=None): if strengths is None: _, distr = rbasex_transform(proj, reg=method, out=None) I, _ = distr.Ibeta() return ((I - Isrc)**2).sum() / Inorm err = np.empty_like(strengths, dtype=float) for n, strength in enumerate(strengths): _, distr = rbasex_transform(proj, reg=(method, strength), out=None) I, _ = distr.Ibeta()
dmask = 1 * (mask1 - binary_erosion(mask1, structure=brush)) + \ 2 * (mask2 - binary_erosion(mask2, structure=brush)) + \ 3 * (mask3 - binary_erosion(mask3, structure=brush)) dmask[dmask == 0] = np.nan from matplotlib.colors import ListedColormap rgb = ListedColormap(['#CC0000', '#00AA00', '#0055FF']) plt.imshow(dmask, extent=(0, w, 0, h), cmap=rgb, interpolation='nearest') # Analyze the left part and plot results plt.subplot(222) plt.title('Distributions: left image') # the reconstructed image is not used in this example, so it is not created; # also notice that order=0 is enough for this totally isotropic case _, distr = rbasex_transform(im, origin=origin1, rmax=r1, order=0, weights=mask1, out=None) r, I = distr.rIbeta() plt.plot(r, I, c=rgb(0), label='$I(r)$') plt.legend() plt.autoscale(enable=True, tight=True) # Analyze the central part and plot results plt.subplot(223) plt.title('Distributions: central image') # here the default order=2 is needed and used _, distr = rbasex_transform(im, origin=origin2, rmax=r2, weights=mask2,
R = 150 # image radius N = 2 * R + 1 # full image width and height block_r = 20 # beam-block disk radius block_w = 5 # beam-block holder width vlim = 3.6 # intensity limits for images ylim = (-1.3, 2.7) # limits for plots # create source distribution and its profiles for reference source = SampleImage(N).func / 100 r_src, P0_src, P2_src = rharmonics(source) # simulate experimental image: # projection im, _ = rbasex_transform(source, direction='forward') # Poissonian noise im[im < 0] = 0 im = np.random.RandomState(0).poisson(im) # image coordinates im_x = np.arange(float(N)) - R im_y = R - np.arange(float(N))[:, None] im_r = np.sqrt(im_x**2 + im_y**2) # simulate beam-block shadow im = im / (1 + np.exp(-(im_r - block_r))) im[:R] *= 1 / (1 + np.exp(-(np.abs(im_x) - block_w))) # create mask that fully covers beam-block shadow mask_r = block_r + 5 mask_w = block_w + 5 mask = np.ones_like(im)