function check_plot(fun,xparam,SE_vec,options_,M_,estim_params_,Bounds,bayestopt_,varargin)
%function check_plot(fun,xparam,SE_vec,options_,M_,estim_params_,Bounds,bayestopt_,varargin)
% Checks the estimated local minimum of the moment's distance objective


% Copyright (C) 2020-2021 Dynare Team
%
% This file is part of Dynare.
%
% Dynare 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 3 of the License, or
% (at your option) any later version.
%
% Dynare 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 Dynare.  If not, see <https://www.gnu.org/licenses/>.

TeX = options_.TeX;
if ~isempty(SE_vec)
    [ s_min, k ] = min(SE_vec);
end

fval = feval(fun,xparam,varargin{:});

if ~isempty(SE_vec)
    skipline()
    disp('LOCAL MINIMUM CHECK')
    skipline()
    fprintf('Fval obtained by the minimization routine: %f', fval);
    skipline()
    if s_min<eps
        fprintf('Most negative variance %f for parameter %d (%s = %f)', s_min, k , bayestopt_.name{k}, xparam(k))
    end
end

[nbplt,nr,nc,lr,lc,nstar] = pltorg(length(xparam));

if ~exist([M_.dname filesep 'graphs'],'dir')
    mkdir(M_.dname,'graphs');
end
if TeX && any(strcmp('eps',cellstr(options_.graph_format)))
    fidTeX = fopen([M_.dname, '/graphs/', M_.fname '_MoMCheckPlots.tex'],'w');
    fprintf(fidTeX,'%% TeX eps-loader file generated by mom.check_plot.m (Dynare).\n');
    fprintf(fidTeX,['%% ' datestr(now,0) '\n']);
    fprintf(fidTeX,' \n');
end

ll = options_.mode_check.neighbourhood_size;
if isinf(ll)
    options_.mode_check.symmetric_plots = false;
end

mcheck = struct('cross',struct(),'emin',struct());

for plt = 1:nbplt
    if TeX
        NAMES = [];
        TeXNAMES = [];
    end
    hh = dyn_figure(options_.nodisplay,'Name','Minimum check plots');
    for k=1:min(nstar,length(xparam)-(plt-1)*nstar)
        subplot(nr,nc,k)
        kk = (plt-1)*nstar+k;
        [name,texname] = get_the_name(kk,TeX,M_,estim_params_,options_);
        xx = xparam;
        if xparam(kk)~=0 || ~isinf(Bounds.lb(kk)) || ~isinf(Bounds.lb(kk))
            l1 = max(Bounds.lb(kk),(1-sign(xparam(kk))*ll)*xparam(kk)); m1 = 0; %lower bound
            l2 = min(Bounds.ub(kk),(1+sign(xparam(kk))*ll)*xparam(kk)); %upper bound
        else
            %size info for 0 parameter is missing, use prior standard
            %deviation
            upper_bound=Bounds.lb(kk);
            if isinf(upper_bound)
                upper_bound=-1e-6*options_.huge_number;
            end
            lower_bound=Bounds.ub(kk);
            if isinf(lower_bound)
                lower_bound=-1e-6*options_.huge_number;
            end
            l1 = max(lower_bound,-bayestopt_.p2(kk)); m1 = 0; %lower bound
            l2 = min(upper_bound,bayestopt_.p2(kk)); %upper bound
        end
        binding_lower_bound=0;
        binding_upper_bound=0;
        if isequal(xparam(kk),Bounds.lb(kk))
            binding_lower_bound=1;
            bound_value=Bounds.lb(kk);
        elseif isequal(xparam(kk),Bounds.ub(kk))
            binding_upper_bound=1;
            bound_value=Bounds.ub(kk);
        end
        if options_.mode_check.symmetric_plots && ~binding_lower_bound && ~binding_upper_bound
            if l2<(1+ll)*xparam(kk) %test whether upper bound is too small due to prior binding
                l1 = xparam(kk) - (l2-xparam(kk)); %adjust lower bound to become closer
                m1 = 1;
            end
            if ~m1 && (l1>(1-ll)*xparam(kk)) && (xparam(kk)+(xparam(kk)-l1)<Bounds.ub(kk)) % if lower bound was truncated and using difference from lower bound does not violate upper bound
                l2 = xparam(kk) + (xparam(kk)-l1); %set upper bound to same distance as lower bound
            end
        end
        z1 = l1:((xparam(kk)-l1)/(options_.mode_check.number_of_points/2)):xparam(kk);
        z2 = xparam(kk):((l2-xparam(kk))/(options_.mode_check.number_of_points/2)):l2;
        z  = union(z1,z2);
        if options_.mom.penalized_estimator
            y = zeros(length(z),2);
            dy=(xx-bayestopt_.p1)'/diag(bayestopt_.p2.^2)*(xx-bayestopt_.p1);
        else
            y = zeros(length(z),1);            
        end
        for i=1:length(z)
            xx(kk) = z(i);
            [fval, info, exit_flag] = feval(fun,xx,varargin{:});
            if exit_flag
                y(i,1) = fval;
            else
                y(i,1) = NaN;
                if options_.debug
                    fprintf('mom.check_plot:: could not solve model for parameter %s at value %4.3f, error code: %u\n',name,z(i),info(1))
                end
            end
            if options_.mom.penalized_estimator
                prior=(xx-bayestopt_.p1)'/diag(bayestopt_.p2.^2)*(xx-bayestopt_.p1);
                y(i,2)  = (y(i,1)+prior-dy);
            end
        end
        mcheck.cross = setfield(mcheck.cross, name, [transpose(z), y]);
        mcheck.emin = setfield(mcheck.emin, name, xparam(kk));
        fighandle=plot(z,y);
        hold on
        yl=get(gca,'ylim');
        plot( [xparam(kk) xparam(kk)], yl, 'c', 'LineWidth', 1)
        NaN_index = find(isnan(y(:,1)));
        zNaN = z(NaN_index);
        yNaN = yl(1)*ones(size(NaN_index));
        plot(zNaN,yNaN,'o','MarkerEdgeColor','r','MarkerFaceColor','r','MarkerSize',6);
        if TeX
            title(texname,'interpreter','latex')
        else
            title(name,'interpreter','none')
        end

        axis tight
        if binding_lower_bound || binding_upper_bound
            xl=get(gca,'xlim');
            plot( [bound_value bound_value], yl, 'r--', 'LineWidth', 1)
            xlim([xl(1)-0.5*binding_lower_bound*(xl(2)-xl(1)) xl(2)+0.5*binding_upper_bound*(xl(2)-xl(1))])
        end
        hold off
        drawnow
    end
    if options_.mom.penalized_estimator
        if isoctave
            axes('outerposition',[0.3 0.93 0.42 0.07],'box','on'),
        else
            axes('position',[0.3 0.01 0.42 0.05],'box','on'),
        end
        line_color=get(fighandle,'color');
        plot([0.48 0.68],[0.5 0.5],'color',line_color{2})
        hold on, plot([0.04 0.24],[0.5 0.5],'color',line_color{1})
        set(gca,'xlim',[0 1],'ylim',[0 1],'xtick',[],'ytick',[])
        text(0.25,0.5,'log-post')
        text(0.69,0.5,'log-lik kernel')
    end
    dyn_saveas(hh,[M_.dname, '/graphs/', M_.fname '_MoMCheckPlots' int2str(plt) ],options_.nodisplay,options_.graph_format);
    if TeX && any(strcmp('eps',cellstr(options_.graph_format)))
        % TeX eps loader file
        fprintf(fidTeX,'\\begin{figure}[H]\n');
        fprintf(fidTeX,'\\centering \n');
        fprintf(fidTeX,'\\includegraphics[width=%2.2f\\textwidth]{%s_MoMCheckPlots%s}\n',options_.figures.textwidth*min(k/nc,1),[M_.dname, '/graphs/',M_.fname],int2str(plt));
        fprintf(fidTeX,'\\caption{Method of Moments check plots.}');
        fprintf(fidTeX,'\\label{Fig:MoMCheckPlots:%s}\n',int2str(plt));
        fprintf(fidTeX,'\\end{figure}\n');
        fprintf(fidTeX,' \n');
    end
end
if TeX && any(strcmp('eps',cellstr(options_.graph_format)))
    fclose(fidTeX);
end

save([M_.dname filesep 'graphs' filesep M_.fname '_MoMCheckPlots_data.mat'],'mcheck');
