def __init__(self, D0, S, lmbda=None, opt=None, xmethod=None, dmethod=None, dimK=1, dimN=2): """ | **Call graph** .. image:: ../_static/jonga/cbpdndl_init.svg :width: 20% :target: ../_static/jonga/cbpdndl_init.svg | Parameters ---------- D0 : array_like Initial dictionary array S : array_like Signal array lmbda : float Regularisation parameter opt : :class:`ConvBPDNDictLearn.Options` object Algorithm options xmethod : string, optional (default 'admm') String selecting sparse coding solver. Valid values are documented in function :func:`.ConvBPDN`. dmethod : string, optional (default 'fista') String selecting dictionary update solver. Valid values are documented in function :func:`.ConvCnstrMOD`. dimK : int, optional (default 1) Number of signal dimensions. If there is only a single input signal (e.g. if `S` is a 2D array representing a single image) `dimK` must be set to 0. dimN : int, optional (default 2) Number of spatial/temporal dimensions """ if opt is None: opt = ConvBPDNDictLearn.Options(xmethod=xmethod, dmethod=dmethod) if xmethod is None: xmethod = opt.xmethod if dmethod is None: dmethod = opt.dmethod if opt.xmethod != xmethod or opt.dmethod != dmethod: raise ValueError('Parameters xmethod and dmethod must have the ' 'same values used to initialise the Options ' 'object') self.opt = opt self.xmethod = xmethod self.dmethod = dmethod # Get dictionary size if self.opt['DictSize'] is None: dsz = D0.shape else: dsz = self.opt['DictSize'] # Construct object representing problem dimensions cri = cr.CDU_ConvRepIndexing(dsz, S, dimK, dimN) # Normalise dictionary D0 = cr.Pcn(D0, dsz, cri.Nv, dimN, cri.dimCd, crp=True, zm=opt['CCMOD', 'ZeroMean']) # Modify D update options to include initial value for Y optname = 'X0' if dmethod == 'fista' else 'Y0' opt['CCMOD'].update( {optname: cr.zpad(cr.stdformD(D0, cri.Cd, cri.M, dimN), cri.Nv)}) # Create X update object xstep = ConvBPDN(D0, S, lmbda, opt['CBPDN'], method=xmethod, dimK=dimK, dimN=dimN) # Create D update object dstep = ConvCnstrMOD(None, S, dsz, opt['CCMOD'], method=dmethod, dimK=dimK, dimN=dimN) # Configure iteration statistics reporting isc = dictlrn.IterStatsConfig(isfld=dc.isfld(xmethod, dmethod, opt), isxmap=dc.isxmap(xmethod, opt), isdmap=dc.isdmap(dmethod), evlmap=dc.evlmap(opt['AccurateDFid']), hdrtxt=dc.hdrtxt(xmethod, dmethod, opt), hdrmap=dc.hdrmap(xmethod, dmethod, opt), fmtmap={ 'It_X': '%4d', 'It_D': '%4d' }) # Call parent constructor super(ConvBPDNDictLearn, self).__init__(xstep, dstep, opt, isc)
def __init__(self, Z, S, dsz, opt=None, dimK=1, dimN=2): """ | **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) self.Xf = sl.pyfftw_rfftn_empty_aligned(self.xshape, self.cri.axisN, self.dtype)
def __init__(self, Z, S, dsz, opt=None, dimK=1, dimN=2): """ 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) self.Xf = sl.pyfftw_rfftn_empty_aligned(self.Y.shape, self.cri.axisN, self.dtype) if Z is not None: self.setcoef(Z)
def __init__(self, D0, S, lmbda, W, opt=None, xmethod=None, dmethod=None, dimK=1, dimN=2): """ | **Call graph** .. image:: ../_static/jonga/cbpdnmddl_init.svg :width: 20% :target: ../_static/jonga/cbpdnmddl_init.svg | Parameters ---------- D0 : array_like Initial dictionary array S : array_like Signal array lmbda : float Regularisation parameter W : array_like Mask array. The array shape must be such that the array is compatible for multiplication with the *internal* shape of input array S (see :class:`.cnvrep.CDU_ConvRepIndexing` for a discussion of the distinction between *external* and *internal* data layouts). opt : :class:`ConvBPDNMaskDictLearn.Options` object Algorithm options xmethod : string, optional (default 'admm') String selecting sparse coding solver. Valid values are documented in function :func:`.ConvBPDNMask`. dmethod : string, optional (default 'fista') String selecting dictionary update solver. Valid values are documented in function :func:`.ConvCnstrMODMask`. dimK : int, optional (default 1) Number of signal dimensions. If there is only a single input signal (e.g. if `S` is a 2D array representing a single image) `dimK` must be set to 0. dimN : int, optional (default 2) Number of spatial/temporal dimensions """ if opt is None: opt = ConvBPDNMaskDictLearn.Options(xmethod=xmethod, dmethod=dmethod) if xmethod is None: xmethod = opt.xmethod if dmethod is None: dmethod = opt.dmethod if opt.xmethod != xmethod or opt.dmethod != dmethod: raise ValueError('Parameters xmethod and dmethod must have the ' 'same values used to initialise the Options ' 'object') self.opt = opt self.xmethod = xmethod self.dmethod = dmethod # Get dictionary size if self.opt['DictSize'] is None: dsz = D0.shape else: dsz = self.opt['DictSize'] # Construct object representing problem dimensions cri = cr.CDU_ConvRepIndexing(dsz, S, dimK, dimN) # Normalise dictionary D0 = cr.Pcn(D0, dsz, cri.Nv, dimN, cri.dimCd, crp=True, zm=opt['CCMOD', 'ZeroMean']) # Modify D update options to include initial values for Y if cri.C == cri.Cd: Y0b0 = np.zeros(cri.Nv + (cri.C, 1, cri.K)) else: Y0b0 = np.zeros(cri.Nv + (1, 1, cri.C * cri.K)) Y0b1 = cr.zpad(cr.stdformD(D0, cri.Cd, cri.M, dimN), cri.Nv) if dmethod == 'fista': opt['CCMOD'].update({'X0': Y0b1}) else: if dmethod == 'cns': Y0 = Y0b1 else: Y0 = np.concatenate((Y0b0, Y0b1), axis=cri.axisM) opt['CCMOD'].update({'Y0': Y0}) # Create X update object xstep = ConvBPDNMask(D0, S, lmbda, W, opt['CBPDN'], method=xmethod, dimK=dimK, dimN=dimN) # Create D update object dstep = ConvCnstrMODMask(None, S, W, dsz, opt['CCMOD'], method=dmethod, dimK=dimK, dimN=dimN) # Configure iteration statistics reporting isc = dictlrn.IterStatsConfig(isfld=dc.isfld(xmethod, dmethod, opt), isxmap=dc.isxmap(xmethod, opt), isdmap=dc.isdmap(dmethod), evlmap=dc.evlmap(opt['AccurateDFid']), hdrtxt=dc.hdrtxt(xmethod, dmethod, opt), hdrmap=dc.hdrmap(xmethod, dmethod, opt), fmtmap={ 'It_X': '%4d', 'It_D': '%4d' }) # Call parent constructor super(ConvBPDNMaskDictLearn, self).__init__(xstep, dstep, opt, isc)
def __init__(self, Z, S, W, dsz, opt=None, dimK=None, dimN=2): """ | **Call graph** .. image:: ../_static/jonga/ccmodmdfista_init.svg :width: 20% :target: ../_static/jonga/ccmodmdfista_init.svg | 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 the *internal* shape of input array S (see :class:`.cnvrep.CDU_ConvRepIndexing` for a discussion of the distinction between *external* and *internal* data layouts). dsz : tuple Filter support size(s) opt : :class:`ConvCnstrMODMasked.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 = ConvCnstrMODMask.Options() # Infer problem dimensions and set relevant attributes of self self.cri = cr.CDU_ConvRepIndexing(dsz, S, dimK=dimK, dimN=dimN) # Append singleton dimensions to W if necessary if hasattr(W, 'ndim'): W = sl.atleast_nd(self.cri.dimN + 3, W) # Reshape W if necessary (see discussion of reshape of S in # ccmod base class) if self.cri.Cd == 1 and self.cri.C > 1 and hasattr(W, 'ndim'): # 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 super(ConvCnstrMODMask, self).__init__(Z, S, dsz, opt, dimK, dimN) # Create byte aligned arrays for FFT calls self.WRy = sl.pyfftw_empty_aligned(self.S.shape, dtype=self.dtype) self.Ryf = sl.pyfftw_rfftn_empty_aligned(self.S.shape, self.cri.axisN, self.dtype)
def __init__(self, Z, S, W, dsz, opt=None, dimK=None, dimN=2): """ 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)) self.Xf = sl.pyfftw_rfftn_empty_aligned(xfshp, self.cri.axisN, self.dtype) if Z is not None: self.setcoef(Z)