예제 #1
0
 def test_08(self):
     N = 16
     M = 4
     Nd = 8
     X = np.random.randn(N, N, 1, 1, M)
     S = np.random.randn(N, N, 1)
     dt = np.float64
     opt = ccmod.ConvCnstrMODOptions(
         {'Verbose': False, 'MaxMainIter': 20,
          'BackTrack': {'Enabled': True},
          'DataType': dt})
     c = ccmod.ConvCnstrMOD(X, S, (Nd, Nd, M), opt=opt)
     c.solve()
     assert(c.X.dtype == dt)
     assert(c.Xf.dtype == sl.complex_dtype(dt))
     assert(c.Yf.dtype == sl.complex_dtype(dt))
예제 #2
0
 def test_05(self):
     N = 16
     M = 4
     Nd = 8
     X = np.random.randn(N, N, 1, 1, M)
     S = np.random.randn(N, N, 1)
     dt = np.float64
     opt = ccmod.ConvCnstrMOD.Options(
         {'Verbose': False, 'MaxMainIter': 20,
          'BackTrack': {'Enabled': True},
          'DataType': dt})
     c = ccmod.ConvCnstrMOD(X, S, (Nd, Nd, M), opt=opt)
     c.solve()
     assert c.X.dtype == dt
     assert c.Xf.dtype == sl.complex_dtype(dt)
     assert c.Yf.dtype == sl.complex_dtype(dt)
예제 #3
0
 def test_06(self):
     N = 16
     Nd = 5
     K = 2
     M = 4
     D = np.random.randn(Nd, Nd, M)
     s = np.random.randn(N, N, K)
     dt = np.float32
     opt = cbpdn.ConvBPDN.Options({'Verbose': False, 'MaxMainIter': 20,
                                   'BackTrack': {'Enabled': True},
                                   'DataType': dt})
     lmbda = 1e-1
     b = cbpdn.ConvBPDN(D, s, lmbda, opt=opt)
     b.solve()
     assert b.X.dtype == dt
     assert b.Xf.dtype == sl.complex_dtype(dt)
     assert b.Yf.dtype == sl.complex_dtype(dt)
예제 #4
0
    def __init__(self, D, S, lmbda, mu=0.0, opt=None, dimK=None, dimN=2):

        if opt is None:
            opt = ConvBPDNRecTV.Options()

        # Infer problem dimensions and set relevant attributes of self
        self.cri = cbpdn.ConvRepIndexing(D, S, dimK=dimK, dimN=dimN)

        # Call parent class __init__
        Nx = np.product(self.cri.shpX)
        yshape = list(self.cri.shpX)
        yshape[self.cri.axisM] += len(self.cri.axisN) * self.cri.Cd
        super(ConvBPDNRecTV, self).__init__(Nx, yshape, yshape,
                                                 S.dtype, opt)

        # Set l1 term scaling and weight array
        self.lmbda = self.dtype.type(lmbda)
        self.Wl1 = np.asarray(opt['L1Weight'], dtype=self.dtype)
        self.mu = self.dtype.type(mu)
        if hasattr(opt['TVWeight'], 'ndim') and opt['TVWeight'].ndim > 0:
            self.Wtv = np.asarray(opt['TVWeight'].reshape((1,)*(dimN+2) +
                                  opt['TVWeight'].shape), dtype=self.dtype)
        else:
            # Wtv is a scalar: no need to change shape
            self.Wtv = self.dtype.type(opt['TVWeight'])

        # Set penalty parameter
        self.set_attr('rho', opt['rho'], dval=(50.0*self.lmbda + 1.0),
                      dtype=self.dtype)

        # Set rho_xi attribute
        self.set_attr('rho_xi', opt['AutoRho','RsdlTarget'], dval=1.0,
                      dtype=self.dtype)

        # Reshape D and S to standard layout
        self.D = np.asarray(D.reshape(self.cri.shpD), dtype=self.dtype)
        self.S = np.asarray(S.reshape(self.cri.shpS), dtype=self.dtype)

        # Compute signal in DFT domain
        self.Sf = sl.rfftn(self.S, None, self.cri.axisN)

        self.Gf, GHGf = sl.GradientFilters(self.cri.dimN+3, self.cri.axisN,
                                           self.cri.Nv, dtype=self.dtype)

        # Initialise byte-aligned arrays for pyfftw
        self.YU = sl.pyfftw_empty_aligned(self.Y.shape, dtype=self.dtype)
        xfshp = list(self.cri.shpX)
        xfshp[dimN-1] = xfshp[dimN-1]//2 + 1
        self.Xf = sl.pyfftw_empty_aligned(xfshp,
                            dtype=sl.complex_dtype(self.dtype))

        self.setdict()
예제 #5
0
 def test_06(self):
     N = 16
     Nd = 5
     K = 2
     M = 4
     D = np.random.randn(Nd, Nd, M)
     s = np.random.randn(N, N, K)
     dt = np.float32
     opt = cbpdn.ConvBPDN.Options({
         'Verbose': False,
         'MaxMainIter': 20,
         'BackTrack': {
             'Enabled': True
         },
         'DataType': dt
     })
     lmbda = 1e-1
     b = cbpdn.ConvBPDN(D, s, lmbda, opt=opt)
     b.solve()
     assert (b.X.dtype == dt)
     assert (b.Xf.dtype == sl.complex_dtype(dt))
     assert (b.Yf.dtype == sl.complex_dtype(dt))
예제 #6
0
    def __init__(self, D, S, lmbda=None, opt=None, dimK=None, dimN=2):
        """
        Initialise a ConvBPDN object with problem parameters.

        This class supports an arbitrary number of spatial dimensions,
        `dimN`, with a default of 2. The input dictionary `D` is either
        `dimN` + 1 dimensional, in which case each spatial component
        (image in the default case) is assumed to consist of a single
        channel, or `dimN` + 2 dimensional, in which case the final
        dimension is assumed to contain the channels (e.g. colour
        channels in the case of images). The input signal set `S` is
        either `dimN` dimensional (no channels, only one signal), `dimN` + 1
        dimensional (either multiple channels or multiple signals), or
        `dimN` + 2 dimensional (multiple channels and multiple signals).
        Determination of problem dimensions is handled by
        :class:`.cnvrep.CSC_ConvRepIndexing`.


        |

        **Call graph**

        .. image:: _static/jonga/fista_cbpdn_init.svg
           :width: 20%
           :target: _static/jonga/fista_cbpdn_init.svg

        |


        Parameters
        ----------
        D : array_like
          Dictionary array
        S : array_like
          Signal array
        lmbda : float
          Regularisation parameter
        opt : :class:`ConvBPDN.Options` object
          Algorithm options
        dimK : 0, 1, or None, optional (default None)
          Number of dimensions in input signal corresponding to multiple
          independent signals
        dimN : int, optional (default 2)
          Number of spatial/temporal dimensions
        """

        # Set default options if none specified
        if opt is None:
            opt = ConvBPDN.Options()

        # Infer problem dimensions and set relevant attributes of self
        if not hasattr(self, 'cri'):
            self.cri = cr.CSC_ConvRepIndexing(D, S, dimK=dimK, dimN=dimN)

        # Set dtype attribute based on S.dtype and opt['DataType']
        self.set_dtype(opt, S.dtype)

        # Set default lambda value if not specified
        if lmbda is None:
            cri = cr.CSC_ConvRepIndexing(D, S, dimK=dimK, dimN=dimN)
            Df = sl.rfftn(D.reshape(cri.shpD), cri.Nv, axes=cri.axisN)
            Sf = sl.rfftn(S.reshape(cri.shpS), axes=cri.axisN)
            b = np.conj(Df) * Sf
            lmbda = 0.1 * abs(b).max()

        # Set l1 term scaling and weight array
        self.lmbda = self.dtype.type(lmbda)
        self.wl1 = np.asarray(opt['L1Weight'], dtype=self.dtype)

        # Call parent class __init__
        xshape = self.cri.shpX
        super(ConvBPDN, self).__init__(xshape, S.dtype, opt)
        if self.opt['BackTrack', 'Enabled']:
            self.L /= self.lmbda

        # Reshape D and S to standard layout
        self.D = np.asarray(D.reshape(self.cri.shpD), dtype=self.dtype)
        self.S = np.asarray(S.reshape(self.cri.shpS), dtype=self.dtype)

        # Compute signal in DFT domain
        self.Sf = sl.rfftn(self.S, None, self.cri.axisN)

        # Create byte aligned arrays for FFT calls
        xfshp = list(self.X.shape)
        xfshp[dimN - 1] = xfshp[dimN - 1] // 2 + 1
        self.Xf = sl.pyfftw_empty_aligned(xfshp,
                                          dtype=sl.complex_dtype(self.dtype))

        # Initialise auxiliary variable Yf
        self.Yf = sl.pyfftw_empty_aligned(xfshp,
                                          dtype=sl.complex_dtype(self.dtype))

        self.Ryf = -self.Sf

        self.Xf = sl.rfftn(self.X, None, self.cri.axisN)
        self.Yf = self.Xf
        self.store_prev()

        self.setdict()
예제 #7
0
파일: ccmodmd.py 프로젝트: eglxiang/sporco
    def __init__(self, Z, S, W, dsz, opt=None, dimK=None, dimN=2):
        """
        Initialise a ConvCnstrMODMaskDcplBase object with problem size
        and options.

        Parameters
        ----------
        Z : array_like
          Coefficient map array
        S : array_like
          Signal array
        W : array_like
          Mask array. The array shape must be such that the array is
          compatible for multiplication with input array S (see
          :func:`.cnvrep.mskWshape` for more details).
        dsz : tuple
          Filter support size(s)
        opt : :class:`ConvCnstrMODMaskDcplBase.Options` object
          Algorithm options
        dimK : 0, 1, or None, optional (default None)
          Number of dimensions in input signal corresponding to multiple
          independent signals
        dimN : int, optional (default 2)
          Number of spatial dimensions
        """

        # Set default options if none specified
        if opt is None:
            opt = ConvCnstrMODMaskDcplBase.Options()

        # Infer problem dimensions and set relevant attributes of self
        self.cri = cr.CDU_ConvRepIndexing(dsz, S, dimK=dimK, dimN=dimN)

        # Convert W to internal shape
        W = np.asarray(W.reshape(cr.mskWshape(W, self.cri)), dtype=S.dtype)

        # Reshape W if necessary (see discussion of reshape of S below)
        if self.cri.Cd == 1 and self.cri.C > 1:
            # In most cases broadcasting rules make it possible for W
            # to have a singleton dimension corresponding to a non-singleton
            # dimension in S. However, when S is reshaped to interleave axisC
            # and axisK on the same axis, broadcasting is no longer sufficient
            # unless axisC and axisK of W are either both singleton or both
            # of the same size as the corresponding axes of S. If neither of
            # these cases holds, it is necessary to replicate the axis of W
            # (axisC or axisK) that does not have the same size as the
            # corresponding axis of S.
            shpw = list(W.shape)
            swck = shpw[self.cri.axisC] * shpw[self.cri.axisK]
            if swck > 1 and swck < self.cri.C * self.cri.K:
                if W.shape[self.cri.axisK] == 1 and self.cri.K > 1:
                    shpw[self.cri.axisK] = self.cri.K
                else:
                    shpw[self.cri.axisC] = self.cri.C
                W = np.broadcast_to(W, shpw)
            self.W = W.reshape(W.shape[0:self.cri.dimN] +
                               (1, W.shape[self.cri.axisC] *
                                W.shape[self.cri.axisK], 1))
        else:
            self.W = W

        # Call parent class __init__
        Nx = self.cri.N * self.cri.Cd * self.cri.M
        CK = (self.cri.C if self.cri.Cd == 1 else 1) * self.cri.K
        shpY = list(self.cri.shpX)
        shpY[self.cri.axisC] = self.cri.Cd
        shpY[self.cri.axisK] = 1
        shpY[self.cri.axisM] += CK
        super(ConvCnstrMODMaskDcplBase,
              self).__init__(Nx, shpY, self.cri.axisM, CK, S.dtype, opt)

        # Reshape S to standard layout (Z, i.e. X in cbpdn, is assumed
        # to be taken from cbpdn, and therefore already in standard
        # form). If the dictionary has a single channel but the input
        # (and therefore also the coefficient map array) has multiple
        # channels, the channel index and multiple image index have
        # the same behaviour in the dictionary update equation: the
        # simplest way to handle this is to just reshape so that the
        # channels also appear on the multiple image index.
        if self.cri.Cd == 1 and self.cri.C > 1:
            self.S = S.reshape(self.cri.Nv + (1, self.cri.C * self.cri.K, 1))
        else:
            self.S = S.reshape(self.cri.shpS)
        self.S = np.asarray(self.S, dtype=self.dtype)

        # Create constraint set projection function
        self.Pcn = cr.getPcn(dsz,
                             self.cri.Nv,
                             self.cri.dimN,
                             self.cri.dimCd,
                             zm=opt['ZeroMean'])

        # Initialise byte-aligned arrays for pyfftw
        self.YU = sl.pyfftw_empty_aligned(self.Y.shape, dtype=self.dtype)
        xfshp = list(self.cri.Nv + (self.cri.Cd, 1, self.cri.M))
        xfshp[dimN - 1] = xfshp[dimN - 1] // 2 + 1
        self.Xf = sl.pyfftw_empty_aligned(xfshp,
                                          dtype=sl.complex_dtype(self.dtype))

        if Z is not None:
            self.setcoef(Z)
예제 #8
0
    def __init__(self, Z, S, dsz, opt=None, dimK=1, dimN=2):
        """Initialise a ConvCnstrMOD_Consensus object with problem
        parameters.  See :meth:`.ConvCnstrMODBase.__init__` for
        interface details.

        |

        **Call graph**

        .. image:: _static/jonga/ccmodcnsns_init.svg
           :width: 20%
           :target: _static/jonga/ccmodcnsns_init.svg
        """

        # Set default options if none specified
        if opt is None:
            opt = ConvCnstrMOD_Consensus.Options()

        # Infer problem dimensions and set relevant attributes of self
        self.cri = cr.CDU_ConvRepIndexing(dsz, S, dimK=dimK, dimN=dimN)

        # Handle possible reshape of channel axis onto multiple image axis
        # (see comment below)
        Nb = self.cri.K if self.cri.C == self.cri.Cd else \
             self.cri.C * self.cri.K
        admm.ADMMConsensus.__init__(self, Nb, self.cri.shpD, S.dtype, opt)

        # Set penalty parameter
        self.set_attr('rho', opt['rho'], dval=self.cri.K, dtype=self.dtype)

        # Reshape S to standard layout (Z, i.e. X in cbpdn, is assumed
        # to be taken from cbpdn, and therefore already in standard
        # form). If the dictionary has a single channel but the input
        # (and therefore also the coefficient map array) has multiple
        # channels, the channel index and multiple image index have
        # the same behaviour in the dictionary update equation: the
        # simplest way to handle this is to just reshape so that the
        # channels also appear on the multiple image index.
        if self.cri.Cd == 1 and self.cri.C > 1:
            self.S = S.reshape(self.cri.Nv + (1, ) +
                               (self.cri.C * self.cri.K, ) + (1, ))
        else:
            self.S = S.reshape(self.cri.shpS)
        self.S = np.asarray(self.S, dtype=self.dtype)

        # Compute signal S in DFT domain
        self.Sf = sl.rfftn(self.S, None, self.cri.axisN)

        # Create constraint set projection function
        self.Pcn = cr.getPcn(dsz,
                             self.cri.Nv,
                             self.cri.dimN,
                             self.cri.dimCd,
                             zm=opt['ZeroMean'])

        if Z is not None:
            self.setcoef(Z)

        self.X = sl.pyfftw_empty_aligned(self.xshape, dtype=self.dtype)
        # See comment on corresponding test in xstep method
        if self.cri.Cd > 1:
            self.YU = sl.pyfftw_empty_aligned(self.yshape, dtype=self.dtype)
        else:
            self.YU = sl.pyfftw_empty_aligned(self.xshape, dtype=self.dtype)
        xfshp = list(self.xshape)
        xfshp[dimN - 1] = xfshp[dimN - 1] // 2 + 1
        self.Xf = sl.pyfftw_empty_aligned(xfshp,
                                          dtype=sl.complex_dtype(self.dtype))
예제 #9
0
    def __init__(self, Z, S, dsz, opt=None, dimK=1, dimN=2):
        """Initialise a ConvCnstrMODBase object with problem parameters.

        This class supports an arbitrary number of spatial dimensions,
        `dimN`, with a default of 2. The input coefficient map array `Z`
        (usually labelled X, but renamed here to avoid confusion with
        the X and Y variables in the ADMM base class) is expected to
        be in standard form as computed by the ConvBPDN class.

        The input signal set `S` is either `dimN` dimensional (no
        channels, only one signal), `dimN` +1 dimensional (either
        multiple channels or multiple signals), or `dimN` +2 dimensional
        (multiple channels and multiple signals). Parameter `dimK`, with
        a default value of 1, indicates the number of multiple-signal
        dimensions in `S`:

        ::

          Default dimK = 1, i.e. assume input S is of form
            S(N0,  N1,   C,   K)  or  S(N0,  N1,   K)
          If dimK = 0 then input S is of form
            S(N0,  N1,   C,   K)  or  S(N0,  N1,   C)

        The internal data layout for S, D (X here), and X (Z here) is:
        ::

          dim<0> - dim<Nds-1> : Spatial dimensions, product of N0,N1,... is N
          dim<Nds>            : C number of channels in S and D
          dim<Nds+1>          : K number of signals in S
          dim<Nds+2>          : M number of filters in D

            sptl.      chn  sig  flt
          S(N0,  N1,   C,   K,   1)
          D(N0,  N1,   C,   1,   M)   (X here)
          X(N0,  N1,   1,   K,   M)   (Z here)

        The `dsz` parameter indicates the desired filter supports in the
        output dictionary, since this cannot be inferred from the
        input variables. The format is the same as the `dsz` parameter
        of :func:`.cnvrep.bcrop`.

        Parameters
        ----------
        Z : array_like
          Coefficient map array
        S : array_like
          Signal array
        dsz : tuple
          Filter support size(s)
        opt : ccmod.Options object
          Algorithm options
        dimK : int, optional (default 1)
          Number of dimensions for multiple signals in input S
        dimN : int, optional (default 2)
          Number of spatial dimensions
        """

        # Set default options if none specified
        if opt is None:
            opt = ConvCnstrMODBase.Options()

        # Infer problem dimensions and set relevant attributes of self
        self.cri = cr.CDU_ConvRepIndexing(dsz, S, dimK=dimK, dimN=dimN)

        # Call parent class __init__
        super(ConvCnstrMODBase, self).__init__(self.cri.shpD, S.dtype, opt)

        # Set penalty parameter
        self.set_attr('rho', opt['rho'], dval=self.cri.K, dtype=self.dtype)

        # Reshape S to standard layout (Z, i.e. X in cbpdn, is assumed
        # to be taken from cbpdn, and therefore already in standard
        # form). If the dictionary has a single channel but the input
        # (and therefore also the coefficient map array) has multiple
        # channels, the channel index and multiple image index have
        # the same behaviour in the dictionary update equation: the
        # simplest way to handle this is to just reshape so that the
        # channels also appear on the multiple image index.
        if self.cri.Cd == 1 and self.cri.C > 1:
            self.S = S.reshape(self.cri.Nv + (1, ) +
                               (self.cri.C * self.cri.K, ) + (1, ))
        else:
            self.S = S.reshape(self.cri.shpS)
        self.S = np.asarray(self.S, dtype=self.dtype)

        # Compute signal S in DFT domain
        self.Sf = sl.rfftn(self.S, None, self.cri.axisN)

        # Create constraint set projection function
        self.Pcn = cr.getPcn(dsz,
                             self.cri.Nv,
                             self.cri.dimN,
                             self.cri.dimCd,
                             zm=opt['ZeroMean'])

        # Create byte aligned arrays for FFT calls
        self.YU = sl.pyfftw_empty_aligned(self.Y.shape, dtype=self.dtype)
        xfshp = list(self.Y.shape)
        xfshp[dimN - 1] = xfshp[dimN - 1] // 2 + 1
        self.Xf = sl.pyfftw_empty_aligned(xfshp,
                                          dtype=sl.complex_dtype(self.dtype))

        if Z is not None:
            self.setcoef(Z)
예제 #10
0
 def rfftn_empty(shape, axes, dtype, order='C', n=None):
     ashp = list(shape)
     raxis = axes[-1]
     ashp[raxis] = ashp[raxis] // 2 + 1
     cdtype = spl.complex_dtype(dtype)
     return np.zeros(ashp, dtype=cdtype)
예제 #11
0
    def __init__(self, D, S, lmbda, mu=0.0, opt=None, dimK=None, dimN=2):
        """
        Initialise a ConvBPDNRecTV object with problem parameters.


        |

        **Call graph**

        .. image:: _static/jonga/cbpdnrtv_init.svg
           :width: 20%
           :target: _static/jonga/cbpdnrtv_init.svg

        |


        Parameters
        ----------
        D : array_like
          Dictionary matrix
        S : array_like
          Signal vector or matrix
        lmbda : float
          Regularisation parameter (l1)
        mu : float
          Regularisation parameter (gradient)
        opt : :class:`ConvBPDNRecTV.Options` object
          Algorithm options
        dimK : 0, 1, or None, optional (default None)
          Number of dimensions in input signal corresponding to multiple
          independent signals
        dimN : int, optional (default 2)
          Number of spatial dimensions
        """

        if opt is None:
            opt = ConvBPDNRecTV.Options()

        # Infer problem dimensions and set relevant attributes of self
        self.cri = cr.CSC_ConvRepIndexing(D, S, dimK=dimK, dimN=dimN)

        # Call parent class __init__
        Nx = np.product(self.cri.shpX)
        yshape = list(self.cri.shpX)
        yshape[self.cri.axisM] += len(self.cri.axisN) * self.cri.Cd
        super(ConvBPDNRecTV, self).__init__(Nx, yshape, yshape, S.dtype, opt)

        # Set l1 term scaling and weight array
        self.lmbda = self.dtype.type(lmbda)
        self.Wl1 = np.asarray(opt['L1Weight'], dtype=self.dtype)
        self.Wl1 = self.Wl1.reshape(cr.l1Wshape(self.Wl1, self.cri))

        self.mu = self.dtype.type(mu)
        if hasattr(opt['TVWeight'], 'ndim') and opt['TVWeight'].ndim > 0:
            self.Wtv = np.asarray(
                opt['TVWeight'].reshape((1, ) * (dimN + 2) +
                                        opt['TVWeight'].shape),
                dtype=self.dtype)
        else:
            # Wtv is a scalar: no need to change shape
            self.Wtv = self.dtype.type(opt['TVWeight'])

        # Set penalty parameter
        self.set_attr('rho',
                      opt['rho'],
                      dval=(50.0 * self.lmbda + 1.0),
                      dtype=self.dtype)

        # Set rho_xi attribute
        self.set_attr('rho_xi',
                      opt['AutoRho', 'RsdlTarget'],
                      dval=1.0,
                      dtype=self.dtype)

        # Reshape D and S to standard layout
        self.D = np.asarray(D.reshape(self.cri.shpD), dtype=self.dtype)
        self.S = np.asarray(S.reshape(self.cri.shpS), dtype=self.dtype)

        # Compute signal in DFT domain
        self.Sf = sl.rfftn(self.S, None, self.cri.axisN)

        self.Gf, GHGf = sl.GradientFilters(self.cri.dimN + 3,
                                           self.cri.axisN,
                                           self.cri.Nv,
                                           dtype=self.dtype)

        # Initialise byte-aligned arrays for pyfftw
        self.YU = sl.pyfftw_empty_aligned(self.Y.shape, dtype=self.dtype)
        xfshp = list(self.cri.shpX)
        xfshp[dimN - 1] = xfshp[dimN - 1] // 2 + 1
        self.Xf = sl.pyfftw_empty_aligned(xfshp,
                                          dtype=sl.complex_dtype(self.dtype))

        self.setdict()