def part_sample(D, s_min, s_max, gap_d, gap_s): # s_min = 44 # s_max= 84 # gap_d = 3 # gap_s = 4 node_s1 = np.arange(0, s_min, gap_s) node_s2 = np.arange(s_max, nr, gap_s) node_d = np.arange(s_min, s_max, gap_d) jitter_s1 = np.random.randint(gap_s, size=node_s1.size) jitter_s1[-1] = np.random.randint(s_min - node_s1[-1]) jitter_s2 = np.random.randint(gap_s, size=node_s2.size) jitter_s2[-1] = np.random.randint(nr - node_s2[-1]) jitter_d = np.random.randint(gap_d, size=node_d.size) jitter_d[-1] = np.random.randint(s_max - node_d[-1]) jitter_d = 0 # regular sampling in the denser part # jitter_s1= 0 # jitter_s2= 0 idr = np.concatenate( (node_s1 + jitter_s1, node_d + jitter_d, node_s2 + jitter_s2), axis=None) cod = np.arange(0, nt * nr).reshape(nt, nr) idx = cod[:, idr].flatten() R = pylops.Restriction(N, idx) D_dec = R * D_sqz D_adj = R.H * D_dec return D_dec, D_adj, idr.size
def load_sample(D, file_name): idr = np.load('%s.npy' % file_name) cod = np.arange(0, nt * nr).reshape(nt, nr) idx = cod[:, idr].flatten() R = pylops.Restriction(N, idx) D_dec = (R * D.flatten()).reshape(nt, idr.szie) D_adj = (R.H * D_dec).reshape(nt, nr) return D_dec, D_adj, idr.size
def re_sample(D, gap): nt, nr = D.size idr = np.arange(0, nr, gap) cod = np.arange(0, nt * nr).reshape(nt, nr) idx = cod[:, idr].flatten() R = pylops.Restriction(N, idx) D_dec = (R * D.flatten()).reshape(nt, idr.szie) D_adj = (R.H * D_dec).reshape(nt, nr) return D_dec, D_adj, idr.size
def irre_sample(D, gap): nt, nr = D.size interval = 6 node = np.arange(0, nr, interval) jitter = np.random.randint(interval, size=node.size - 1) jitter_last = np.random.randint(nr - node[-1]) jitter = np.concatenate((jitter, jitter_last), axis=None) idr = node + jitter cod = np.arange(0, nt * nr).reshape(nt, nr) idx = cod[:, idr].flatten() R = pylops.Restriction(N, idx) D_dec = (R * D.flatten()).reshape(nt, idr.szie) D_adj = (R.H * D_dec).reshape(nt, nr) return D_dec, D_adj, idr.size
def SubSampling(size: int, sampling_indices: Union[np.ndarray, list], shape: Optional[tuple] = None, axis: int = 0, dtype: str = 'float64', inplace: bool = True): r""" Subsampling operator. Extract subset of values from input array at locations ``sampling_indices`` in forward mode and place those values at locations ``sampling_indices`` in an otherwise zero array in adjoint mode. Parameters ---------- size : int Size of input array. sampling_indices : :obj:`list` or :obj:`numpy.ndarray` Integer indices of samples for data selection. shape : tuple Shape of input array (``None`` if only one dimension is available). axis : int When ``shape`` is not ``None``, axis along which subsampling is applied. dtype : str Type of elements in input array. inplace : bool Work inplace (``True``) or make a new copy (``False``). By default, data is a reference to the model (in forward) and model is a reference to the data (in adjoint). Returns ------- :py:class:`~pycsou.linop.base.PyLopLinearOperator` The subsampling operator. Raises ------ ValueError If shape and size do not match. Examples -------- .. testsetup:: import numpy as np from pycsou.linop.sampling import SubSampling .. doctest:: >>> x = np.arange(9).reshape(3,3) >>> sampling_indices = [0,2] >>> SamplingOp=SubSampling(size=x.size, sampling_indices=sampling_indices) >>> SamplingOp * x.reshape(-1) array([0, 2]) >>> SamplingOp.adjoint(SamplingOp* x.reshape(-1)).reshape(x.shape) array([[0., 0., 2.], [0., 0., 0.], [0., 0., 0.]]) >>> SamplingOp=SubSampling(size=x.size, sampling_indices=sampling_indices, shape=x.shape, axis=1) >>> (SamplingOp * x.reshape(-1)).reshape(x.shape[1], len(sampling_indices)) array([[0, 2], [3, 5], [6, 8]]) >>> SamplingOp.adjoint(SamplingOp* x.reshape(-1)).reshape(x.shape) array([[0., 0., 2.], [3., 0., 5.], [6., 0., 8.]]) Notes ----- Subsampling of a subset of :math:`L` values at locations ``sampling_indices`` from an input vector :math:`\mathbf{x}` of size :math:`N` can be expressed as: .. math:: y_i = x_{n_i} \quad \forall i=1,2,...,L, where :math:`\mathbf{n}=[n_1, n_2,..., n_L]` is a vector containing the indeces of the original array at which samples are taken. Conversely, in adjoint mode the available values in the data vector :math:`\mathbf{y}` are placed at locations :math:`\mathbf{n}=[n_1, n_2,..., n_L]` in the model vector: .. math:: x_{n_i} = y_i \quad \forall i=1,2,...,L and :math:`x_{j}=0 \,\forall j \neq n_i` (i.e., at all other locations in input vector). See Also -------- :py:class:`~pycsou.linop.sampling.Masking`, :py:class:`~pycsou.linop.sampling.Downsampling` """ PyLop = pylops.Restriction(M=size, iava=sampling_indices, dims=shape, dir=axis, dtype=dtype, inplace=inplace) return PyLopLinearOperator(PyLop=PyLop, is_symmetric=False, is_dense=False, is_sparse=False)
axs[0].set_title('Data(frequency domain)') axs[1].plot(t, x, 'k', LineWidth=2) axs[1].set_title('Data(time domain)') axs[1].axis('tight') ############################################################################### # We now define the locations at which the signal will be sampled. # subsampling locations perc_subsampling = 0.2 Nsub = int(np.round(N * perc_subsampling)) iava = np.sort(np.random.permutation(np.arange(N))[:Nsub]) # Create restriction operator Rop = pylops.Restriction(N, iava, dtype='float64') y = Rop * x ymask = Rop.mask(x) # Visualize data fig = plt.figure(figsize=(12, 4)) plt.plot(t, x, 'k', lw=3) plt.plot(t, x, '.k', ms=20, label='all samples') plt.plot(t, ymask, '.g', ms=15, label='available samples') plt.legend() plt.title('Data restriction') ############################################################################### # To start let's consider the simplest *'solver'*, i.e., *least-square inversion # without regularization*. We aim here to minimize the following cost function:
############################################################################### # To start we import a 2d image and define our restriction operator to irregularly and randomly # sample the image for 30% of the entire grid im = np.load("../testdata/python.npy")[:, :, 0] Nz, Nx = im.shape N = Nz * Nx # Subsample signal perc_subsampling = 0.2 Nsub2d = int(np.round(N * perc_subsampling)) iava = np.sort(np.random.permutation(np.arange(N))[:Nsub2d]) # Create operators and data Rop = pylops.Restriction(N, iava, dtype="float64") D2op = pylops.Laplacian((Nz, Nx), weights=(1, 1), dtype="float64") x = im.ravel() y = Rop * x y1 = Rop.mask(x) ############################################################################### # We will now use two different routines from our optimization toolbox # to estimate our original image in the regular grid. xcg_reg_lop = pylops.optimization.leastsquares.NormalEquationsInversion( Rop, [D2op], y, epsRs=[np.sqrt(0.1)], returninfo=False,
plt.legend() plt.title("TV inversion") ############################################################################### # Finally, we repeat the same exercise on a 2-dimensional image. In this case # we mock a medical imaging problem: the data is created by appling a 2D # Fourier Transform to the input model and by randomly sampling 60% of # its values. x = np.load("../testdata/optimization/shepp_logan_phantom.npy") x = x / x.max() ny, nx = x.shape perc_subsampling = 0.6 nxsub = int(np.round(ny * nx * perc_subsampling)) iava = np.sort(np.random.permutation(np.arange(ny * nx))[:nxsub]) Rop = pylops.Restriction(ny * nx, iava, dtype=np.complex128) Fop = pylops.signalprocessing.FFT2D(dims=(ny, nx)) n = np.random.normal(0, 0.0, (ny, nx)) y = Rop * Fop * (x.ravel() + n.ravel()) yfft = Fop * (x.ravel() + n.ravel()) yfft = np.fft.fftshift(yfft.reshape(ny, nx)) ymask = Rop.mask(Fop * (x.ravel()) + n.ravel()) ymask = ymask.reshape(ny, nx) ymask.data[:] = np.fft.fftshift(ymask.data) ymask.mask[:] = np.fft.fftshift(ymask.mask) fig, axs = plt.subplots(1, 3, figsize=(14, 5)) axs[0].imshow(x, vmin=0, vmax=1, cmap="gray") axs[0].set_title("Model")
# Load image X = misc.ascent() X = X/np.max(X) ny, nx = X.shape ############################################################################### # We can now define a :class:`pylops.Restriction` operator and look at how # the eigenvalues of our image change when we remove some of its sample. # Restriction operator sub = 0.4 nsub = int(ny*nx*sub) iava = np.random.permutation(np.arange(ny*nx))[:nsub] Rop = pylops.Restriction(ny*nx, iava) # Data y = Rop * X.ravel() # Masked data Y = (Rop.H * Rop * X.ravel()).reshape(ny, nx) # SVD of true and masked data Ux, Sx, Vhx = np.linalg.svd(X, full_matrices=False) Uy, Sy, Vhy = np.linalg.svd(Y, full_matrices=False) plt.figure() plt.semilogy(Sx, 'k', label=r'$||X||_*$=%.2f' % np.sum(Sx)) plt.semilogy(Sy, 'r', label=r'$||Y||_*$=%.2f' % np.sum(Sy)) plt.legend()
# model _, x = linear2d(xaxis, taxis, v, t0_m, theta_m, amp_m, wav) ############################################################################### # We can now define the spatial locations along which the data has been # sampled. In this specific example we will assume that we have access only to # 40% of the 'original' locations. perc_subsampling = 0.6 nxsub = int(np.round(par['nx'] * perc_subsampling)) iava = np.sort(np.random.permutation(np.arange(par['nx']))[:nxsub]) # restriction operator Rop = pylops.Restriction(par['nx'] * par['nt'], iava, dims=(par['nx'], par['nt']), dir=0, dtype='float64') # data y = Rop * x.ravel() y = y.reshape(nxsub, par['nt']) # mask ymask = Rop.mask(x.flatten()) # inverse xinv = Rop / y.ravel() xinv = xinv.reshape(par['nx'], par['nt']) fig, axs = plt.subplots(1, 2, sharey=True, figsize=(5, 4))
# model _, x = linear2d(xaxis, taxis, v, t0_m, theta_m, amp_m, wav) ############################################################################### # We can now define the spatial locations along which the data has been # sampled. In this specific example we will assume that we have access only to # 40% of the 'original' locations. perc_subsampling = 0.6 nxsub = int(np.round(par["nx"] * perc_subsampling)) iava = np.sort(np.random.permutation(np.arange(par["nx"]))[:nxsub]) # restriction operator Rop = pylops.Restriction(par["nx"] * par["nt"], iava, dims=(par["nx"], par["nt"]), dir=0, dtype="float64") # data y = Rop * x.ravel() y = y.reshape(nxsub, par["nt"]) # mask ymask = Rop.mask(x.ravel()) # inverse xinv = Rop / y.ravel() xinv = xinv.reshape(par["nx"], par["nt"]) fig, axs = plt.subplots(1, 2, sharey=True, figsize=(5, 4))
#node = np.arange(0,nr,interval) #jitter = np.random.randint(interval,size=node.size-1) #jitter_last = np.random.randint(nr - node[-1]) #jitter = np.concatenate((jitter,jitter_last),axis=None) #idr = node + jitter idr = np.load('idr_14.npy') N = nt * nr * ns cod = np.arange(0, N).reshape(nt, nr, ns) #idr = np.arange(0,nr,3) #ids = np.arange(0,ns,3) idrn = cod[:, idr, :] idx = idrn[:, :, idr].flatten() R = pylops.Restriction(N, idx) D_dec = R * ND.flatten() D_adj = (R.H * D_dec).reshape(nt, nr, ns) D1_r_dec = np.real(R * (D1_r.flatten())) D1_s_dec = np.real(R * (D1_s.flatten())) D2_r_dec = np.real(R * (D2_r.flatten())) D2_s_dec = np.real(R * (D2_s.flatten())) D1_rs_dec = np.real(R * (D1_rs.flatten())) D1sD2r_dec = np.real(R * (D1sD2r.flatten())) D2sD1r_dec = np.real(R * (D2sD1r.flatten())) D2sD2r_dec = np.real(R * (D2sD2r.flatten())) Forward = pylops.VStack([ R * mask_tt * F.H * mask_fre, R * mask_tt * F.H * D1op_r * mask_fre, R * mask_tt * F.H * D1op_s * mask_fre,
x = x + np.sin(2*np.pi*freq*t) ############################################################################### # First of all, we subsample the signal at random locations and we retain 40% # of the initial samples. perc_subsampling = 0.4 ntsub = int(np.round(nt*perc_subsampling)) isample = np.arange(nt) iava = np.sort(np.random.permutation(np.arange(nt))[:ntsub]) ############################################################################### # We then create the restriction and interpolation operators and display # the original signal as well as the subsampled signal. Rop = pylops.Restriction(nt, iava, dtype='float64') NNop, iavann = pylops.signalprocessing.Interp(nt, iava + 0.4, kind='nearest', dtype='float64') LIop, iavali = pylops.signalprocessing.Interp(nt, iava+0.4, kind='linear', dtype='float64') SIop, iavasi = pylops.signalprocessing.Interp(nt, iava + 0.4, kind='sinc', dtype='float64') y = Rop*x ynn = NNop*x yli = LIop*x ysi = SIop*x ymask = Rop.mask(x) # Visualize data fig = plt.figure(figsize=(15, 5)) plt.plot(isample, x, '.-k', lw=3, ms=10, label='all samples')