Skip to content
Snippets Groups Projects
Select Git revision
  • 1f8c182900ee5d0bcb38a56af93d9c7c2421a13c
  • master default protected
  • noGUIDE
  • 4.5
4 results

gui_determ_simulation.m

Blame
  • Forked from Dynare / matlab-gui
    11 commits behind the upstream repository.
    gui_determ_simulation.m 24.24 KiB
    function gui_determ_simulation(tabId)
    % function gui_determ_simulation(tabId)
    % interface for the DYNARE simul command (deterministic simulations)
    %
    % INPUTS
    %   tabId:  GUI tab element which displays deterministic simulation interface
    %
    % OUTPUTS
    %   none
    %
    % SPECIAL REQUIREMENTS
    %   none
    
    % Copyright (C) 2003-2019 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 <http://www.gnu.org/licenses/>.
    
    global model_settings project_info options_ M_ oo_ dynare_gui_
    
    bg_color = char(getappdata(0,'bg_color'));
    special_color = char(getappdata(0,'special_color'));
    
    handles = [];
    gui_size = gui_tools.get_gui_elements_size(tabId);
    
    % --- PANELS -------------------------------------
    handles.uipanelShocks = uipanel( ...
        'Parent', tabId, ...
        'Tag', 'uipanelShocks', ...
        'BackgroundColor', special_color, ...
        'Units', 'normalized', ...
        'Position', [0.01 0.18 0.6 0.73], ...
        'Title', '', ...
        'BorderType', 'none');
    
    uipanelShocks_CreateFcn;
    
    handles.uipanelVars = uipanel( ...
        'Parent', tabId, ...
        'Tag', 'uipanelVars', ...
        'UserData', zeros(1,0), ...
        'BackgroundColor', special_color, ...
        'Units', 'normalized', ...
        'Position', [0.62 0.18 0.37 0.70], ...
        'Title', '', ...
        'BorderType', 'none');
    
    handles = gui_tabs.create_endo_vars(handles, 'perfect_foresight');
    
    handles.uipanelComm = uipanel( ...
        'Parent', tabId, ...
        'Tag', 'uipanelCommOptions', ...
        'UserData', zeros(1,0), ...
        'BackgroundColor', bg_color, ...
        'Units', 'normalized', ...
        'Position', [0.01 0.09 0.98 0.09], ...
        'Title', 'Current command options:');
    
    % --- STATIC TEXT -------------------------------------
    uicontrol( ...
        'Parent', tabId, ...
        'Style', 'text', ...
        'BackgroundColor', bg_color, ...
        'Units', 'normalized', ...
        'Position', [0.62 0.92 0.48 0.05], ...
        'FontWeight', 'bold', ...
        'String', 'Select variables for which to plot simulated trajectory:', ...
        'HorizontalAlignment', 'left');
    
    uicontrol( ...
        'Parent', tabId, ...
        'Style', 'text', ...
        'BackgroundColor', bg_color, ...
        'Units', 'normalized', ...
        'Position', [0.01 0.92 0.48 0.05], ...
        'FontWeight', 'bold', ...
        'String', 'Define shocks on exogenous variables:', ...
        'HorizontalAlignment', 'left');
    
    if ~isfield(model_settings, 'simul')
        model_settings.simul = struct();
    end
    comm_str = gui_tools.command_string('simul', model_settings.simul);
    
    handles.simul = uicontrol( ...
        'Parent', handles.uipanelComm, ...
        'Tag', 'simul', ...
        'Style', 'text',  'BackgroundColor', bg_color, ...
        'Units', 'normalized', 'Position', [0.01 0.01 0.98 0.98], ...
        'FontAngle', 'italic', ...
        'String', comm_str, ...
        'TooltipString', comm_str, ...
        'HorizontalAlignment', 'left');
    
    % --- Radio Buttons -------------------------------------
    handles.buttongroup = uibuttongroup( ...
        'Parent', tabId, ...
        'Position', [0.62 0.88 0.36 0.05], ...
        'Units', 'normalized', ...
        'SelectionChangedFcn', {@init_val, handles});
    
    uicontrol(handles.buttongroup, ...
        'Style', 'text', ...
        'Units', 'normalized', ...
        'Position', [0 -.2 1 1], ...
        'FontWeight', 'bold', ...
        'String', 'Initial value: ', ...
        'HorizontalAlignment', 'left');
    
    uicontrol(handles.buttongroup, ...
        'Style', 'radiobutton', ...
        'String', 'zero', ...
        'Units', 'normalized', ...
        'Position', [0.2 0 1 1]);
                  
    uicontrol(handles.buttongroup, ...
        'Style', 'radiobutton', ...
        'String', 'steady state', ...
        'Units', 'normalized', ...
        'Position', [0.3 0 1 1]);
    
    uicontrol(handles.buttongroup, ...
        'Style', 'radiobutton', ...
        'String', 'smoother', ...
        'Units', 'normalized', ...
        'Position', [0.5 0 1 1]);
    
    % --- PUSHBUTTONS -------------------------------------
    handles.pushbuttonSimulation = uicontrol( ...
        'Parent', tabId, ...
        'Tag', 'pushbuttonSimulation', ...
        'Style', 'pushbutton', ...
        'Units','normalized','Position',[gui_size.space gui_size.bottom gui_size.button_width_small gui_size.button_height], ...
        'String', 'Run Simulation', ...
        'Callback', @pushbuttonSimulation_Callback);
    
    handles.pushbuttonReset = uicontrol( ...
        'Parent', tabId, ...
        'Tag', 'pushbuttonReset', ...
        'Style', 'pushbutton', ...
        'Units','normalized','Position',[gui_size.space*2+gui_size.button_width_small gui_size.bottom gui_size.button_width_small gui_size.button_height], ...
        'String', 'Reset', ...
        'Callback', @pushbuttonReset_Callback);
    
    handles.pushbuttonClose = uicontrol( ...
        'Parent', tabId, ...
        'Tag', 'pushbuttonReset', ...
        'Style', 'pushbutton', ...
        'Units','normalized','Position',[gui_size.space*3+gui_size.button_width_small*2 gui_size.bottom gui_size.button_width_small gui_size.button_height], ...
        'String', 'Close this tab', ...
        'Callback',{@close_tab,tabId});
    
    handles.pushbuttonCloseAll = uicontrol( ...
        'Parent', tabId, ...
        'Tag', 'pushbuttonSimulation', ...
        'Style', 'pushbutton', ...
        'Units','normalized','Position',[gui_size.space*4+gui_size.button_width_small*3 gui_size.bottom gui_size.button_width_small gui_size.button_height], ...
        'String', 'Close all output figures', ...
        'Enable', 'on', ...
        'Callback', @pushbuttonCloseAll_Callback);
    
    handles.pushbuttonCommandDefinition = uicontrol( ...
        'Parent', tabId, ...
        'Tag', 'pushbuttonCommandDefinition', ...
        'Style', 'pushbutton', ...
        'Units','normalized','Position',[1-gui_size.space-gui_size.button_width_small gui_size.bottom gui_size.button_width_small gui_size.button_height], ...
        'String', 'Define command options ...', ...
        'Callback', @pushbuttonCommandDefinition_Callback);
    
        function uipanelShocks_CreateFcn()
            handles.shocksTabGroup = uitabgroup(handles.uipanelShocks, 'Position', [0 0 1 1]);
            handles.shocks_tab = uitab(handles.shocksTabGroup, 'Title', 'Shocks' , 'UserData', 1);
            handles.shocks_panel = uipanel('Parent', handles.shocks_tab, 'BackgroundColor', 'white', 'BorderType', 'none');
            uicontrol( ...
                'Parent', handles.shocks_panel, ...
                'Style', 'text', 'BackgroundColor', special_color, ...
                'Units', 'normalized', 'Position', [0.02 0.85 0.96 0.1], ...
                'FontWeight', 'bold', ...
                'String', 'Select exogenous variable for which you want to define temporary changes in the value.', ...
                'HorizontalAlignment', 'left');
    
            shocks = model_settings.shocks(:, 3);
            list_shocks = uicontrol('Parent', handles.shocks_panel, ...
                'Style', 'popupmenu', ...
                'Units', 'normalized', ...
                'Position', [0.02 0.77 0.7 0.06], ...
                'String', ['Select varexo...'; shocks], ...
                'Callback', @pushbuttonValueChanged_Callback);
    
            handles.pushbuttonAddValue = uicontrol('Parent', handles.shocks_panel, ...
                'Style', 'pushbutton', ...
                'Units', 'normalized', ...
                'Position', [0.73 0.77 0.25 0.06], ...
                'String', 'Add shock ...', ...
                'Enable', 'Off', ...
                'Callback', @pushbuttonAddShock_Callback);
    
            handles.shocks_table = uitable(handles.shocks_panel, ...
                'Data', get_det_shocks(), ...
                'Units', 'normalized', ...
                'Position', [0.02 0.10 0.96 0.6], ...
                'ColumnName', {'Shock', 'Start', 'End', 'Value', 'Expect date', 'Unanticipated', 'Permanent', 'Remove'}, ...
                'ColumnFormat', {'char', 'numeric', 'numeric', 'char', 'numeric', 'logical', 'logical', 'logical' }, ...
                'ColumnEditable', [false, true, true, true, true, true, true, true], ...
                'RowName', [], ...
                'CellEditCallback', @savedata);
    
            handles.pushbuttonRemoveValue = uicontrol('Parent', handles.shocks_panel, ...
                'Style', 'pushbutton', ...
                'Units', 'normalized', ...
                'Position', [0.73 0.03 0.25 0.06], ...
                'String', 'Remove all selected', ...
                'Enable', 'Off', ...
                'Callback', @pushbuttonRemoveValues_Callback);
    
            function pushbuttonValueChanged_Callback(hObject, ~)
                if get(hObject, 'Value') > 1
                    handles.pushbuttonAddValue.Enable = 'On';
                else
                    handles.pushbuttonAddValue.Enable = 'Off';
                end
            end
    
            function pushbuttonAddShock_Callback(~, ~)
                value = get(list_shocks, 'Value');
                if value > 1
                    handles.shocks_table.Data{end+1, 1} = shocks{value-1};
                    handles.shocks_table.Data{end, 2} = 1;
                    handles.shocks_table.Data{end, 3} = '';
                    handles.shocks_table.Data{end, 4} = '';
                    handles.shocks_table.Data{end, 5} = '';
                    handles.shocks_table.Data{end, 6} = false;
                    handles.shocks_table.Data{end, 7} = false;
                    handles.shocks_table.Data{end, 8} = false;
                end
            end
    
            function pushbuttonRemoveValues_Callback(~, ~)
                handles.shocks_table.Data = ...
                    handles.shocks_table.Data(not([handles.shocks_table.Data{:, 8}]), :);
            end
    
            function savedata(~, callbackdata)
                if callbackdata.Indices(2) == 3
                    if isnan(callbackdata.NewData)
                        handles.shocks_table.Data{callbackdata.Indices(1), callbackdata.Indices(2)} = '';
                    elseif ischar(callbackdata.NewData)
                        handles.shocks_table.Data{callbackdata.Indices(1), callbackdata.Indices(2)} ...
                            = str2double(callbackdata.NewData);
                    end
                elseif callbackdata.Indices(2) == 4
                    if ~isempty(callbackdata.NewData) && (any(isnan(callbackdata.NewData)) || any(isinf(callbackdata.NewData)))
                        handles.shocks_table.Data{callbackdata.Indices(1), callbackdata.Indices(2)} = '';
                    end
                elseif callbackdata.Indices(2) == 5
                    if isnan(callbackdata.NewData)
                        handles.shocks_table.Data{callbackdata.Indices(1), callbackdata.Indices(2)} = '';
                    elseif ischar(callbackdata.NewData)
                        handles.shocks_table.Data{callbackdata.Indices(1), callbackdata.Indices(2)} ...
                            = str2double(callbackdata.NewData);
                    end
                elseif callbackdata.Indices(2) == 8
                    if any([handles.shocks_table.Data{:,8}])
                        handles.pushbuttonRemoveValue.Enable = 'On';
                    else
                        handles.pushbuttonRemoveValue.Enable = 'Off';
                    end
                end
            end
        end
    
        function data = get_det_shocks()
            data = cell(0, 8);
            for i = 1:length(model_settings.jsonmodel.statements)
                switch model_settings.jsonmodel.statements{i}.statementName
    %                 case 'initval'
    %                     for j = 1:length(model_settings.jsonmodel.statements{i}.vals)
    %                         if any(strcmp(M_.exo_names, model_settings.jsonmodel.statements{i}.vals{j}.name))
    %                             data{end+1, 1} = model_settings.jsonmodel.statements{i}.vals{j}.name;
    %                             data{end, 2} = 0;
    %                             data{end, 3} = '';
    %                             data{end, 4} = num2str(model_settings.jsonmodel.statements{i}.vals{j}.value);
    %                             data{end, 5} = '';
    %                             data{end, 6} = false;
    %                             data{end, 7} = false;
    %                             data{end, 8} = false;
    %                         end
    %                     end
                    case 'endval'
                        for j = 1:length(model_settings.jsonmodel.statements{i}.vals)
                            if any(strcmp(M_.exo_names, model_settings.jsonmodel.statements{i}.vals{j}.name))
                                data{end+1, 1} = model_settings.jsonmodel.statements{i}.vals{j}.name;
                                data{end, 2} = 1;
                                data{end, 3} = '';
                                data{end, 4} = num2str(model_settings.jsonmodel.statements{i}.vals{j}.value);
                                data{end, 5} = '';
                                data{end, 6} = false;
                                data{end, 7} = true;
                                data{end, 8} = false;
                            end
                        end
                    case 'shocks'
                        for j = 1:length(model_settings.jsonmodel.statements{i}.deterministic_shocks)
                            if any(strcmp(M_.exo_names, model_settings.jsonmodel.statements{i}.deterministic_shocks{j}.var))
                                name = model_settings.jsonmodel.statements{i}.deterministic_shocks{j}.var;
                                for k = 1:length(model_settings.jsonmodel.statements{i}.deterministic_shocks{j}.values)
                                    value = model_settings.jsonmodel.statements{i}.deterministic_shocks{j}.values{k}.value;
                                    data{end+1, 1} = name;
                                    data{end, 2} = model_settings.jsonmodel.statements{i}.deterministic_shocks{j}.values{k}.period1;
                                    if model_settings.jsonmodel.statements{i}.deterministic_shocks{j}.values{k}.period1 ...
                                            ~= model_settings.jsonmodel.statements{i}.deterministic_shocks{j}.values{k}.period2
                                        data{end, 3} = model_settings.jsonmodel.statements{i}.deterministic_shocks{j}.values{k}.period2;
                                    else
                                        data{end, 3} = model_settings.jsonmodel.statements{i}.deterministic_shocks{j}.values{k}.period1;
                                    end
                                    data{end, 4} = value;
                                    data{end, 5} = '';
                                    data{end, 6} = false;
                                    data{end, 7} = false;
                                    data{end, 8} = false;
                                end
                            end
                        end
                end
            end
        end
    
        function pushbuttonSimulation_Callback(~, ~)
            old_oo = oo_;
            try
                backup = gui_auxiliary.backup_options(options_);
                options_ = default_option_values(M_);
                options_ = gui_auxiliary.add_backup_to_options(options_, backup);
                if ~isempty(model_settings.simul)
                    names = fieldnames(model_settings.simul);
                    for ii = 1:size(names, 1)
                        if isempty(model_settings.simul.(names{ii}))
                            gui_auxiliary.set_command_option(names{ii}, 1, 'check_option');
                        else
                            gui_auxiliary.set_command_option(names{ii}, model_settings.simul.(names{ii}));
                        end
                    end
                end
    
                if options_.periods == 0
                    gui_tools.show_error('You must set the `periods` option for simul');
                    return
                end
                
                % set initval
                gui_tools.project_log_entry('Doing deterministic simulation','...');
                [jObj, guiObj] = gui_tools.create_animated_screen('Running deterministic simulation. Please wait...', tabId);
    
                gui.perfect_foresight.run(convert_gui_info_to_json());
    
                if any([handles.endoTable.Data{:,1}])
                    vars = handles.endoTable.Data([handles.endoTable.Data{:,1}], 2);
                else
                    vars = handles.endoTable.Data(:, 2);
                end
                for ii = 1:length(vars)
                    rplot(vars(ii));
                end
    
                jObj.stop;
                jObj.setBusyText('Done');
                project_info.modified = true;
                project_info.deterministic_simulation_run = true;
                gui_set_menus(true);
            catch ME
                jObj.stop;
                jObj.setBusyText('Done with errors');
                gui_tools.show_error('Error in execution of simul command', ME, 'extended');
                oo_ = old_oo;
            end
            delete(guiObj);
        end
    
        function pushbuttonReset_Callback(~, ~)
            handles.endoTable.Data(:, 1) = {false};
            model_settings.simul = struct();
            comm_str = gui_tools.command_string('simul', model_settings.simul);
            handles.simul.String = comm_str;
            handles.simul.TooltipString = comm_str;
        end
    
        function pushbuttonCommandDefinition_Callback(~, ~)
            h = gui_define_comm_options(dynare_gui_.simul,'simul');
            uiwait(h);
            try
                new_comm = getappdata(0, 'simul');
                model_settings.simul = new_comm;
                comm_str = gui_tools.command_string('simul', new_comm);
                
                handles.simul.String = comm_str;
                gui_tools.project_log_entry('Defined command simul', comm_str);
            catch ME
                gui_tools.show_error('Error defining simul command', ME, 'basic');
            end
        end
    
        function pushbuttonCloseAll_Callback(~, ~)
            gui_tools.close_all_figures();
        end
    
        function close_tab(~, ~, hTab)
            gui_tabs.delete_tab(hTab);
        end
    
        function json = convert_gui_info_to_json()
            data = handles.shocks_table.Data;
            json = struct('periods', options_.periods);
            if ~all(isint([data{:,2}]))
                throw(MException('convert_gui_info_to_json', 'start period must be an integer'));
            end
    
            if ~all(cellfun(@isint,data(:,3)) | cellfun(@isempty,data(:,3)))
                throw(MException('convert_gui_info_to_json', 'end period must be empty or an integer'));
            end
    
            expected_shock_dates = ~cellfun(@isempty, data(:,5));
            if ~all(isint([data{expected_shock_dates, 5}]))
                throw(MException('convert_gui_info_to_json', 'expected dates must be integers'));
            end
    
            unanticipated = [data{:, 6}];
            if any(expected_shock_dates & unanticipated)
                throw(MException('convert_gui_info_to_json', 'cannot set an expected date when shock is unanticipated'));
            end
    
            % Anticipated Permanent shock
            shock = data([data{:,7}] & ~[data{:,6}], :);
            ss = struct('exo_id', NaN, 'start_date', NaN, 'value', NaN);
            json.anticipated_permanent_shocks = repmat(ss, rows(shock), 1);
            for i = 1:rows(shock)
                if ~isempty(shock{i, 3})
                    throw(MException('Data:shock_error', 'permanent shocks cannot have end periods'));
                end
                json.anticipated_permanent_shocks(i).exo_id = ...
                    find(not(cellfun('isempty', strfind(M_.exo_names, shock{i, 1}))));
                json.anticipated_permanent_shocks(i).start_date = shock{i, 2};
                json.anticipated_permanent_shocks(i).value = evalin('base', shock{i, 4});
            end
    
            % Unanticipated Permanent shock
            shock = data([data{:,7}] & [data{:,6}], :);
            ss = struct('exo_id', NaN, 'start_date', NaN, 'value', NaN, 'anticipated_date', NaN);
            json.unanticipated_permanent_shocks = repmat(ss, rows(shock), 1);
            for i = 1:rows(shock)
                if ~isempty(shock{i, 3})
                    throw(MException('Data:shock_error', 'permanent shocks cannot have end periods'));
                end
                if ~isempty(shock{i, 5})
                    if shock{i, 5} > shock{i, 2}
                        throw(MException('Data:shock_error', 'cannot have expected date > start period'));
                    end
                end
                json.unanticipated_permanent_shocks(i).exo_id = ...
                    find(not(cellfun('isempty', strfind(M_.exo_names, shock{i, 1}))));
                json.unanticipated_permanent_shocks(i).start_date = shock{i, 2};
                json.unanticipated_permanent_shocks(i).anticipated_date = shock{i, 5};
                json.unanticipated_permanent_shocks(i).value = evalin('base', shock{i, 4});
            end
    
            % Anticipated Transitory shock
            shock = data(~[data{:,7}] & ~[data{:,6}], :);
            ss = struct('exo_id', NaN, 'start_date', NaN, 'end_date', NaN, 'value', NaN);
            json.anticipated_transitory_shocks = repmat(ss, rows(shock), 1);
            for i = 1:rows(shock)
                if isempty(shock{i, 3}) || ~isint(shock{i, 3}) || isnan(shock{i, 3}) || isinf(shock{i, 3})
                    throw(MException('Data:shock_error', 'transitory shocks must have end periods'));
                end
                json.anticipated_transitory_shocks(i).exo_id = ...
                    find(not(cellfun('isempty', strfind(M_.exo_names, shock{i, 1}))));
                json.anticipated_transitory_shocks(i).start_date = shock{i, 2};
                json.anticipated_transitory_shocks(i).end_date = shock{i, 3};
                json.anticipated_transitory_shocks(i).anticipated_date = shock{i, 5};
                json.anticipated_transitory_shocks(i).value = evalin('base', shock{i, 4});
            end
    
            % Unanticipated Transitory shock
            shock = data(~[data{:,7}] & [data{:,6}], :);
            ss = struct('exo_id', NaN, 'start_date', NaN, 'end_date', NaN, 'value', NaN);
            json.unanticipated_transitory_shocks = repmat(ss, rows(shock), 1);
            for i = 1:rows(shock)
                if isempty(shock{i, 3}) || ~isint(shock{i, 3}) || isnan(shock{i, 3}) || isinf(shock{i, 3})
                    throw(MException('Data:shock_error', 'transitory shocks must have end periods'));
                end
                if ~isempty(shock{i, 5})
                    if shock{i, 5} > shock{i, 2}
                        throw(MException('Data:shock_error', 'cannot have expected date > start period'));
                    end
                end
                json.unanticipated_transitory_shocks(i).exo_id = ...
                    find(not(cellfun('isempty', strfind(M_.exo_names, shock{i, 1}))));
                json.unanticipated_transitory_shocks(i).start_date = shock{i, 2};
                json.unanticipated_transitory_shocks(i).end_date = shock{i, 3};
                json.unanticipated_transitory_shocks(i).value = evalin('base', shock{i, 4});
                json.unanticipated_transitory_shocks(i).anticipated_date = shock{i, 5};
            end
    
            % Initval (exo)
            shock = model_settings.shocks;
            ss = struct('id', NaN, 'value', NaN);
            json.initval_exo = repmat(ss, rows(shock), 1);
            for i = 1:rows(shock)
                json.initval_exo(i).id = ...
                    find(not(cellfun('isempty', strfind(M_.exo_names, shock{i, 1}))));
                json.initval_exo(i).value = shock{i, 4};
            end
    
            % Initval (endo)
            endo = handles.endoTable.Data;
            ss = struct('id', NaN, 'value', NaN);
            json.initval_endo = repmat(ss, rows(endo), 1);
            for i = 1:rows(endo)
                json.initval_endo(i).id = ...
                    find(not(cellfun('isempty', strfind(M_.endo_names, endo{i, 2}))));
                json.initval_endo(i).value = endo{i, 3};
            end
    
            % Endval (endo)
            ss = struct('id', NaN, 'value', NaN);
            json.endval_endo = repmat(ss, rows(endo), 1);
            for i = 1:rows(endo)
                json.endval_endo(i).id = ...
                    find(not(cellfun('isempty', strfind(M_.endo_names, endo{i, 2}))));
                json.endval_endo(i).value = endo{i, 4};
            end
    
            % return as JSON string
            json = savejson('', json, 'ParseLogical', 1, 'FileName', '', 'ArrayIndent', 0);
        end
    end
    
    function init_val(~, evt, handles)
    global oo_
    if strcmp(evt.NewValue.String, 'zero')
        handles.endoTable.Data(:,3) = num2cell(zeros(M_.orig_endo_nbr, 1));
    elseif strcmp(evt.NewValue.String, 'steady state')
        if ~isfield(oo_, 'steady_state')
            gui_tools.show_warning('Must first calculate the steady state')
            evt.OldValue.Value = 1;
            return
        end
        handles.endoTable.Data(:,3) = num2cell(oo_.steady_state);
    elseif strcmp(evt.NewValue.String, 'smoother')
        if ~isfield(oo_, 'SmoothedVariables')
            gui_tools.show_warning('Must first run smoother')
            evt.OldValue.Value = 1;
            return
        end
        fname = inputdlg('output file from smoother2histval');
        if isempty(fname)
            evt.OldValue.Value = 1;
        else
            histvalf(fname{:})
            handles.endoTable.Data(:,3) = num2cell(M_.endo_histval);
        end
    end
    end