% em_test_setup.m
%
% create sample image, system matrix, and sinograms for examples
% and testing of Poisson emission maximum likelihood (ML) algorithms
% creates: ig sg xtrue G proj ci ytrue ri yi
%
% Copyright Jan 1998, Jeff Fessler, University of Michigan

% true emission image
if ~isvar('xtrue'), printm 'xtrue'
	if ~isvar('ig')
		ig = image_geom('nx', 64, 'ny', 60, 'fov', 500);
	end
	xtrue = read_zubal_emis('nx', ig.nx, 'ny', ig.ny);
	mumap = read_zubal_attn('nx', ig.nx, 'ny', ig.ny);
	im plc 2 3
	im(1, xtrue, 'emission image'), cbar
	im(2, mumap, 'attenuation map'), cbar

	% reconstruction mask (which pixels do we estimate?)
	ig.mask = ig.circ(220, 180) > 0;
	im(3, ig.mask + xtrue, 'support mask + xtrue')
end

% system matrix G
if ~isvar('G'), printm 'system'
	sg = sino_geom('par', 'nb', ig.nx+2, 'na', ig.ny*3/2, ...
		'dr', 528 / (ig.nx+2));

	% simple strip-integral system model
	G = Gtomo2_strip(sg, ig, 'single', 1);

	if isvar('f.wtf') && has_mex_jf
		if exist(f.wtf), delete(f.wtf), end
		wtf_write(f.wtf, G, ig.nx, ig.ny, sg.nb, sg.na);
	end
	if isvar('f.wtr') && has_mex_jf && has_aspire
		if exist(f.wtr), delete(f.wtr), end
		os_run(sprintf('wt -chat 0 col2row %s %s', f.wtr, f.wtf))
	end
end

% noisy measurements
if ~isvar('yi'), printm 'data yi'
	proj = G * xtrue;
	li = G * mumap;
	printm('Maximum line integral = %g', max(li(:)))
	if ~isvar('f.count'), f.count = 1e5; end
	% detector efficiency variations per CTI 931 PET scanner
	ci = exp(0.3 * randn(size(proj)));
	ci = ci .* exp(-li);
	ci = f.count / sum(ci(:) .* proj(:)) * ci;
	ci = dsingle(ci);
	ytrue = ci .* proj;
	if ~isvar('f.randpercent')
		f.randpercent = 10;
	end
	ri = f.randpercent / 100 * mean(ytrue(:)) * sg.ones;
	ri = dsingle(ri);
	rng(0)
	yi = poisson(ytrue + ri);

	im(4, ytrue, 'ytrue: true projections'), cbar
	im(5, yi, 'yi: noisy projections'), cbar
	clear ytrue proj
end

% FBP reconstruction
if ~isvar('xfbp'), printm 'fbp'
	xfbp = em_fbp(sg, ig, yi, ci, ri);
	xfbp = max(xfbp, 0);
	im(6, xfbp, 'FBP Reconstruction'), cbar
end

% save to files if needed
if isvar('f.yi')
	fld_write(f.yi, yi, 'check', 0)
end
if isvar('f.ci')
	fld_write(f.ci, ci, 'check', 0)
end
if isvar('f.ri')
	fld_write(f.ri, ri, 'check', 0)
end
if isvar('f.mask')
	fld_write(f.mask, ig.mask, 'check', 0)
end


function [ll,lls,Ht] = gogarch_likelihood(parameters,data,p,q,gjrType,P,L,isOgarch,isInference)
% Log-likelihood for use in estimation GOGARCH and OGARCH models
%
% USAGE:
%  [LL,LLS,HT] = gogarch_likelihood(PARAMETERS,DATA,P,Q,GJRTYPE,P,L,ISOGARCH,ISINFERNCE)
%
% INPUTS:
%   PARAMETERS - K*(K-1)/2 + sum(P) + sum(Q) by 1 vector of parameters (only sum(P) + sum(Q) if ISOGARCH)
%   DATA       - K by K by Tarray of data (either realized measures or outer-products of daily data)
%   P          - K by 1 vector of positive, scalar integer representing the number of symmetric innovations
%   Q          - K by 1 vector of non-negative, scalar integer representing the number of conditional covariance lags
%   GJRTYPE    - K by 1 vector containing either 1 (TARCH/AVGARCH) or 2 (GJRGARCH/GARCH/ARCH)
%   P          - Eigenvector of unconditional covariance matrix of the data
%   L          - Diagonal matrix containing the eigenvalues of unconditional covariance matrix of the data
%   ISOGARCH   - Boolean indicating that the model is OGARCH (otherwise GOGARCH)
%   ISINFERNCE - Boolean indicating the likelihood is being used for inference, so that the first
%                  K(K+1)/2 parameters are ivech(S)
%
% OUTPUTS:
%   LL         - The log likelihood computed at PARAMETERS
%   LLS        - T by 1 vector of log-likelihoods
%   HT         - K by K by T vector of conditional covariances
%
% COMMENTS:

% Copyright: Kevin Sheppard
% kevin.sheppard@economics.ox.ac.uk
% Revision: 1    Date: 4/15/2012

[k,~,T] = size(data);
if size(parameters,1)>size(parameters,2)
    parameters = parameters';
end

offset = 0;
if isInference
    S =  ivech(parameters(1:k*(k+1)/2));
    [P,L] = eig(S);
    P = P';
    offset = offset + k*(k+1)/2;
end

if ~isOgarch
    phi = parameters(offset + (1:k*(k-1)/2));
    U = phi2u(phi);
    offset = offset + k*(k-1)/2;
else
    U = eye(k);
end
Z = P*L^(0.5)*U;
Zinv = U'*L^(-0.5)*P';
stdData = zeros(k,k,T);
for t=1:T
    stdData(:,:,t) = Zinv*data(:,:,t)*Zinv';
end
% Univariate GARCH models
V = zeros(T,k);
w = .06 * .94.^(0:sqrt(T));
w = w/sum(w);
likData = zeros(T,k);
for i=1:k
    count = p(i) + q(i);
    volParameters = parameters(offset + (1:count));
    volParameters = max(volParameters,0);
    volParameters = [1-sum(volParameters) volParameters]; %#ok<AGROW>
    offset = offset + count;
    likData(:,i) = squeeze(stdData(i,i,:));
    volData = sqrt(likData(:,i));
    backCast = w*volData(1:length(w)).^2;
    v = tarch_core_simple(volData,volParameters,backCast,0,p(i),0,q(i),gjrType(i));
    V(:,i) = v;
end

likConst = k*log(2*pi);
logdetZZp = log(det(Z*Z'));
lls = 0.5*(likConst + logdetZZp + sum(log(V),2) + sum(likData./V,2));
ll = sum(lls);

if ~isreal(ll) || isnan(ll) || isinf(ll)
    ll = 1e7;
end

if nargout>2
    Ht = zeros(k,k,T);
    for t=1:T
        Ht(:,:,t) = Z*diag(V(t,:))*Z';
    end
end


function varargout = chebyball(F)
%CHEBYBALL Computes Chebyshev ball of a constraint object
%
% If two outputs are requested, the numerical data is returned
% [xc,R] = chebyball(F)
%
% If three outputs are requrested, the symbolic model (x-xc)'(x-xc)<R^2 is
% appended
% [xc,R,C] = chebyball(F)
%
% If only one output is requested, only the symbolic constraint is returned
% C = chebyball(F)

switch nargout
    case 0
        f = chebyball(lmi(F))
    case 1
        [f] = chebyball(lmi(F));
        varargout{1} = f;
    case 2
        [xc,R] = chebyball(lmi(F));
        varargout{1} = xc;
        varargout{2} = R;
    case 3
        [xc,R,f] = chebyball(lmi(F));
        varargout{1} = xc;
        varargout{2} = R;
        varargout{3} = f;
    otherwise
end


function [H_t] = shift_t(H,t)

% Shifts the matrix H by t spots to the right
% Use a negative t to shift to the left
% To be used with the convolutive NMF algorithms

[K,N] = size(H);

if t>0
      H_trunc = H(:,1:N-t);
      H_t = [zeros(K,t)+eps,H_trunc];

elseif t<0
      H_trunc = H(:,-t+1:end);
      H_t = [H_trunc,zeros(K,-t)+eps];
else
      H_t = H;
end

end


function [i_min,i_max,j_min,j_max,lew] = get_lew(img,smap_b)
% cut a local window from the original img, and also return
% lew's coordinates in the original img

    [all_i,all_j] = find(smap_b~=0);
    rescale = 0.2;
    i_min = round(min(all_i)*(1-rescale));
    i_max = round(max(all_i)*(1+rescale));
    j_min = round(min(all_j)*(1-rescale));
    j_max = round(max(all_j)*(1+rescale));

    img_size = size(img(:,:,1));
    [i_min,i_max,j_min,j_max] = handle_cross_boundary(i_min,i_max,j_min,j_max,img_size);
    lew = img(i_min:i_max,j_min:j_max,:);
end


function [precision,recall] = evaluate(NAME,boundingBoxes, threshold)
tmpName = extractBefore(NAME,'.jpg');
PATH_REAL = "Data/" + tmpName + ".txt";
fileID = fopen(PATH_REAL{1},'r');
formatSpec = ' %d ';
BoundingData = fscanf(fileID,formatSpec);

[realObjectCount,~] = size(BoundingData);
realObjectCount = (realObjectCount - 1)/4;
correctObjects  = 0;
[~,detectedCount] = size(boundingBoxes);

for i=1:detectedCount
    ourBox = boundingBoxes{1,i};
    topX = ourBox(1,1);
    topY = ourBox(1,2);
    lowX = ourBox(1,3);
    lowY = ourBox(1,4);
    for b=1:realObjectCount
        rtopX = BoundingData(1 + (4*(b-1)),1);
        rtopY = BoundingData(2 + (4*(b-1)),1);
        rlowX = BoundingData(3 + (4*(b-1)),1);
        rlowY = BoundingData(4 + (4*(b-1)),1);
        width = 0;
        if lowX > topX
            width =  lowX-topX;
        else
             width =  topX-lowX;
        end
        height = 0;
        if lowY > topY
            height =  lowY-topY ;
        else
             height =  topY-lowY;
        end

        realWidth = 0;
        if rlowX > rtopX
            realWidth =  rlowX-rtopX;
        else
             realWidth =  rtopX-rlowX;
        end
        realHeight = 0;
        if rlowY > rtopY
            realHeight =   rlowY-rtopY ;
        else
             realHeight =  rtopY-rlowY;
        end

        ourBox  = [ topX,   topY, width ,height  ];
        realBox = [ rtopX, rtopY,realWidth ,realHeight];
        overlapRatio = bboxOverlapRatio(ourBox,realBox);
        if overlapRatio > threshold
            correctObjects = correctObjects + 1;
            break;
        end
    end
end

recall = correctObjects /realObjectCount ;
precision = correctObjects /detectedCount ;
end

github-repos/MATLAB/zhangqianqianQQ-MachineVisionAlgorithm/MachineVisionAlgorithm-683338f6c3b1aab9fa2b80026915fe936aebf0ee/识别算法/Object Recognition based on super pixel/evaluate.m


function fx1 = p00_fx1 ( prob, x )

%*****************************************************************************80
%
%% P00_FX1: first derivative of a function specified by problem number.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    15 January 2013
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer PROB, the number of the problem.
%
%    Input, real X, the point at which F is to be evaluated.
%
%    Output, real FX1, the first derivative of the function at X.
%
  if ( prob == 1 )
    fx1 = p01_fx1 ( x );
  elseif ( prob == 2 )
    fx1 = p02_fx1 ( x );
  elseif ( prob == 3 )
    fx1 = p03_fx1 ( x );
  elseif ( prob == 4 )
    fx1 = p04_fx1 ( x );
  elseif ( prob == 5 )
    fx1 = p05_fx1 ( x );
  elseif ( prob == 6 )
    fx1 = p06_fx1 ( x );
  elseif ( prob == 7 )
    fx1 = p07_fx1 ( x );
  elseif ( prob == 8 )
    fx1 = p08_fx1 ( x );
  elseif ( prob == 9 )
    fx1 = p09_fx1 ( x );
  elseif ( prob == 10 )
    fx1 = p10_fx1 ( x );
  elseif ( prob == 11 )
    fx1 = p11_fx1 ( x );
  elseif ( prob == 12 )
    fx1 = p12_fx1 ( x );
  elseif ( prob == 13 )
    fx1 = p13_fx1 ( x );
  elseif ( prob == 14 )
    fx1 = p14_fx1 ( x );
  elseif ( prob == 15 )
    fx1 = p15_fx1 ( x );
  elseif ( prob == 16 )
    fx1 = p16_fx1 ( x );
  elseif ( prob == 17 )
    fx1 = p17_fx1 ( x );
  elseif ( prob == 18 )
    fx1 = p18_fx1 ( x );
  elseif ( prob == 19 )
    fx1 = p19_fx1 ( x );
  else
    fprintf ( 1, '\n' );
    fprintf ( 1, 'P00_FX1 - Fatal error!\n' );
    fprintf ( 1, '  Illegal problem number = %d\n', prob );
    error ( 'P00_FX1 - Fatal error!' );
  end

  return
end


%% Image Processing for Microchannel Flow experiment
% Prototype code:
% Using images taken in the experiment:
%
% 1st image fluid flow: 20 mu L/min
% 2st image fluid flow: 10 mu L/min
%
% Microchannel 1: 1808.bmp & 1813.bmp
% Microchannel 2: 1824.bmp & 1828.bmp
% Microchannel 3: 1834.bmp & 1838.bmp
% Microchannel 4: 1843.bmp & 1847.bmp
% Microchannel 5: 1855.bmp & 1860.bmp

target = {'1808.bmp' '1813.bmp'...
    '1824.bmp' '1828.bmp' ...
    '1834.bmp' '1838.bmp' ...
    '1843.bmp' '1847.bmp' ...
    '1855.bmp' '1860.bmp'};
%or
number = [1808 1813 1824 1828 1834 1838 1843 1847 1855 1860];

%Pix_value = [0.31 0.31 0.31 0.31 0.31 0.31 0.31 0.31 0.31 0.31];

%% Load images
name = strcat(num2str(number(1)),'.bmp');
image = imread(name);

%% Apply filter
h = fspecial('unsharp');
image2 = imfilter(image,h); % apply X filter

%% Convert to gray scale
image3 = rgb2gray(image); % conver Original to gray scales
image4 = rgb2gray(image2); % conver Filtered to gray scales

%% Create image negative
% Original Gray
image5 = double(image3);
scale_image = 1/max(image5(:)); % scale_image = 1/255
neg_image5 = 1-image5*scale_image;

% Filtered Gray
image6 = double(image4);
scale_image = 1/max(image6(:)); % scale_image = 1/255
neg_image6 = 1-image6*scale_image;

%% Remove values below an specific Pix_value
Pix_value = 0.31;

[n,m,p] = size(neg_image5);
for k = 1:p
    for j = 1:n;
        for i = 1:m;
            if neg_image5(j,i,k) >= Pix_value
                neg_image5(j,i,k) = 0;
            else
                % do nothing
            end
        end
    end
end
[n,m,p] = size(neg_image6);
for k = 1:p
    for j = 1:n;
        for i = 1:m;
            if neg_image6(j,i,k) >= Pix_value
                neg_image6(j,i,k) = 0;
            else
                % do nothing
            end
        end
    end
end

%% Plot pictures
figure(1);
subplot(2,3,1); imshow(image); title('Original');
subplot(2,3,4); imshow(image2); title('Filtered Image');
subplot(2,3,2); imshow(image3); title('Gray Image with filter');
subplot(2,3,5); imshow(image4); title('Gray Image with out filter');
subplot(2,3,3); imshow(neg_image5); title('Original, filtered an processed');
subplot(2,3,6); imshow(neg_image6); title('negative of the filtered and processed');

%% Save gray_imageX
name2 = strcat(num2str(number(1)),'_gray.bmp');
imwrite(image4,name2,'bmp');

%% Save neg_imageX
name2 = strcat(num2str(number(1)),'_neg.bmp');
imwrite(neg_image6,name2,'bmp');

%% Compute Mixing Index
I = neg_image6;      % Use values in neg_image6 for the difusion analysis.
I_mean = mean(I(:)); % Find the average of the image intensity values.
x = find(I);         % find indices of non-zero values.
N = length(x);       % Total number of non-zero values.

Mix_index = 1-(1/I_mean)*sqrt(sum(sum((I - I_mean).^2))/N);

% Now that I sure what I want to do I'll create a function to evaluate
% automatically data picture.


function idx = getNearest(data, centers,trans)
% idx = getNearest(data, centers)
%
% Gets indices of centers closest (in Euclidean space) to each data point
%
% data(ndata, nvars)
% centers(ncenters, nvars)
% idx(ndata, 1)

% dist(a, b) = ||a-b|| = sum(a.^2) - 2*a*b' + sum(b.^2) for 1xnvars vectors
% a and b.

if(~exist('trans','var'))
    centers = centers';
end
centerssq = sum(centers.^2, 1);

distmat = repmat(centerssq, [size(data,1) 1]);
distmat = distmat - 2*data * centers;

[dist, idx] = min(distmat, [], 2);


function tests = test_ft_connectivity_mutualinformation

% MEM 1gb
% WALLTIME 00:10:00
% DEPENDENCY ft_connectivity_mutualinformation

if nargout
  % assume that this is called by RUNTESTS
  tests = functiontests(localfunctions);
else
  % assume that this is called from the command line
  func = localfunctions;
  for i=1:numel(func)
    fprintf('evaluating %s\n', func2str(func{i}));
    feval(func{i});
  end
end

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function test_chan_time(testCase)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

nchan  = 6;
ntime  = 100000;
dat    = randn(nchan, ntime);

%   histmethod = The way that histograms are generated from the data. Possible values
%                are 'eqpop' (default), 'eqspace', 'ceqspace', 'gseqspace'.
%                See the help of the 'binr' function in the ibtb toolbox for more information.
%   numbin     = scalar value. The number of bins used to create the histograms needed for
%                the entropy computations
%   opts       = structure that is passed on to the 'information' function in the ibtb
%                toolbox. See the help of that function for more information.
%   refindx    = scalar value or 'all'. The channel that is used as 'reference channel'.

result = {};
result{end+1} = ft_connectivity_mutualinformation(dat, 'method', 'ibtb', 'histmethod', 'eqpop'    , 'numbin', 5);
result{end+1} = ft_connectivity_mutualinformation(dat, 'method', 'ibtb', 'histmethod', 'eqspace'  , 'numbin', 5);
result{end+1} = ft_connectivity_mutualinformation(dat, 'method', 'ibtb', 'histmethod', 'ceqspace' , 'numbin', 5);
result{end+1} = ft_connectivity_mutualinformation(dat, 'method', 'ibtb', 'histmethod', 'gseqspace', 'numbin', 5);
result{end+1} = ft_connectivity_mutualinformation(dat, 'method', 'ibtb', 'histmethod', 'eqpop'    , 'numbin', 50);
result{end+1} = ft_connectivity_mutualinformation(dat, 'method', 'ibtb', 'histmethod', 'eqspace'  , 'numbin', 50);
result{end+1} = ft_connectivity_mutualinformation(dat, 'method', 'ibtb', 'histmethod', 'ceqspace' , 'numbin', 50);
result{end+1} = ft_connectivity_mutualinformation(dat, 'method', 'ibtb', 'histmethod', 'gseqspace', 'numbin', 50);
result{end+1} = ft_connectivity_mutualinformation(dat, 'method', 'gcmi');

% all iterations were done with (slightly) different options, hence the results should not be equal
for i=1:numel(result)
  for j=(i+1):numel(result)
    assert(~isequaln(result{i}, result{j}), 'the results %d and %d should not be equal', i, j);
  end
end


function varargout = resolutionmerge(varargin)
% RESOLUTIONMERGE M-file for resolutionmerge.fig
%
% GUI for improving resolution of lower resolution image using higher
% resolution image using RGB-to-HSI conversion.
% Images have to be spatially registered.
%
% Monochromatic (gray scale) low resolution image is converged to colored
% image by false color mapping to "hot" color scheme. This RGB image is
% then converted to Hue, Saturation and Value (HSV) image. Value component is replaced
% by higher resolution image and the resulting HSV image is converted back to
% RGB. This RGB merged image converted to gray scale is a merged image with
% improved spatial resolution.
%
% To run, type:
% >> resolutionmerge
%
% Can work with any type of color or monochromatic image. If images are colored
% they are converted to gray scale first and then merged.
% To load variables from matlab file, the file should contain variables
% LOWRES and HIGHRES
%
% created by K.Artyushkova
% February 2010
%
%

% Begin initialization code - DO NOT EDIT
gui_Singleton = 1;
gui_State = struct('gui_Name',       mfilename, ...
                   'gui_Singleton',  gui_Singleton, ...
                   'gui_OpeningFcn', @resolutionmerge_OpeningFcn, ...
                   'gui_OutputFcn',  @resolutionmerge_OutputFcn, ...
                   'gui_LayoutFcn',  [] , ...
                   'gui_Callback',   []);
if nargin && ischar(varargin{1})
    gui_State.gui_Callback = str2func(varargin{1});
end

if nargout
    [varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
    gui_mainfcn(gui_State, varargin{:});
end
% End initialization code - DO NOT EDIT

% --- Executes just before resolutionmerge is made visible.
function resolutionmerge_OpeningFcn(hObject, eventdata, handles, varargin)
% This function has no output args, see OutputFcn.
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
% varargin   command line arguments to resolutionmerge (see VARARGIN)

% Choose default command line output for resolutionmerge
handles.output = hObject;

% Update handles structure
guidata(hObject, handles);

% UIWAIT makes resolutionmerge wait for user response (see UIRESUME)
% uiwait(handles.figure1);

% --- Outputs from this function are returned to the command line.
function varargout = resolutionmerge_OutputFcn(hObject, eventdata, handles)
% varargout  cell array for returning output args (see VARARGOUT);
% hObject    handle to figure
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Get default command line output from handles structure
varargout{1} = handles.output;

%% Input section
% --------------------------------------------------------------------
function load_low_res_1_Callback(hObject, eventdata, handles)
% hObject    handle to load_low_res_1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

[filename, pathname]=uigetfile('*.*','Open low resolution image');
cd(pathname)
[N,M]=size(filename);
image=imread(char(filename));
[n,m,p]=size(image);
if p==3
    lowres=rgb2gray(image);
else
    lowres=image;
end
axes(handles.axes1)
handles.lowres=lowres;
iptsetpref('ImshowAxesVisible', 'on')
imagesc(uint8(lowres)), colormap(gray)
guidata(hObject,handles)

% --------------------------------------------------------------------
function open_lowres_Callback(hObject, eventdata, handles)
% hObject    handle to open_lowres (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
[filename, pathname]=uigetfile('*.mat','Open low resolution image. Image should be saved in variable LOWRES');
cd(pathname)
D=load (filename, 'lowres');
image=D.lowres;
[n,m,p]=size(image);
if p==3
    lowres=rgb2gray(image);
else
    lowres=image;
end
axes(handles.axes1)
handles.lowres=lowres;
iptsetpref('ImshowAxesVisible', 'on')
imagesc(uint8(lowres)), colormap(gray)
guidata(hObject,handles)

% --------------------------------------------------------------------
function load_highres_Callback(hObject, eventdata, handles)
% hObject    handle to load_highres (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
[filename, pathname]=uigetfile('*.*','Open high resolution image');
cd(pathname)
[N,M]=size(filename);
image=imread(char(filename));
[n,m,p]=size(image);
if p==3
    highres=rgb2gray(image);
else
    highres=image;
end
axes(handles.axes2)
handles.highres=highres;
iptsetpref('ImshowAxesVisible', 'on')
imagesc(uint8(highres)), colormap(gray)
guidata(hObject,handles)

% --------------------------------------------------------------------
function Open_highres_Callback(hObject, eventdata, handles)
% hObject    handle to Open_highres (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
[filename, pathname]=uigetfile('*.mat','Open high resolution image. Image should be saved in variable LOWRES');
cd(pathname)
D=load (filename, 'highres');
image=D.highres;
[n,m,p]=size(image);
if p==3
    highres=rgb2gray(image);
else
    highres=image;
end
axes(handles.axes2)
handles.highres=highres;
iptsetpref('ImshowAxesVisible', 'on')
imagesc(uint8(highres)), colormap(gray)
guidata(hObject,handles)

% --------------------------------------------------------------------
function Untitled_1_Callback(hObject, eventdata, handles)
% hObject    handle to Untitled_1 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

%% Main algorithm
% --- Executes on button press in Merge_resolution.
function Merge_resolution_Callback(hObject, eventdata, handles)
% hObject    handle to Merge_resolution (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
lowres=handles.lowres;
highres=handles.highres;
map=hot(256);
R=ind2rgb(lowres,map);
axes(handles.axes3)
iptsetpref('ImshowAxesVisible', 'on')
imagesc(R), colormap(hot)
HSV=rgb2hsv(R);
HSV_sub=HSV;
HSV_sub(:,:,3)=highres;
merged=hsv2rgb(HSV_sub);
merged=uint8(merged);
mergedG=rgb2gray(merged);
axes(handles.axes4)
iptsetpref('ImshowAxesVisible', 'on')
imagesc(uint8(mergedG)), colormap(gray)
handles.merged=merged;
handles.mergedG=mergedG;
guidata(hObject, handles);

% --- Executes on button press in displaycolor.
function displaycolor_Callback(hObject, eventdata, handles)
% hObject    handle to displaycolor (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of displaycolor
merged=handles.merged;
axes(handles.axes4)
iptsetpref('ImshowAxesVisible', 'on')
imagesc(uint8(merged))

% --- Executes on button press in disp_grayscale.
function disp_grayscale_Callback(hObject, eventdata, handles)
% hObject    handle to disp_grayscale (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

% Hint: get(hObject,'Value') returns toggle state of disp_grayscale
mergedG=handles.mergedG;
axes(handles.axes4)
iptsetpref('ImshowAxesVisible', 'on')
imagesc(uint8(mergedG)), colormap(gray)

% --------------------------------------------------------------------
function Untitled_2_Callback(hObject, eventdata, handles)
% hObject    handle to Untitled_2 (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)

%% Output section
% --------------------------------------------------------------------
function save_mat_Callback(hObject, eventdata, handles)
% hObject    handle to save_mat (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
mergedG=handles.mergedG;
merged=handles.merged;
datapath = uigetdir;
cd(datapath)
[filename, pathname] = uiputfile('*.mat', 'save merged image into mat file');
save(filename, 'merged','mergedG')

% --------------------------------------------------------------------
function save_tiff_Callback(hObject, eventdata, handles)
% hObject    handle to save_tiff (see GCBO)
% eventdata  reserved - to be defined in a future version of MATLAB
% handles    structure with handles and user data (see GUIDATA)
mergedG=handles.mergedG;
merged=handles.merged;
datapath = uigetdir;
cd(datapath)
imwrite(uint8(mergedG),'mergedG.tiff','tiff')
imwrite(uint8(merged),'merged.tiff','tiff')


function Inds = sllabelinds(labels, labelset)
%SLLABELINDS Extract indices corresponding to specified labels
%
% $ Syntax $
%   - Inds = sllabelinds(labels, labelset)
%
% $ Arguments $
%   - labels:       The labels of samples
%   - labelset:     The set of labels whose indices to be extracted
%   - Inds:         The cell array of indices extracted for labelset
%
% $ Description $
%   - Inds = sllabelinds(labels, labelset) extracts the indices
%     corresponding to the labels specified in labelset. Suppose the
%     labelset is given by [l1, l2, ...], then Inds would be like
%     {[i11, i12, ...], [i21, i22, ...], ...}, where [i11, i12, ...] is
%     a row vector of indices corresponding to l1, so that
%     labels(i11) = labels(i12) = ... = l1.
%
% $ History $
%   - Created by Dahua Lin, on Aug 31, 2006
%

%% parse and verify input

if ~isvector(labels) || ~isnumeric(labels)
    error('sltoolbox:invalidarg', ...
        'labels should be a numeric vector');
end

if size(labels, 1) ~= 1
    labels = labels(:)';
end

%% re-arrange

[labels, si] = sort(labels, 2, 'ascend');
[nums, labelfound] = slcount(labels);
[sinds, einds] = slnums2bounds(nums);
[sfound, smap] = ismember(labelset, labelfound);

%% extract

c = length(labelset);
Inds = cell(1, c);
for i = 1 : c
    if sfound(i)
        mi = smap(i);
        curinds = si(sinds(mi):einds(mi));
        Inds{i} = curinds;
    else
        Inds{i} = [];
    end
end


function y = qinvjmul(labx,frmx,b,K)
% y = qinvjmul(labx,frmx,b,K)
%
% QINVJMUL  Inverse of Jordan multiply for Lorentz blocks
%
% **********  INTERNAL FUNCTION OF SEDUMI **********
%
% See also sedumi

% This file is part of SeDuMi 1.1 by Imre Polik and Oleksandr Romanko
% Copyright (C) 2005 McMaster University, Hamilton, CANADA  (since 1.1)
%
% Copyright (C) 2001 Jos F. Sturm (up to 1.05R5)
%   Dept. Econometrics & O.R., Tilburg University, the Netherlands.
%   Supported by the Netherlands Organization for Scientific Research (NWO).
%
% Affiliation SeDuMi 1.03 and 1.04Beta (2000):
%   Dept. Quantitative Economics, Maastricht University, the Netherlands.
%
% Affiliations up to SeDuMi 1.02 (AUG1998):
%   CRL, McMaster University, Canada.
%   Supported by the Netherlands Organization for Scientific Research (NWO).
%
% This program is free software; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2 of the License, or
% (at your option) any later version.
%
% This program is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program; if not, write to the Free Software
% Foundation, Inc.,  51 Franklin Street, Fifth Floor, Boston, MA
% 02110-1301, USA

lorN = length(K.q);
if lorN == 0
    y = zeros(0,1);
    return
end
if length(labx) > 2*lorN
    labx = labx(K.l+1:K.l+2*lorN);
end
detx = labx(1:lorN) .* labx(lorN+1:end);
x = qframeit(labx,frmx,K);
ix = K.mainblks;
if length(b) == ix(3)-ix(1);   % lorentz only ?
    ix = (1-ix(1)) + ix;
end
% ------------------------------------------------------------
% Let y1(k) = xk'Jbk/(sqrt2*detxk)
% ------------------------------------------------------------
y1 = x(1:lorN).*b(ix(1):ix(2)-1) - ddot(x(lorN+1:end),b,K.qblkstart);
y1 = y1./(sqrt(2)*detx);
% ------------------------------------------------------------
% Let y2[k] = (sqrt2/x1)*b2[k] - (y1/x1) * x2[k]
% ------------------------------------------------------------
y = [y1; qblkmul(sqrt(2)./x(1:lorN),b,K.qblkstart)...
    - qblkmul(y1./x(1:lorN),x(lorN+1:end),K.qblkstart)];


function [L,S,errHist] = solver_RPCA_constrained(AY,lambda_S, tau, A_cell, opts)
% [L,S,errHist] = solver_RPCA_constrained(Y,lambda_S, tau, A_cell, opts)
% Solves the problem
%   minimize_{L,S} .5|| L + S - Y ||_F^2
%   subject to
%   if opts.sum = true
%       (1)  ||L||_* + lambda_S ||S||_1 <= tau
%   if opts.max = true
%       (2) max(  ||L||_* , lambda_S ||S||_1 ) <= tau
%
%   if opts.max and opts.sum are false and tau is a negative number, then
%   we solve the problem:
%       minimize_{L,S} .5|| L + S - Y ||_F^2  + abs(tau)*( ||L||_* + lambda_S ||S||_1 )
%   (but see solver_RPCA_Lagrangian.m for a simpler interface)
%
%   or if A_cell is provided, where A_cell = {A, At}
%   (A is a function handle, At is a function handle to the transpose of A)
%   then
%
%   minimize_{L,S} .5|| A(L + S) - Y ||_F^2
%       subject to ...
%   (here, Y usually represents A(Y); if Y is not the same size
%    as A(L), then we will automatically set Y <-- A(Y) )
%
%   errHist(:,1) is a record of the residual
%   errHist(:,2) is a record of the full objective (that is, .5*resid^2 )
%   errHist(:,3) is the output of opts.errFcn if provided
%
% opts is a structure with options:
%   opts.sum, opts.max  (as described above)
%   opts.L0         initial guess for L (default is 0)
%   opts.S0         initial guess for S (default is 0)
%   opts.size       [n1,n2] where L and S are n1 x n2 matrices. The size is automatically
%       determined in most cases, but when providing a linear operator
%       it may be necessary to provide an explicit size.
%   opts.tol        sets stopping tolerance
%   opts.maxIts     sets maximum number of iterations
%   opts.printEvery will print information this many iterations
%   opts.displayTime will print out timing information (default is true for large problems)
%   opts.errFcn     a function of (L,S) that records information
%   opts.trueObj    if provided, this will be subtracted from errHist(2,:)
%   opts.Lip        Lipschitz constant, i.e., 2*spectralNorm(A)^2
%                       by default, assume 2 (e.g., good if A = P_Omega)
%   opts.FISTA      whether to use FISTA or not. By default, true
%     opts.restart  how often to restart FISTA; set to -Inf to make it automatic
%   opts.BB         whether to use the Barzilai-Borwein spectral steplength
%     opts.BB_type  which BB stepsize to take. Default is 1, the larger step
%     opts.BB_split whether to calculate stepslengths for S and L independently.
%       Default is false, which is recommended.
%   opts.quasiNewton  uses quasi-Newton-like Gauss-Seidel scheme.
%                     Only available in "max" mode
%     opts.quasiNewton_stepsize     stepsize length. Default is .8*(2/Lip)
%     opts.quasinewton_SLS          whether to take S-L-S sequence (default is true)
%                                   otherwise, takes a L-S Gauss-Seidel sequence
%   opts.SVDstyle   controls what type of SVD is performed.
%       1 = full svd using matlab's "svd". Best for small problems
%       2 = partial svd using matlab's "svds". Not recommended.
%       3 = partial svd using PROPACK, if installed. Better than option 2, worse than 4
%       4 = partial svd using randomized linear algebra, following
%           the Halko/Tropp/Martinnson "Structure in Randomness" paper
%       in option 4, there are additional options:
%       opts.SVDwarmstart   whether to "warm-start" the algorithm
%       opts.SVDnPower  number of power iterations (default is 2 unless warm start)
%       opts.SVDoffset  oversampling, e.g., "rho" in Tropp's paper. Default is 5
%
%   opts.L1L2      instead of using l1 penalty, e.g., norm(S(:),1), we can
%       also use block norm penalties, such as (if opts.L1L2 = 'rows')
%       the sum of the l2-norm of rows (i.e., l1-norm of rows),
%       or if opts.L1L2='cols', the sum of the l2-norms of colimns.
%       By default, or if opts.L1L2 = [] or false, then uses usual l1 norm.
%       [Feature added April 17 2015]
%
%  Features that may be added later: [email developers if these are
%    important to you]
%       - Allow Huber loss function.
%
% Stephen Becker, March 6 2014. Edited March 14 2014, April 2015.
%   stephen.becker@colorad.edu
% See also solver_RPCA_Lagrangian.m, solver_RPCA_SPGL1.m

% todo: allow S >= 0 constraints, since this is easy
% todo: allow Huber loss function

error(nargchk(3,5,nargin,'struct'));
if nargin < 5, opts = []; end
% == PROCESS OPTIONS ==
function out = setOpts( field, default )
    if ~isfield( opts, field )
        opts.(field)    = default;
    end
    out = opts.(field);
    opts    = rmfield( opts, field ); % so we can do a check later
end

if nargin < 4 || isempty(A_cell)
    A   = @(X) X(:);
    [n1,n2] = size(AY);
    At  = @(x) reshape(x,n1,n2);

    if ~iscell(tau)
        AY  = A(AY);
    end
    % The factor of 2 is since we are in both L and S
else
    A   = A_cell{1};
    At  = A_cell{2};
    % Y could be either Y or A(Y)
    if size(AY,2) > 1
        % AY is a vector, so it is probably Y and not AY
        disp('Changing Y to A(Y)');
        AY = A(AY);
        [n1,n2] = size(AY); % April 24 '14
    else
        % April 24, '14: we need to know the (n1,n2)
        sz      = setOpts('size',[] );
        if isempty(sz)
            error('Cannot determine the size of the variables; please specify opts.size=[n1,n2]');
        end
        n1 = sz(1);
        n2 = sz(2);
    end
    %[n1,n2] = size(AY); % comment out April 24 '14
end
normAY =    norm(AY(:));

vec = @(X) X(:);

% Some problem sizes. Feel free to tweak. Mainly affect the defaults
SMALL   = ( n1*n2 <= 50^2 );
MEDIUM  = ( n1*n2 <= 200^2 ) && ~SMALL;
LARGE   = ( n1*n2 <= 1000^2 ) && ~SMALL && ~MEDIUM;
HUGE    = ( n1*n2 > 1000^2 );

% -- PROCESS OPTIONS -- (some defaults depend on problem size )
tol     = setOpts('tol',1e-6*(SMALL | MEDIUM) + 1e-4*LARGE + 1e-3*HUGE );
maxIts  = setOpts('maxIts', 1e3*(SMALL | MEDIUM ) + 400*LARGE + 200*HUGE );
printEvery  = setOpts('printEvery',100*SMALL + 50*MEDIUM + 5*LARGE + 1*HUGE);
errFcn      = setOpts('errFcn', [] );
Lip         = setOpts('Lip', 2 );
restart     = setOpts('restart',-Inf);
trueObj     = setOpts('trueObj',0);
sumProject  = setOpts('sum', false );
maxProject  = setOpts('max', false );

if tau < 0
	Lagrangian = true;
	if sumProject || maxProject
		error('in Lagrangian mode (when tau<0 significies lambda=|tau|), turn off sum/maxProject');
	end
	lambda = abs(tau);
	tau = []; % help us track down bugs
else
	Lagrangian = false;
	if (sumProject && maxProject) || (~sumProject && ~maxProject), error('must choose either "sum" or "max" type projection'); end
end

QUASINEWTON = setOpts('quasiNewton', maxProject || Lagrangian );
FISTA       = setOpts('FISTA',~QUASINEWTON);
BB          = setOpts('BB',~QUASINEWTON);
% Note: BB with FISTA is sometimesm not so good
if BB && FISTA, warning('solver_RPCA:convergence','Convergence not guaranteed with FISTA if opts.BB=true'); end
BB_split    = setOpts('BB_split',false);
BB_type     = setOpts('BB_type',1); % 1 or 2
stepsizeQN  = setOpts('quasiNewton_stepsize', .8*2/Lip );
S_L_S       = setOpts('quasiNewton_SLS', true );
displayTime = setOpts('displayTime',LARGE | HUGE );
SVDstyle    = setOpts('SVDstyle', 1*SMALL + 4*(~SMALL) ); % 1 is full SVD
% and even finer tuning (only matter if SVDstyle==4)
SVDwarmstart= setOpts('SVDwarmstart', true );
SVDnPower   = setOpts('SVDnPower', 1 + ~SVDwarmstart ); % number of power iteratiosn
SVDoffset   = setOpts('SVDoffset', 5 );
SVDopts = struct('SVDstyle', SVDstyle,'warmstart',SVDwarmstart,...
    'nPower',SVDnPower,'offset',SVDoffset );

if QUASINEWTON
    if sumProject
        error('Can not run quasi-Newton mode when in "sum" formulation. Please change to "max"');
    elseif FISTA
        error('Can not run quasi-Newton with FISTA');
    elseif BB
        error('Can not run quasi-Newton with BB');
    end
end

% April 17 2015
L1L2        = setOpts('L1L2',0);
if isempty(L1L2), L1L2=0; end
if L1L2,
    if ~isempty(strfind(lower(L1L2),'row')),  L1L2 = 'rows';
    elseif ~isempty(strfind(lower(L1L2),'col')),  L1L2 = 'cols';
        % so col, COL, cols, columns, etc. all acceptable
    else
        error('unrecognized option for L1L2: should be row or column or 0');
    end
end

projNuclear(); % remove any persistent variables
if maxProject
    project = @(L,S,varargin) projectMax(L1L2,tau,lambda_S,SVDopts, L,S);
elseif sumProject
    if any(L1L2), error('with opts.sum=true, need opts.L1L2=0'); end
    project = @(L,S,varargin) projectSum(tau,lambda_S,L,S);
elseif Lagrangian
    project = @(L,S,varargin) projectMax(L1L2,lambda,lambda*lambda_S,SVDopts, L,S, varargin{:});
end

L           = setOpts('L0',zeros(n1,n2) );
S           = setOpts('S0',zeros(n1,n2) );

% Check for extra options that were not processed
if ~isempty( fieldnames(opts ) )
    disp( 'warning, found extra guys in opts');
    disp( opts )
    error('Found unprocessed options in "opts"');
end

stepsize    = 1/Lip;
errHist     = zeros(maxIts, 2 + ~isempty(errFcn) );
Grad        = 0;
if FISTA || BB || QUASINEWTON
    L_old   = L;
    S_old   = S;
end
L_fista     = L;
S_fista     = S;
BREAK   = false;
kk      = 0; % counter for FISTA
timeRef = tic;
for k = 1:maxIts
    % Gradient in (L,S) (at the fista point) is (R,R) where...
    R   = A(L_fista + S_fista) - AY;
    Grad_old    = Grad;
    Grad        = At(R);

    objL        = Inf;
    if QUASINEWTON
%         stepsizeQN  = 1 - min(0.1, 1/k );
%         stepsizeQN = 1 - .3/sqrt(k);

        if S_L_S
            % we solve for S, update L, then re-update S
            % Exploits the fact that projection for S is faster
            dL      = L - L_old;
            S_old   = S;
            [~,S_temp]   = project( [], S - stepsizeQN*( Grad + dL ), stepsizeQN ); % take small step...

            dS      = S_temp - S_old;
            L_old   = L;
            [L,~,rnk,objL]   = project( L - stepsizeQN*( Grad + dS ), [], stepsizeQN );

            dL      = L - L_old;
            [~,S]   = project( [], S - stepsizeQN*( Grad + dL ) , stepsizeQN);
        else
            % Gauss-Seidel update, starting with L, then S
            % Changing order seemed to not work as well
            dS      = S - S_old;
            L_old   = L;
            [L,~,rnk,objL]   = project( L - stepsizeQN*( Grad + dS ), [] , stepsizeQN);
            dL      = L - L_old;
            S_old   = S;
            [~,S]   = project( [], S - stepsizeQN*( Grad + dL ) , stepsizeQN);
        end
%         stepsizeQN = (1+3*stepsizeQN)/4;
    else
        if BB && k > 1
            [stepsizeL, stepsizeS]  = compute_BB_stepsize( Grad, Grad_old, L, L_old, S, S_old, BB_split, BB_type);
            if isnan(stepsizeL) || isnan(stepsizeS)
                fprintf(2,'Warning: no BB stepsize possible since iterates have not changed!\n');
                [stepsizeL, stepsizeS]   = deal( stepsize );
            end
        else
            [stepsizeL, stepsizeS]   = deal( stepsize );
        end

        % Now compute proximity step
        if FISTA || BB
            L_old   = L;
            S_old   = S;
        end
        L           = L_fista - stepsizeL*Grad;
        S           = S_fista - stepsizeS*Grad;
        if any(isnan(L(:))) || any(isnan(S(:))), fprintf(2,'DEBUG!\n'); keyboard; end
        [L,S,rnk,objL]   = project( L, S, stepsizeL, stepsizeS);
        if any(isnan(L(:))) || any(isnan(S(:))), fprintf(2,'DEBUG!\n'); keyboard; end
    end

    DO_RESTART = false;
    if FISTA
        if k>1 && restart > 0 && ~isinf(restart) && ~mod(kk,restart)
            kk = 0;
            DO_RESTART  = true;
        elseif restart==-Inf && kk > 5
            % In this case, we restart if the function has significantly increased
            if (errHist(k-1,2)-errHist(k-5,2)) > 1e-8*abs(errHist(k-5,2))
                DO_RESTART = true;
                kk = 0;
            end
        end
        L_fista = L + kk/(kk+3)*( L - L_old );
        S_fista = S + kk/(kk+3)*( S - S_old );
        kk      = kk + 1;
    else
        L_fista = L;
        S_fista = S;
    end

%     res          = norm(R(:)); % this is for L_fista, not L
    R            = A(L + S) - AY;
    % sometimes we already have R pre-computed, so if this turns out to
    %   be a signficant computational cost we can make fancier code...
    res          = norm(R(:));
    errHist(k,1) = res;
    errHist(k,2) = 1/2*(res^2); % + lambda_L*objL + lambda_S*objS;
    if Lagrangian
        errHist(k,2) = errHist(k,2) + lambda*objL;
        if any(L1L2)
            if strcmpi(L1L2,'rows')
                errHist(k,2) = errHist(k,2) + lambda*lambda_S*sum( sqrt( sum(S.^2,2) ) );
            else
                errHist(k,2) = errHist(k,2) + lambda*lambda_S*sum( sqrt( sum(S.^2,1) ) );
            end
        else
            errHist(k,2) = errHist(k,2) + lambda*lambda_S*norm(S(:),1);
        end
    end
    if k > 1 && abs(diff(errHist(k-1:k,1)))/res < tol
        BREAK = true;
    end
    PRINT   = ~mod(k,printEvery) | BREAK | DO_RESTART;
    if PRINT
        fprintf('Iter %4d, rel. residual %.2e, objective %.2e', k, res/normAY, errHist(k,2) -trueObj);
    end
    if ~isempty(errFcn)
        err     = errFcn(L,S);
        errHist(k,3)    = err;
        if PRINT, fprintf(', err %.2e', err ); end
    end
    if ~isempty(rnk) && PRINT, fprintf(', rank(L) %3d', rnk ); end
    if PRINT
        fprintf(', sparsity(S) %5.1f%%', 100*nnz(S)/numel(S) );
    end
    if displayTime && PRINT
        tm = toc( timeRef ); timeRef = tic;
        fprintf(', time %.1f s', tm );
    end
    if DO_RESTART, fprintf(' [restarted FISTA]'); end
    if PRINT, fprintf('\n'); end
    if BREAK
        fprintf('Reached stopping criteria (based on change in residual)\n');
        break;
    end
end
if BREAK
    errHist = errHist(1:k,:);
else
    fprintf('Reached maximum number of allowed iterations\n');
end

end

% subfunctions for projection
function [L,S,rnk,nuclearNorm] = projectMax( L1L2, tau, lambda_S,SVDopts, L, S , stepsize, stepsizeS)
 if nargin >= 7 && ~isempty(stepsize)
     % we compute proximity, not projection
     tauL 	= -abs( tau*stepsize );
     if nargin < 8 || isempty( stepsizeS ), stepsizeS = stepsize; end
     tauS 	= -abs( lambda_S*stepsizeS );
 else
     tauL 	= abs(tau);
     tauS 	= abs(tau/lambda_S );
 end

 % We project separately, so very easy
 if ~isempty(L)
     [L,rnk,nuclearNorm]  = projNuclear(tauL, L,SVDopts);
     if tauL > 0
         % we did projection, so this should be feasible
         nuclearNorm = 0;
     end
 else
     rnk = [];
     nuclearNorm = 0;
 end

 if ~isempty(S)
     if tauS > 0
         if ~any(L1L2)
             % use the l1 norm
             projS  = project_l1(tauS);
         elseif strcmpi(L1L2,'rows')
             projS  = project_l1l2(tauS,true);
         elseif strcmpi(L1L2,'cols')
             projS  = project_l1l2(tauS,false);
         else
             error('bad value for L1L2: should be [], ''rows'' or ''cols'' ');
         end
         S  = projS( S );
     else
         if ~any(L1L2)
             % use the l1 norm
             % simple prox
             S = sign(S).*max(0, abs(S) - abs(tauS));
         elseif strcmpi(L1L2,'rows')
             projS  = prox_l1l2(abs(tauS));
             S      = projS(S,1);
         elseif strcmpi(L1L2,'cols')
             projS  = prox_l1l2(abs(tauS));
             S      = projS(S',1)';
         else
             error('bad value for L1L2: should be [], ''rows'' or ''cols'' ');
         end

     end
 end
end

function [X,rEst,nrm] = projNuclear( tau, X, SVDopts )
 % Input must be a matrix, not a vector
 % Computes either the proximity operator of the nuclear norm (if tau<0)
 % or projection onto the nuclear norm ball of radius tau (if tau>0)

 persistent oldRank Vold iteration
 if nargin==0, oldRank=[]; Vold = []; iteration = 0; return; end
 if isempty(oldRank), rEst = 10;
 else, rEst = oldRank + 2;
 end
 if isempty(iteration), iteration = 0; end
 iteration   = iteration + 1;
 [n1,n2]     = size(X);
 minN       = min( [n1,n2] ); % could set smaller to make nonconvex
 % For the first few iterations, we constrain rankMax
 switch iteration
     case 1
         rankMax     = round(minN/4);
     case 2
         rankMax     = round(minN/2);
     otherwise
         rankMax     = minN;
 end

 style = SVDopts.SVDstyle;
 if tau==0, X=0*X; return; end

 switch style
     case 1
         % full SVD
         [U,S,V] = svd(X,'econ');
         s   = diag(S);
         if tau < 0 % we do prox
             s = max( 0, s - abs(tau) );
         else
             s = project_simplex( tau, s );
         end
         tt      = s > 0;
         rEst    = nnz(tt);
         U       = U(:,tt);
         S       = diag(s(tt));
         V       = V(:,tt);
         nrm     = sum(s(tt));
     case {2,3,4}
         % 2: use Matlab's sparse SVD
         % 3: use PROPACK
         % 4: use Joel Tropp's randomized SVD
         if style==2
             opts = struct('tol',1e-4);
             if rankMax==1, opts.tol = min(opts.tol,1e-6); end % important!
             svdFcn = @(X,rEst)svds(X,rEst,'L',opts);
         elseif style==3
             opts = struct('tol',1e-4,'eta',eps);
             opts.delta = 10*opts.eta;
             % set eta to eps, but not 0 otherwise reorth is very slow
             if rankMax==1, opts.tol = min(opts.tol,1e-6); end % important!
             svdFcn = @(X,rEst)lansvd(X,rEst,'L',opts);
         elseif style == 4
             opts = [];
             if isfield(SVDopts,'nPower') && ~isempty( SVDopts.nPower )
                 nPower = SVDopts.nPower;
             else
                 nPower = 2;
             end
             if isfield(SVDopts,'offset') && ~isempty( SVDopts.offset )
                 offset = SVDopts.offset;
             else
                 offset = 5;
             end
             if isfield( SVDopts, 'warmstart' ) && SVDopts.warmstart==true ...
                     && ~isempty(Vold)
                 opts = struct( 'warmStart', Vold );
             end
             ell     = @(r) min([r+offset,n1,n2]); % number of samples to take
             svdFcn = @(X,rEst)randomizedSVD(X,rEst,ell(rEst),nPower,[],opts );
         end

         ok  = false;
         while ~ok
             rEst    = min( [rEst,rankMax] );
             [U,S,V] = svdFcn(X,rEst);
             s       = diag(S);
             if tau < 0
                 % we are doing prox
                 lambda = abs(tau);
             else
                 lambda  = findTau(s,tau);
             end
             ok      = ( min(s) < lambda ) || (rEst == rankMax);
             if ok, break; end
             rEst    = 2*rEst;
         end
         rEst = min( length(find(s>lambda)), rankMax );
         S   = diag( s(1:rEst) - lambda );
         U   = U(:,1:rEst);
         V   = V(:,1:rEst);
         nrm = sum( s(1:rEst) - lambda );
     otherwise
         error('bad value for SVDstyle');
 end
 if isempty(U)
     X = 0*X;
 else
     X = U*S*V';
 end
 oldRank = size(U,2);
 if isfield( SVDopts, 'warmstart' ) && SVDopts.warmstart==true
     Vold = V;
 end
end

function x = project_simplex( q, x )
 % projects onto the constraints sum(x)=q and x >= 0
 % Update: projects onto sum(x) <= q and x >= 0

 x     = x.*( x > 0 ); % March 11 '14
 % March 11, fixing bug: we want to project onto the volume, not
 %   the actual simplex (surface)
 if sum(x) <= q, return; end
 if q==0, x = 0*x; return; end

 s     = sort( x, 'descend' );
 if q < eps(s(1))
     % eps(x) is the distance from abs(x) to the next larger
     %   floating point number, i.e., in floating point arithmetic,
     %   x + eps(x)/2 = x
     % eps(1) is about 2.2e-16

     error('Input is scaled so large compared to q that accurate computations are difficult');
     % since then cs(1) = s(1) - q is  not even guaranteed to be
     % smaller than q !
 end
 cs    = ( cumsum(s) - q ) ./ ( 1 : numel(s) )';
 ndx   = nnz( s > cs );
 x     = max( x - cs(ndx), 0 );
end

function tau = findTau( s, lambda )
 % Returns the shrinkage value necessary to shrink the vector s
 %   so that it is in the lambda scaled simplex
 %   Usually, s is the diagonal part of an SVD
 if all(s==0)||lambda==0, tau=0; return; end
 if numel(s)>length(s), error('s should be a vector, not a matrix'); end
 if ~issorted(flipud(s)), s = sort(s, 'descend'); end
 if any( s < 0 ), error('s should be non-negative'); end

 % project onto the simplex of radius lambda (not tau)
 % and use this to find "tau" (the shrinkage amount)
 % If we know s_i > tau for i = 1, ..., k, then
 %   tau = ( sum(s(1:k)) - lambda )/k
 % But we don't know k, so find it:
 cs  = (cumsum(s) - abs(lambda) )./(1:length(s))';
 ndx = nnz( s > cs ); % >= 1 as long as lambda > 0
 tau = max(0,cs(ndx));
 % We want to make sure we project onto sum(sigma) <= lambda
 %   and not sum(sigma) == lambda, so do not allow negative tau

end

function [L,S,rnk,nuclearNorm] = projectSum( tau, lambda_S, L, S )
  [m,n]           = size(L);
  [U,Sigma,V]     = svd(L,'econ');
  s       = diag(Sigma);
  wts     = [ ones(length(s),1); lambda_S*ones(m*n,1) ];
  proj    = project_l1(tau,wts);
  sS      = proj( [s;vec(S)] );
  sProj   = sS(1:length(s));
  S       = reshape( sS(length(s)+1:end), m, n );
  L       = U*diag(sProj)*V';
  rnk     = nnz( sProj );
  nuclearNorm = sum(sProj);
end

function [stepsizeL, stepsizeS]  = compute_BB_stepsize( ...
    Grad, Grad_old, L, L_old, S, S_old, BB_split, BB_type)

  if ~BB_split
      % we take a Barzilai-Borwein stepsize in the full variable
      yk  = Grad(:) - Grad_old(:);
      yk  = [yk;yk]; % to account for both variables
      sk  = [L(:) - L_old(:); S(:) - S_old(:) ];
      if BB_type == 1
          % Default. The bigger stepsize
          stepsize    = norm(sk)^2/(sk'*yk);
      elseif BB_type == 2
          stepsize    = sk'*yk/(norm(yk)^2);
      end
      [stepsizeL, stepsizeS] = deal( stepsize );

  elseif BB_split
      % treat L and S variables separately
      % Doesn't seem to work well.
      yk  = Grad(:) - Grad_old(:);
      skL  = L(:) - L_old(:);
      skS  = S(:) - S_old(:);
      if BB_type == 1
          % Default. The bigger stepsize
          stepsizeL   = norm(skL)^2/(skL'*yk);
          stepsizeS   = norm(skS)^2/(skS'*yk);
      elseif BB_type == 2
          stepsizeL   = skL'*yk/(norm(yk)^2);
          stepsizeS   = skS'*yk/(norm(yk)^2);
      end
  end
end

function op = project_l1( q , d)
%PROJECT_L1   Projection onto the scaled 1-norm ball.
%    OP = PROJECT_L1( Q ) returns an operator implementing the
%    indicator function for the 1-norm ball of radius q,
%    { X | norm( X, 1 ) <= q }. Q is optional; if omitted,
%    Q=1 is assumed. But if Q is supplied, it must be a positive
%    real scalar.
%
%    OP = PROJECT_L1( Q, D ) uses a scaled 1-norm ball of radius q,
%    { X | norm( D.*X, 1 ) <= 1 }. D should be the same size as X
%    and non-negative (some zero entries are OK).

% Note: theoretically, this can be done in O(n)
%   but in practice, worst-case O(n) median sorts are slow
%   and instead average-case O(n) median sorts are used.
%   But in matlab, the median is no faster than sort
%   (the sort is probably quicksort, O(n log n) expected, with
%    good constants, but O(n^2) worst-case).
%   So, we use the naive implementation with the sort, since
%   that is, in practice, the fastest.

 if nargin == 0,
     q = 1;
 elseif ~isnumeric( q ) || ~isreal( q ) || numel( q ) ~= 1 || q <= 0,
     error( 'Argument must be positive.' );
 end
 if nargin < 2 || isempty(d) || numel(d)==1
     if nargin>=2 && ~isempty(d)
         % d is a scalar, so norm( d*x ) <= q is same as norm(x)<=q/d
         if d==0
             error('If d==0 in proj_l1, the set is just {0}, so use proj_0');
         elseif d < 0
             error('Require d >= 0');
         end
         q = q/d;
     end
     op = @(varargin)proj_l1_q(q, varargin{:} );
 else
     if any(d<0)
         error('All entries of d must be non-negative');
     end
     op = @(varargin)proj_l1_q_d(q, d, varargin{:} );
 end

 % This is modified from TFOCS, Nov 26 2013, Stephen Becker
 % Note: removing "v" (value) output from TFOCS code
 %   Also removing extraneous inputs
    function x = proj_l1_q( q, x, varargin )
        myReshape   = @(x) x; % do nothing
        if size(x,2) > 1
            if ndims(x) > 2, error('You must modify this code to deal with tensors'); end
            myReshape     = @(y) reshape( y, size(x,1), size(x,2) );
            x   = x(:); % make it into a vector
        end
        s      = sort(abs(nonzeros(x)),'descend');
        cs     = cumsum(s);
        % ndx    = find( cs - (1:numel(s))' .* [ s(2:end) ; 0 ] >= q, 1 );
        ndx    = find( cs - (1:numel(s))' .* [ s(2:end) ; 0 ] >= q+2*eps(q), 1 ); % For stability
        if ~isempty( ndx )
            thresh = ( cs(ndx) - q ) / ndx;
            x      = x .* ( 1 - thresh ./ max( abs(x), thresh ) ); % May divide very small numbers
        end
        x   = myReshape(x);
    end

% Allows scaling. Added Feb 21 2014
    function x = proj_l1_q_d( q, d,  x, varargin )
        myReshape   = @(x) x; % do nothing
        if size(x,2) > 1
            if ndims(x) > 2, error('You must modify this code to deal with tensors'); end
            myReshape     = @(y) reshape( y, size(x,1), size(x,2) );
            x   = x(:); % make it into a vector
        end
        [goodInd,j,xOverD] = find( x./ d );
        [lambdas,srt]      = sort(abs(xOverD),'descend');
        s   = abs(x(goodInd).*d(goodInd));
        s   = s(srt);
        dd  = d(goodInd).^2;
        dd  = dd(srt);
        cs  = cumsum(s);
        cd  = cumsum(dd);
        ndx    = find( cs - lambdas.*cd >= q+2*eps(q), 1, 'first');
        if ~isempty( ndx )
            ndx     = ndx - 1;
            lambda  = ( cs(ndx) - q )/cd(ndx);
            x       = sign(x).*max( 0, abs(x) - lambda*d );
        end
        x   = myReshape(x);
    end

end

% Copied from TFOCS, April 17 2015
function op = project_l1l2( q, rowNorms )
%PROJ_L1L2    L1-L2 block norm: sum of L2 norms of rows.
%    OP = PROJ_L1L2( q ) implements the constraint set
%        {X | sum_{i=1:m} norm(X(i,:),2) <= 1 }
%    where X is a m x n matrix.  If n = 1, this is equivalent
%    to PROJ_L1. If m=1, this is equivalent to PROJ_L2
%
%    Q is optional; if omitted, Q=1 is assumed. But if Q is supplied,
%    then it must be positive and real and a scalar.
%
%   OP = PROJ_L1L2( q, rowNorms )
%     will either do the sum of the l2-norms of rows if rowNorms=true
%       (the default), or the sum of the l2-norms of columns if
%       rowNorms = false.
%
%   Known issues: doesn't yet work with complex-valued data.
%       Should be easy to fix, so email developers if this is
%       needed for your problem.
%
% Dual: prox_linfl2.m [not yet available]
% See also prox_l1l2.m, proj_l1.m, proj_l2.m

    if nargin == 0 || isempty(q),
        q = 1;
    elseif ~isnumeric( q ) || ~isreal( q ) || any(q <= 0) ||numel(q)>1,
        error( 'Argument must be positive and a scalar.' );
    end

    if nargin<2 || isempty(rowNorms)
        rowNorms = true;
    end

    if rowNorms
        op = @(x,varargin)prox_f_rows(q,x);
    else
        op = @(x,varargin)prox_f_cols(q,x);
    end

    function X = prox_f_rows(tau,X)
        nrms    = sqrt( sum( X.^2, 2 ) );
        % When we include a row of x, corresponding to row y of Y,
        % its contribution is norm(y)-lambda
        % So we have sum_{i=1}^m max(0, norm(y_0)-lambda)
        % So, basically project nrms onto the l1 ball...
        s      = sort( nrms, 'descend' );
        cs     = cumsum(s);

        ndx    = find( cs - (1:numel(s))' .* [ s(2:end) ; 0 ] >= tau+2*eps(tau), 1 ); % For stability

        if ~isempty( ndx )
            thresh = ( cs(ndx) - tau ) / ndx;
            % Apply to relevant rows
            d   = max( 0, 1-thresh./nrms );
            m   = size(X,1);
            X   = spdiags( d, 0, m, m )*X;
        end
    end

    function X = prox_f_cols(tau,X)
        nrms    = sqrt( sum( X.^2, 1 ) ).';
        s      = sort( nrms, 'descend' );
        cs     = cumsum(s);

        ndx    = find( cs - (1:numel(s))' .* [ s(2:end) ; 0 ] >= tau+2*eps(tau), 1 ); % For stability

        if ~isempty( ndx )
            thresh = ( cs(ndx) - tau ) / ndx;
            d   = max( 0, 1-thresh./nrms );
            n   = size(X,2);
            X   = X*spdiags( d, 0, n,n );
        end
    end

end % end projection_l1l2.m

% Copied from TRFOCS April 17 2015
function op = prox_l1l2( q )
%PROX_L1L2    L1-L2 block norm: sum of L2 norms of rows.
%    OP = PROX_L1L2( q ) implements the nonsmooth function
%        OP(X) = q * sum_{i=1:m} norm(X(i,:),2)
%    where X is a m x n matrix.  If n = 1, this is equivalent
%    to PROX_L1
%    Q is optional; if omitted, Q=1 is assumed. But if Q is supplied,
%    then it must be positive and real.
%    If Q is a vector, it must be m x 1, and in this case,
%    the weighted norm OP(X) = sum_{i} Q(i)*norm(X(i,:),2)
%    is calculated.
%
% Dual: proj_linfl2.m
% See also proj_linfl2.m, proj_l1l2.m

    if nargin == 0,
        q = 1;
    elseif ~isnumeric( q ) || ~isreal( q ) || any(q <= 0),
        error( 'Argument must be positive.' );
    end
    op = @(x,t)prox_f(q,x,t);

    function x = prox_f(q,x,t)
        if nargin < 3,
            error( 'Not enough arguments.' );
        end
        v = sqrt( sum(x.^2,2) );
        s = 1 - 1 ./ max( v ./ ( t .* q ), 1 );
        m = length(s);
        x = spdiags(s,0,m,m)*x;
    end

end


function cvx_optpnt = exponential( sx )

%EXPONENTIAL   Exponential cone.
%   EXPONENTIAL, called with no arguments, creates three scalar variables X,
%   Y, and Z and constraints them to lie in an exponetial cone. That is,
%   given the declaration
%       variables x y z
%       {x,y,z} == exp_cone
%   constraints the variables to satisfy
%       y*exp(x/y) <= z
%       y > 0
%   The inequality form does not obey the disciplined convex programming
%   ruleset, but a function EXP_P has been created to represent this
%   computation; so the set declaration above is equivalent to
%       EXP_P(X,Y) <= Z
%   EXP_CONE(SX), where SX is a size vector, creates three array variables
%   X, Y, and Z, each of size SX, which are constrained elementwise to
%   satisfy EXP_P(X,Y) <= Z. If SX is empty, then SX=[1,1] is assumed.

cvx_expert_check( 'exponential' );
narginchk(0,1);

%
% Check size vector
%

if nargin == 0 || isempty( sx ),
    sx = [1,1]; %#ok
else
    [ temp, sx ] = cvx_check_dimlist( sx, true ); %#ok
    if ~temp,
        error( 'First argument must be a dimension vector.' );
    end
end

%
% Build the cone
%

cvx_begin set
    variables x( sx ) y( sx ) z( sx )
    [ tx, dummy ] = find( cvx_basis( x ) ); %#ok
    [ ty, dummy ] = find( cvx_basis( y ) ); %#ok
    [ tz, dummy ] = find( cvx_basis( z ) ); %#ok
    newnonl( cvx_problem, 'exponential', [ tx(:)' ; ty(:)' ; tz(:)' ] );
    cvx___.canslack( tx ) = false;
    cvx___.canslack( ty ) = false;
cvx_end

cvx_optpnt = cvxtuple( struct( 'x', x, 'y', y, 'z', z ) );

% Copyright 2005-2016 CVX Research, Inc.
% See the file LICENSE.txt for full copyright information.
% The command 'cvx_where' will show where this file is located.


% Make the following HHMM
%
%     LH                  RH
%    /                      \
%   /                        \
%  LR -> UD -> RL -> DU       RL -> UD -> LR -> DU
%   \
%    \
%     Q1 -> Q2
%
% where level 1 is fully interconnected (not shown)
% level 2 is left-right
% and each model at level 3 is a 2 state LR shared HMM

Qsizes = [2 4 2];
D = 3;

% LEVEL 1

startprob1 = 'ergodic';
transprob1 = 'ergodic';

% LEVEL 2

startprob = zeros(2, 4);
%        Q1  Q2
startprob(1, 1) = 1;
startprob(2, 3) = 1;

transprob = zeros(2, 4, 4);
transprob(1,:,:) = [0 1 0 0
		    0 0 1 0
		    0 0 0 1
		    0 0 0 1];
transprob(2,:,:) = [0 0 0 1
		    1 0 0 0
		    0 1 0 0
		    0 0 0 1];

Q2args = {'startprob', startprob, 'transprob', transprob};

% always terminate in state 4 (default)
% F2args

% LEVEL 3

% Defaults are fine: always start in state 1, left-right model, finish in state 2

% OBS LEVEl

chars = ['L', 'l', 'U', 'u', 'R', 'r', 'D', 'd'];
Osize = length(chars);

obsprob = zeros([4 2 Osize]);
%       Q2 Q3 O
obsprob(1, 1, find(chars == 'L')) =  1.0;
obsprob(1, 2, find(chars == 'l')) =  1.0;

obsprob(2, 1, find(chars == 'U')) =  1.0;
obsprob(2, 2, find(chars == 'u')) =  1.0;

obsprob(3, 1, find(chars == 'R')) =  1.0;
obsprob(3, 2, find(chars == 'r')) =  1.0;

obsprob(4, 1, find(chars == 'D')) =  1.0;
obsprob(4, 2, find(chars == 'd')) =  1.0;

Oargs = {'CPT', obsprob};

bnet = mk_hhmm3('Qsizes', Qsizes, 'Osize', Osize', 'discrete_obs', 1, 'Oargs', Oargs, 'Q1args', Q1args, 'Q2args', Q2args);

T = 20;
usecell = 0;
evidence = sample_dbn(bnet, T, usecell);
%chars(evidence(end,:))

Q1 = 1; Q2 = 2; Q3 = 3; F3 = 4; F2 = 5; obs = 6;
Qnodes = [Q1 Q2 Q3]; Fnodes = [F2 F3];

pretty_print_hhmm_parse(evidence, Qnodes, Fnodes, obs, chars);

eclass = bnet.equiv_class;
S=struct(bnet.CPD{eclass(Q2,2)})


function st_io_test03 ( )

%*****************************************************************************80
%
%% ST_IO_TEST03 tests ST_SORT_A.
%
%  Discussion:
%
%    The matrix is:
%
%      11  12   0   0  15
%      21  22   0   0   0
%       0   0  33   0  35
%       0   0   0  44   0
%      51   0  53   0  55
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    23 July 2014
%
%  Author:
%
%    John Burkardt
%
  m = 5;
  n = 5;
  nst = 11;
  ast = [ 51.0, 12.0, 11.0, 33.0, 15.0, 53.0, 55.0, 22.0, 35.0, 44.0, 21.0 ]';
  ist = [ 5, 1, 1, 3, 1, 5, 5, 2, 3, 4, 2 ];
  jst = [ 1, 2, 1, 3, 5, 3, 5, 2, 5, 4, 1 ];

  fprintf ( 1, '\n' );
  fprintf ( 1, 'ST_IO_TEST03\n' );
  fprintf ( 1, '  ST_SORT_A sorts an ST matrix by columns.\n' );

  i_min = min ( ist );
  i_max = max ( ist );
  j_min = min ( jst );
  j_max = max ( jst );

  st_header_print ( i_min, i_max, j_min, j_max, m, n, nst );

  st_print ( m, n, nst, ist, jst, ast, '  Matrix data before sorting:' );

  [ ist, jst, ast ] = st_sort_a ( m, n, nst, ist, jst, ast );

  st_print ( m, n, nst, ist, jst, ast, '  Matrix data after sorting:' );

  return
end


function r8_cscd_test ( )

%*****************************************************************************80
%
%% R8_CSCD_TEST tests R8_CSCD.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    12 January 2015
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'R8_CSCD_TEST\n' );
  fprintf ( 1, '  R8_CSCD computes the cosecant of an angle\n' );
  fprintf ( 1, '  given in degrees.\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  ANGLE    R8_CSCD(ANGLE)\n' );
  fprintf ( 1, '\n' );

  for i = 0 : 15 : 360
    angle = i;
    if ( mod ( i, 180 ) == 0 )
      fprintf ( 1, '  %8.2f    Undefined\n', angle );
    else
      fprintf ( 1, '  %8.2f  %14.6g\n', angle, r8_cscd ( angle ) );
    end
  end

  return
end


function Pe = bit_channel_upgrading_procedure(W, z, miu)
N = length(z);
if N == 1
    Pe = 0.5 * sum(min(W));
    disp(['Bit index = ' num2str(z) '  ML detection Bit Error rate = ' num2str(Pe)])
else
    W_up = get_W_up(W);
    W_up = LR_sort(W_up);
    W_up_after_erasure_symbol_merge = erasure_symbol_merge(W_up);
    W_up_after_merge = upgrading_merge(W_up_after_erasure_symbol_merge, miu);
    Pe1 = bit_channel_upgrading_procedure(W_up_after_merge, z(1 : N/2), miu);

    W_down= get_W_down(W);
    W_down = LR_sort(W_down);
    W_down_after_erasure_symbol_merge = erasure_symbol_merge(W_down);
    W_down_after_merge = upgrading_merge(W_down_after_erasure_symbol_merge, miu);
    Pe2 = bit_channel_upgrading_procedure(W_down_after_merge, z(N/2 + 1 : end), miu);

    Pe = [Pe1 Pe2];
end
end

% function Pe = bit_channel_upgrading_procedure(W, z, miu)
% N = length(z);
% m = round(log2(N));
% Pe = zeros(N, 1);
% for k = N - 7 : N - 1
%     char_bin_expansion = dec2bin(k, m);
%     W_tmp = W;
%     for i_level = 1 : m
%         if char_bin_expansion(i_level) == '0'
%             W_up = get_W_up(W_tmp);
%             W_up = LR_sort(W_up);
%             W_up_after_erasure_symbol_merge = erasure_symbol_merge(W_up);
%             W_tmp = upgrading_merge(W_up_after_erasure_symbol_merge, miu);
%         else
%             W_down = get_W_down(W_tmp);
%             W_down = LR_sort(W_down);
%             W_down_after_erasure_symbol_merge = erasure_symbol_merge(W_down);
%             W_tmp = upgrading_merge(W_down_after_erasure_symbol_merge, miu);
%         end
%     end
%     Pe(k + 1) = 0.5 * sum(min(W_tmp));
%     disp(['Bit index = ' num2str(k + 1) ' ML detection Bit Error rate = ' num2str(Pe(k + 1))])
% end
% end


function [l] = qt2l(qt)
% Convert volume from US liquid quarts to liters.
% Chad Greene 2012
l = qt*0.946352946;


classdef TP10 < PROBLEM
% <multi> <real> <large/none> <constrained> <robust>
% Test problem for robust multi-objective optimization
% delta --- 0.05 --- Maximum disturbance degree
% H     ---   50 --- Number of disturbances

%------------------------------- Reference --------------------------------
% A. Gaspar-Cunha, J. Ferreira, and G. Recio, Evolutionary robustness
% analysis for multi-objective optimization: benchmark problems, Structural
% and Multidisciplinary Optimization, 2014, 49: 771-793.
%------------------------------- Copyright --------------------------------
% Copyright (c) 2023 BIMK Group. You are free to use the PlatEMO for
% research purposes. All publications which use this platform or any code
% in the platform should acknowledge the use of "PlatEMO" and reference "Ye
% Tian, Ran Cheng, Xingyi Zhang, and Yaochu Jin, PlatEMO: A MATLAB platform
% for evolutionary multi-objective optimization [educational forum], IEEE
% Computational Intelligence Magazine, 2017, 12(4): 73-87".
%--------------------------------------------------------------------------

    properties
        delta;      % Maximum disturbance degree
        H;          % Number of disturbances
    end
    methods
        %% Default settings of the problem
        function Setting(obj)
            [obj.delta,obj.H] = obj.ParameterSet(0.05,50);
            obj.M = 2;
            obj.D = 3;
            obj.lower    = [0,0,1];
            obj.upper    = [10,10,3];
            obj.encoding = ones(1,obj.D);
        end
        %% Calculate objective values
        function PopObj = CalObj(~,PopDec)
            PopObj(:,1) = PopDec(:,1).*sqrt(16+PopDec(:,3).^2) + PopDec(:,2).*sqrt(1+PopDec(:,3).^2);
            PopObj(:,2) = 20*sqrt(16+PopDec(:,3).^2)./PopDec(:,1)./PopDec(:,3);
        end
        %% Calculate constraint violations
        function PopCon = CalCon(obj,PopDec)
            PopCon(:,1) = 20*sqrt(16+PopDec(:,3).^2) - 100*PopDec(:,1).*PopDec(:,3);
            PopCon(:,2) = 80*sqrt(1+PopDec(:,3).^2) - 100*PopDec(:,2).*PopDec(:,3);
        end
        %% Generate points on the Pareto front
        function R = GetOptimum(obj,N)
            R = [100,100];
        end
        %% Calculate the metric value
        function score = CalMetric(obj,metName,Population)
            switch metName
                case {'Mean_IGD','Mean_HV','Worst_IGD','Worst_HV'}
                    score = feval(metName,Population,obj);
                otherwise
                    score = feval(metName,Population,obj.optimum);
            end
        end
        %% Perturb solutions multiple times
        function PopX = Perturb(obj,PopDec,N)
            if nargin < 3; N = obj.H; end
            Delta = repmat(obj.delta.*(obj.upper-obj.lower),N*size(PopDec,1),1);
            w     = UniformPoint(N,obj.D,'Latin');
            Dec   = 2*Delta.*w(reshape(repmat(1:end,size(PopDec,1),1),1,[]),:) + repmat(PopDec,N,1) - Delta;
            Dec   = obj.CalDec(Dec);
            PopX  = SOLUTION(Dec,obj.CalObj(Dec),obj.CalCon(Dec));
        end
    end
end


function [gal] = ft32gal(ft3)
% Convert volume from cubic feet to US liquid gallons.
% Chad Greene 2012
gal = ft3*7.4805194805;


% EX_STOKES_BIFURCATION_RT_MP: data file for Stokes problem in a pipe with a bifurcation.

% 1) PHYSICAL DATA OF THE PROBLEM
problem_data  = struct ();

% Physical domain, defined as NURBS map given in a text file
problem_data.geo_name = 'geo_bifurcation_mp.txt';

% Type of boundary conditions for each side of the domain
problem_data.drchlt_sides = 1:3;
problem_data.nmnn_sides = [];

% Physical parameters
problem_data.viscosity = @(x, y) ones (size (x));

% Force term
problem_data.f  = @(x, y) zeros ([2, size(x)]);

% Boundary terms
problem_data.h  = @test_stokes_bifurcation_mp_h_drchlt;

% 2) CHOICE OF THE DISCRETIZATION PARAMETERS
method_data = struct ();

method_data.element_name = 'rt';     % Element type for discretization

method_data.degree       = [3 3];  % Degree of the splines
method_data.regularity   = [2 2];  % Regularity of the splines
method_data.nsub         = [5 5];  % Number of subdivisions
method_data.nquad        = [5 5];  % Points for the Gaussian quadrature rule
method_data.Cpen = 10 * (method_data.degree(1)+1);

% 3) CALL TO THE SOLVER
[geometry, msh, space_v, vel, space_p, press] = mp_solve_stokes_div_conforming (problem_data, method_data);

% 4) POST-PROCESSING
% 4.1) EXPORT TO PARAVIEW
output_file  = 'bifurcation_2d_rt_mp_deg3_reg2_sub5';
vtk_pts = {linspace(0, 1, 20), linspace(0, 1, 20)};

fprintf ('results being saved in: %s_vel.pvd and %s_press.pvd\n', output_file, output_file)
sp_to_vtk (vel, space_v, geometry, vtk_pts, sprintf ('%s_vel', output_file), {'velocity', 'divergence'}, {'value', 'divergence'})
sp_to_vtk (press, space_p, geometry, vtk_pts, sprintf ('%s_press', output_file), 'pressure')

%!test
%! problem_data  = struct ();
%! problem_data.geo_name = 'geo_bifurcation_mp.txt';
%! problem_data.drchlt_sides = 1:3;
%! problem_data.nmnn_sides = [];
%! problem_data.viscosity = @(x, y) ones (size (x));
%! problem_data.f  = @(x, y) zeros ([2, size(x)]);
%! problem_data.h  = @test_stokes_bifurcation_mp_h_drchlt;
%! method_data = struct ();
%! method_data.element_name = 'rt';     % Element type for discretization
%! method_data.degree       = [3 3];  % Degree of the splines
%! method_data.regularity   = [2 2];  % Regularity of the splines
%! method_data.nsub         = [5 5];  % Number of subdivisions
%! method_data.nquad        = [5 5];  % Points for the Gaussian quadrature rule
%! method_data.Cpen = 10 * (method_data.degree(1)+1);
%! [geometry, msh, space_v, vel, space_p, press] = mp_solve_stokes_div_conforming (problem_data, method_data);
%! assert (msh.nel, 100)
%! assert (space_v.ndof, 552)
%! assert (space_p.ndof, 256)
%! for iptc = 1:4
%!   div = sp_eval (vel(space_v.gnum{iptc}) .* space_v.dofs_ornt{iptc}', space_v.sp_patch{iptc}, geometry(iptc), [20 20], 'divergence');
%!   assert (max (abs (div(:))) < 1e-12)
%! end


function [qx,qP,qD,xhist] = spm_pf(M,y,U)
% Particle Filtering for dynamic models
% FORMAT [qx,qP,qD,xhist] = spm_pf(M,y)
% M - model specification structure
% y - output or data (N x T)
% U - exogenous input
%
% M(1).x                            % initial states
% M(1).f  = inline(f,'x','v','P')   % state equation
% M(1).g  = inline(g,'x','v','P')   % observer equation
% M(1).pE                           % parameters
% M(1).V                            % observation noise precision
%
% M(2).v                            % initial process noise
% M(2).V                            % process noise precision
%
% qx - conditional expectation of states
% qP - {1 x T} conditional covariance of states
% qD - full sample
%__________________________________________________________________________
% See notes at the end of this script for details and a demo.  This routine
% is based on:
%
% var der Merwe R, Doucet A, de Freitas N and Wan E (2000). The
% unscented particle filter.  Technical Report CUED/F-INFENG/TR 380
%__________________________________________________________________________
% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging

% Karl Friston
% $Id: spm_pf.m 1143 2008-02-07 19:33:33Z spm $

% check model specification
%--------------------------------------------------------------------------
M  = spm_DEM_M_set(M);
dt = M(1).E.dt;
if length(M) ~=2
    errordlg('spm_pf requires a two-level model')
    return
end

% INITIALISATION:
%==========================================================================
T    = length(y);                          % number of time points
n    = M(2).l;                             % number of innovations
N    = 200;                                % number of particles.

% precision of measurement noise
%--------------------------------------------------------------------------
R    = M(1).V;
for i = 1:length(M(1).Q)
    R = R + M(1).Q{i}*exp(M(1).h(i));
end
P  = M(1).pE;                              % parameters
Q  = M(2).V.^-.5;                          % root covariance of innovations
v  = kron(ones(1,N),M(2).v);               % innovations
x  = kron(ones(1,N),M(1).x);               % hidden states
v  = v + 128*Q*randn(size(v));

% inputs
%--------------------------------------------------------------------------
if nargin < 3
    U = sparse(n,T);
end

for t = 1:T

    % PREDICTION STEP: with the (8x) transition prior as proposal
    %----------------------------------------------------------------------
    for i = 1:N
        v(:,i)     = 8*Q*randn(n,1) + U(:,t);
        f          = M(1).f(x(:,i),v(:,i),P);
        dfdx       = spm_diff(M(1).f,x(:,i),v(:,i),P,1);
        xPred(:,i) = x(:,i) + spm_dx(dfdx,f,dt);
    end

    % EVALUATE IMPORTANCE WEIGHTS: and normalise
    %----------------------------------------------------------------------
    for i = 1:N
        yPred  = M(1).g(xPred(:,i),v(:,i),P);
        ePred  = yPred - y(:,t);
        w(i)   = ePred'*R*ePred;
    end
    w   = w - min(w);
    w   = exp(-w/2);
    w   = w/sum(w);

    % SELECTION STEP: multinomial resampling.
    %----------------------------------------------------------------------
    x   = xPred(:,multinomial(1:N,w));

    % report and record moments
    %----------------------------------------------------------------------
    qx(:,t)  = mean(x,2);
    qP{t}    = cov(x');
    qX(:,t)  = x(:);
    fprintf('PF: time-step = %i : %i\n',t,T);
end

% sample density
%==========================================================================
if nargout > 3
    xhist = linspace(min(qX(:)),max(qX(:)),32);
    for i = 1:T
        q = hist(qX(:,i),xhist);
        qD(:,i) = q(:);
    end
end

return

function I = multinomial(inIndex,q);
%==========================================================================
% PURPOSE : Performs the resampling stage of the SIR
%           in order(number of samples) steps.
% INPUTS  : - inIndex = Input particle indices.
%           - q       = Normalised importance ratios.
% OUTPUTS : - I = Resampled indices.
% AUTHORS : Arnaud Doucet and Nando de Freitas

% MULTINOMIAL SAMPLING:
% generate S ordered random variables uniformly distributed in [0,1]
% high speed Niclas Bergman Procedure
%--------------------------------------------------------------------------
q        = q(:);
S        = length(q);  % S = Number of particles.
N_babies = zeros(1,S);
cumDist  = cumsum(q');

u = fliplr(cumprod(rand(1,S).^(1./(S:-1:1))));
j = 1;
for i = 1:S
    while (u(1,i) > cumDist(1,j))
        j = j + 1;
    end
    N_babies(1,j) = N_babies(1,j) + 1;
end;

% COPY RESAMPLED TRAJECTORIES:
%--------------------------------------------------------------------------
index = 1;
for i = 1:S
    if (N_babies(1,i)>0)
        for j=index:index+N_babies(1,i)-1
            I(j) = inIndex(i);
        end;
    end;
    index = index + N_babies(1,i);
end

return
%==========================================================================

% notes and demo:
%==========================================================================
% The code below generates a nonlinear, non-Gaussian problem (S) comprising
% a model S.M and data S.Y (c.f. van der Merwe et al 2000))
%
% The model is   f(x) = dxdt
%                     = 1 + sin(0.04*pi*t) - log(2)*x + n
%                y    = g(x)
%                     = (x.^2)/5  : if t < 30
%                       -2 + x/2  : otherwise
% i.e. the output nonlinearity becomes linear after 30 time steps.  In this
% implementation time is modelled as an auxiliary state variable.  n is
% the process noise, which is modelled as a log-normal variate.  e is
% Gaussian observation noise.

% model specification
%--------------------------------------------------------------------------
f       = '[1; (1 + sin(P(2)*pi*x(1)) - P(1)*x(2) + exp(v))]';
g       = '(x(1) > 30)*(-2 + x(2)/2) + ~(x(1) > 30)*(x(2).^2)/5';
M(1).x  = [1; 1];                  % initial states
M(1).f  = inline(f,'x','v','P');   % state equation
M(1).g  = inline(g,'x','v','P');   % observer equation
M(1).pE = [log(2) 0.04];           % parameters
M(1).V  = exp(4);                  % observation noise precision

M(2).v  = 0;                       % initial process log(noise)
M(2).V  = 2.4;                     % process log(noise) precision

% generate data (output)
%--------------------------------------------------------------------------
T       = 60;                      % number of time points
S       = spm_DEM_generate(M,T);

% Particle filtering
%--------------------------------------------------------------------------
pf_x    = spm_pf(M,S.Y);

% plot results
%--------------------------------------------------------------------------
x       = S.pU.x{1};
plot([1:T],x(2,:),[1:T],pf_x(2,:))
legend({'true','PF'})


function [i,j] = xy2ind(ebsd,x,y)
% convert x,y coordinates into indeces of ebsd
%
% Syntax
%
%   ind = xy2ind(ebsd,x,y)
%   ebsd(ind)
%
%   [i,j] = ind = xy2ind(ebsd,x,y)
%   ebsd(i,j)
%
% Input
%  ebsd - @EBSDsquare
%  x,y  - spatial coordinates
%
% Output
%  ind  - index to @EBSDsquare
%  i,j  - indeces to @EBSDsquare
%

if nargin == 2
  y = x(:,2);
  x = x(:,1);
end

i = 1+round((y - ebsd.prop.y(1))./ebsd.dy);
j = 1+round((x - ebsd.prop.x(1))./ebsd.dx);

if nargout == 1, i = sub2ind(size(ebsd),i,j); end


function [fx,dfdx,dfdp] = f_DCMwHRFext(Xt,Theta,ut,inF) %
% DCM for fMRI evolution function (including Balloon model)
% function [fx,dF_dX,dF_dTheta] = f_DCMwHRF(Xt,Theta,ut,inF)
% This function evaluates the evolution function DCM for fMRI, including
% the Balloon HRF model.

ut = ut(inF.confounds.indu);
nx = length(Xt);
nr = length(inF.r);

%- hidden states evolution
xn = Xt(inF.n5);
if ~isfield(inF,'fast')
    [fxh,dfdxh,dfdph] = f_HRF3(Xt(1:nx-nr),Theta,xn,inF);
else
    fxh = zeros(nx-nr,1);
    dfdxh = zeros(nx-nr,nx-nr);
    dfdph = zeros(length(Theta),nx-nr);
end

[fxn,dfdxn,dfdpn] = f_dcm4fmri(Xt(inF.n5),Theta,ut,inF);
[fxr,dfdxr,dfdpr] = f_dcm_extension(Xt([inF.n5 inF.r]),Theta,ut,inF);

%== Reshape flow field and gradients
%- flow
fx = zeros(nx,1);
fx(1:nx-nr) = fxh ;
fx(inF.n5) = fxn ;
fx(inF.r) = fxr ;

%- jacobian
dfdx = zeros(nx,nx);
dfdx(1:nx-nr,1:nx-nr) = dfdxh ;
dfdx(inF.n5,inF.n5) = dfdxn;
dfdx([inF.n5 inF.r],inF.r) = dfdxr ;

%- wrt parameters
dfdp = zeros(length(Theta),nx);
dfdp(:,1:nx-nr) = dfdph ;
dfdp(:,inF.n5) = dfdp(:,inF.n5)+dfdpn ;
dfdp(:,inF.r) = dfdpr ;

end


function varargout = coeffs2( f, m, n )
%COEFFS2   Double Fourier coefficients of a SPHEREFUN.
%
%   X = COEFFS2( F ) returns the 2D Fourier modes of the spherefun, viewed
%   as a doubly periodic function.
%
%   [C, D, R] = COEFFS2( F ) returns a low rank approximation to the 2D
%   Fourier modes.
%
%   X = COEFFS2(F, M, N) returns bivariate coefficients with N Fourier
%   modes in latitude and M Fourier modes in longitude.

% Copyright 2017 by The University of Oxford and The Chebfun Developers.
% See http://www.chebfun.org/ for Chebfun information.

% empty check
if isempty(f)
    varargout = {};
    return
end

% Calculate the CDR decomposition:
[C, D, R] = cdr(f);

if ( nargin == 1 )
    % Find the  coefficients of each slice:
    U = C.coeffs;
    R = R.coeffs;
else
    if ( nargin == 2 )
        n = m;
    end
    % Find the coefficients of each slice:
    U = trigtech.alias(C.coeffs, n);
    R = trigtech.alias(R.coeffs, m);
end

% Prepare the output. Keep in low rank form if nargin > 1.
if ( nargout <= 1 )
    varargout = { U*D*R.' };
elseif ( nargout <= 3 )
    varargout = { U, D, R };
else
    error('SPHEREFUN:COEFFS:NARGOUT',...
            'Too many output arguments')
end

end


function data = imgSTD(img)
    data = struct('intensity',[],'red',[],'green',[],'blue',[],'mean_range',[],'std_range',[],'mean_std',[],'std_std',[],'mean_entropy',[]);
    dim = size(img,1) / 4;
    for j = 1:4
        xend = j*dim;
        xstart = xend - 3;
        for m = 1:4

            intensity = [];
            red = [];
            green = [];
            blue = [];
            mean_range = [];
            std_range = [];
            mean_std = [];
            std_std = [];
            mean_entropy = [];

            yend = m*dim;
            ystart = yend - dim + 1;
            for k = xstart:xend
                for l = ystart:yend
                    intensity = [intensity img{k,l}.intensity];
                    red = [red img{k,l}.red];
                    green = [green img{k,l}.green];
                    blue = [blue img{k,l}.blue];
                    mean_range = [mean_range img{k,l}.mean_range];
                    std_range = [std_range img{k,l}.std_range];
                    mean_std = [mean_std img{k,l}.mean_std];
                    std_std = [std_std img{k,l}.std_std];
                    mean_entropy = [mean_entropy img{k,l}.mean_entropy];
                end
            end
            data.intensity = [data.intensity std(intensity)];
            data.red = [data.red std(red)];
            data.green = [data.green std(green)];
            data.blue = [data.blue std(blue)];
            data.mean_range = [data.mean_range std(mean_range)];
            data.std_range = [data.std_range std(std_range)];
            data.mean_std = [data.mean_std std(mean_std)];
            data.std_std = [data.std_std std(std_std)];
            data.mean_entropy = [data.mean_entropy std(mean_entropy)];
        end
    end
end