daniele@160: classdef dictionary daniele@160: %% Dictionary for sparse representation daniele@160: properties daniele@160: phi %Matrix containing the dictionary daniele@160: len %Length of basis functions daniele@160: nAtoms %Number of basis function daniele@160: name %String containing the matrix ensemble from which the dictionary is drawn daniele@160: end daniele@160: properties (Dependent = true) daniele@160: redundancy %Redundancy of the dictionary: nAtoms/len daniele@160: coherence %Maximum inner product of different basis daniele@160: isNormalised %True if the atoms have unit norm daniele@160: rank %rank of the dictionary daniele@160: end daniele@160: daniele@160: methods daniele@160: %% Constructor daniele@160: function obj = dictionary(phi,len,nAtoms) daniele@160: % obj = dictionary(phi,len,nAtoms) daniele@160: % INPUTS: daniele@160: % - phi: either a string specifying a matrix ensamble or a daniele@160: % matrix defining an explicit dictionary daniele@160: % - len: length of the atoms (only for implicit dictionaries) daniele@160: % - nAtoms: number of atoms (only for implicit dictionaries) daniele@160: if nargin daniele@160: if ~ischar(phi) daniele@160: [obj.len obj.nAtoms] = size(phi); daniele@160: obj.phi = phi; daniele@160: obj.name = 'explicit'; daniele@160: else daniele@160: switch lower(phi) daniele@160: case 'dct' daniele@160: obj.phi = dctmatrix(len,nAtoms); daniele@184: case 'grassmannian' daniele@160: obj.phi = grassmanian(len,nAtoms); daniele@160: otherwise daniele@160: obj.phi = MatrixEnsemble(len,nAtoms,phi); daniele@160: end daniele@160: obj.len = len; daniele@160: obj.nAtoms = nAtoms; daniele@160: obj.name = lower(phi); daniele@160: end daniele@160: end daniele@184: end daniele@160: %% Dependent properties daniele@160: function redundancy = get.redundancy(obj) daniele@160: redundancy = obj.nAtoms/obj.len; daniele@160: end daniele@160: function coherence = get.coherence(obj) daniele@160: obj.phi = normcol(obj.phi); daniele@160: G = obj.phi'*obj.phi; daniele@160: G = G - eye(size(G)); daniele@160: coherence = max(abs(G(:))); daniele@160: end daniele@160: function isNormalised = get.isNormalised(obj) daniele@160: isNormalised = norm(sum(conj(obj.phi).*obj.phi) - ... daniele@160: ones(1,obj.nAtoms))<1e-9; daniele@160: end daniele@160: function r = get.rank(obj) daniele@160: r = rank(obj.phi); daniele@160: end daniele@160: %% Operations daniele@160: function obj = normalize(obj) daniele@160: obj.phi = normcol(obj.phi); daniele@184: end daniele@160: %% Visualization daniele@160: function image(obj) daniele@160: %Image of the dictionary daniele@160: if isreal(obj.phi) daniele@160: imagesc(obj.phi); daniele@160: title('Dictionary'); daniele@160: xlabel('Atom number'); daniele@160: else daniele@160: subplot(2,1,1) daniele@160: imagesc(real(obj.phi)); daniele@160: title('Real'); daniele@160: xlabel('Atom number'); daniele@160: subplot(2,1,2) daniele@160: imagesc(imag(obj.phi)); daniele@160: title('Imaginary'); daniele@160: xlabel('Atom number'); daniele@160: end daniele@160: end daniele@160: function imagegram(obj) daniele@160: G = obj.phi'*obj.phi; daniele@160: imagesc(G); daniele@160: title('Gram Matrix') daniele@160: end daniele@160: function plot(obj,n) daniele@160: %Plot of the n-th basis daniele@160: if isreal(obj.phi) daniele@160: plot(obj.phi(:,n)); daniele@160: title(['Atom number ' num2str(n) '/' num2str(size(obj.phi,2))]); daniele@160: else daniele@160: subplot(2,1,1) daniele@160: plot(real(obj.phi(:,n))); daniele@160: title(['Atom number ' num2str(n) '/' num2str(size(obj.phi,2)) ' - Real']); daniele@160: subplot(2,1,2) daniele@160: plot(imag(obj.phi(:,n))); daniele@160: title(['Atom number ' num2str(n) '/' num2str(size(obj.phi,2)) ' - Imaginary']); daniele@160: end daniele@184: end daniele@160: function movie(obj) daniele@160: %Movie of the basis daniele@160: for i=1:size(obj.phi,2) daniele@160: obj.plot(i); daniele@160: pause(1/25); daniele@160: end daniele@160: end daniele@160: end daniele@160: end