From d07dd3263238ce8bdb5964af9aec8ca7521ceaf7 Mon Sep 17 00:00:00 2001
From: Houtan Bastani <houtan@dynare.org>
Date: Fri, 2 Aug 2019 10:24:00 -0400
Subject: [PATCH] moment_calibration

---
 src/+gui_tools/menu_options.m |   1 +
 src/dynare_gui.m              |  31 +++--
 src/gui_moment_calibration.m  | 224 ++++++++++++++++++++++++++++++++++
 3 files changed, 248 insertions(+), 8 deletions(-)
 create mode 100644 src/gui_moment_calibration.m

diff --git a/src/+gui_tools/menu_options.m b/src/+gui_tools/menu_options.m
index c022a47..859ede5 100644
--- a/src/+gui_tools/menu_options.m
+++ b/src/+gui_tools/menu_options.m
@@ -72,6 +72,7 @@ switch oid
         handles.model_export.Enable = status;
         handles.sensitivity_analysis.Enable = status;
         handles.irf_calibration.Enable = status;
+        handles.moment_calibration.Enable = status;
 
     case 'output'
         if strcmpi(status, 'off')
diff --git a/src/dynare_gui.m b/src/dynare_gui.m
index 8f5725f..34a8843 100644
--- a/src/dynare_gui.m
+++ b/src/dynare_gui.m
@@ -321,6 +321,11 @@ possibly_create_model_settings();
 gui_irf_calibration(addTab(hObject, 'IRF Calibration', handles));
 end
 
+function moment_calibration_Callback(hObject, ~, handles)
+possibly_create_model_settings();
+gui_moment_calibration(addTab(hObject, 'Moment Calibration', handles));
+end
+
 % Output!
 function output_shock_decomposition_Callback(hObject, ~, handles)
 gui_shock_decomposition(addTab(hObject, 'Shock decomp. ', handles));
@@ -701,27 +706,37 @@ h24 = uimenu(...
     'CreateFcn', {@local_CreateFcn, blanks(0), appdata} );
 
 appdata = [];
-appdata.lastValidTag = 'sensitivity_analysis';
+appdata.lastValidTag = 'irf_calibration';
 
 uimenu(...
     'Parent',h24,...
     'Enable','off',...
-    'Callback',@(hObject,eventdata)dynare_gui('sensitivity_analysis_Callback',hObject,eventdata,guidata(hObject)),...
-    'Label','Sensitivity Analysis',...
-    'Tag','sensitivity_analysis',...
+    'Callback',@(hObject,eventdata)dynare_gui('irf_calibration_Callback',hObject,eventdata,guidata(hObject)),...
+    'Label','Irf Calibration',...
+    'Tag','irf_calibration',...
     'CreateFcn', {@local_CreateFcn, blanks(0), appdata} );
 
 appdata = [];
-appdata.lastValidTag = 'irf_calibration';
+appdata.lastValidTag = 'moment_calibration';
 
 uimenu(...
     'Parent',h24,...
     'Enable','off',...
-    'Callback',@(hObject,eventdata)dynare_gui('irf_calibration_Callback',hObject,eventdata,guidata(hObject)),...
-    'Label','Irf Calibration',...
-    'Tag','irf_calibration',...
+    'Callback',@(hObject,eventdata)dynare_gui('moment_calibration_Callback',hObject,eventdata,guidata(hObject)),...
+    'Label','Moment Calibration',...
+    'Tag','moment_calibration',...
     'CreateFcn', {@local_CreateFcn, blanks(0), appdata} );
 
+appdata = [];
+appdata.lastValidTag = 'sensitivity_analysis';
+
+uimenu(...
+    'Parent',h24,...
+    'Enable','off',...
+    'Callback',@(hObject,eventdata)dynare_gui('sensitivity_analysis_Callback',hObject,eventdata,guidata(hObject)),...
+    'Label','Sensitivity Analysis',...
+    'Tag','sensitivity_analysis',...
+    'CreateFcn', {@local_CreateFcn, blanks(0), appdata} );
 
 appdata = [];
 appdata.lastValidTag = 'uipanel_welcome';
diff --git a/src/gui_moment_calibration.m b/src/gui_moment_calibration.m
new file mode 100644
index 0000000..f1f3583
--- /dev/null
+++ b/src/gui_moment_calibration.m
@@ -0,0 +1,224 @@
+function gui_moment_calibration(tabId)
+% function gui_moment_calibration(tabId)
+% interface for the DYNARE moment_calibration command
+%
+% INPUTS
+%   tabId:  GUI tab element which displays the moment_calibration interface
+%
+% OUTPUTS
+%   none
+%
+% SPECIAL REQUIREMENTS
+%   none
+
+% Copyright (C) 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 options_
+
+handles = [];
+gui_size = gui_tools.get_gui_elements_size(tabId);
+
+uicontrol( ...
+    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 Moment Calibration', ...
+    'Callback', @call_moment_calibration);
+
+uicontrol( ...
+    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', @reset);
+
+uicontrol( ...
+    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 Tab', ...
+    'Callback', {@close_tab, tabId});
+
+handles.panel = uipanel( ...
+    tabId, ...
+    'Tag', 'panel', ...
+    'Units', 'normalized', ...
+    'Position', [0.01 0.1 .99 0.9], ...
+    'Title', '', ...
+    'BorderType', 'none');
+
+handles.tabGroup = uitabgroup( ...
+    handles.panel, ...
+    'Position', [0 0 1 1]);
+
+handles.tab = uitab( ...
+    handles.tabGroup, ...
+    'Title', 'Variables', ...
+    'UserData', 1);
+
+handles.var_panel = uipanel( ...
+    handles.tab, ...
+    'BorderType', 'none');
+
+uicontrol( ...
+    handles.var_panel, ...
+    'Style', 'text', ...
+    'Units', 'normalized', ...
+    'Position', [0.02 0.85 0.96 0.1], ...
+    'FontWeight', 'bold', ...
+    'String', 'Select variable and shock to define Moment calibration criteria.', ...
+    'HorizontalAlignment', 'left');
+
+endogs = model_settings.variables(:, 3);
+list_endogs1 = uicontrol( ...
+    handles.var_panel, ...
+    'Style', 'popupmenu', ...
+    'Units', 'normalized', ...
+    'Position', [0.02 0.77 0.3 0.06], ...
+    'String', ['Select endog...'; endogs], ...
+    'Callback', @varlist_selection_changed);
+
+list_endogs2 = uicontrol( ...
+    handles.var_panel, ...
+    'Style', 'popupmenu', ...
+    'Units', 'normalized', ...
+    'Position', [0.36 0.77 0.3 0.06], ...
+    'String', ['Select shock...'; endogs], ...
+    'Callback', @varlist_selection_changed);
+
+handles.add_var = uicontrol( ...
+    handles.var_panel, ...
+    'Style', 'pushbutton', ...
+    'Units', 'normalized', ...
+    'Position', [0.73 0.77 0.25 0.06], ...
+    'String', 'Add ...', ...
+    'Enable', 'Off', ...
+    'Callback', @add_var);
+
+handles.table = uitable(handles.var_panel, ...
+    'Units', 'normalized', ...
+    'Position', [0.02 0.10 0.96 0.6], ...
+    'ColumnName', {'Varibale1', 'Variable2', 'Period Sign', 'Start Period', 'End Period', 'Sign', 'Start Interval', 'End Interval', 'Remove'}, ...
+    'ColumnFormat', {'char', 'char', 'char', 'numeric', 'numeric', 'char', 'numeric', 'numeric', 'logical'}, ...
+    'ColumnEditable', [false, false, true, true, true, true, true, true, true], ...
+    'RowName', [], ...
+    'CellEditCallback', @savedata);
+
+handles.remove_all_selected = uicontrol( ...
+    handles.var_panel, ...
+    'Style', 'pushbutton', ...
+    'Units', 'normalized', ...
+    'Position', [0.73 0.03 0.25 0.06], ...
+    'String', 'Remove all selected', ...
+    'Enable', 'Off', ...
+    'Callback', @remove);
+
+    function varlist_selection_changed(~, ~)
+        if list_endogs1.Value > 1 && list_endogs2.Value > 1
+            handles.add_var.Enable = 'On';
+        else
+            handles.add_var.Enable = 'Off';
+        end
+    end
+
+    function add_var(~, ~)
+        if list_endogs1.Value > 1 && list_endogs2.Value > 1
+            handles.table.Data{end+1, 1} = endogs{list_endogs1.Value-1};
+            handles.table.Data{end, 2} = endogs{list_endogs2.Value-1};
+            handles.table.Data{end, 3} = '';
+            handles.table.Data{end, 4} = '';
+            handles.table.Data{end, 5} = '';
+            handles.table.Data{end, 6} = '';
+            handles.table.Data{end, 7} = '';
+            handles.table.Data{end, 8} = '';
+            handles.table.Data{end, 9} = false;
+        end
+    end
+
+    function remove(~, ~)
+        handles.table.Data = ...
+            handles.table.Data(not([handles.table.Data{:, 9}]), :);
+    end
+
+    function savedata(~, callbackdata)
+        if callbackdata.Indices(2) == 4 || callbackdata.Indices(2) == 5
+            if isnan(str2double(callbackdata.NewData))
+                handles.table.Data{callbackdata.Indices(1), callbackdata.Indices(2)} = ...
+                    callbackdata.PreviousData;
+            end
+        elseif callbackdata.Indices(2) == 3 || callbackdata.Indices(2) == 6
+            if ~strcmp(callbackdata.NewData, '-') ...
+                    && ~strcmp(callbackdata.NewData, '+')
+               handles.table.Data{callbackdata.Indices(1), callbackdata.Indices(2)} = ...
+                   callbackdata.PreviousData;
+            end
+        elseif callbackdata.Indices(2) == 7 || callbackdata.Indices(2) == 8
+            if isnan(str2double(callbackdata.NewData))
+                handles.table.Data{callbackdata.Indices(1), callbackdata.Indices(2)} = ...
+                    callbackdata.PreviousData;
+            end
+        elseif callbackdata.Indices(2) == 9
+            if any([handles.table.Data{:, 9}])
+                handles.remove_all_selected.Enable = 'On';
+            else
+                handles.remove_all_selected.Enable = 'Off';
+            end
+        end
+    end
+
+    function reset(~, ~)
+        handles.table.Data = cell(0, 9);
+    end
+
+    function call_moment_calibration(~, ~)
+        r = rows(handles.table.Data);
+        options_.endogenous_prior_restrictions.moment = cell(r, 4);
+        for i = 1:r
+            options_.endogenous_prior_restrictions.moment{i, 1} = handles.table.Data{i, 1};
+            options_.endogenous_prior_restrictions.moment{i, 2} = handles.table.Data{i, 2};
+            sign = 1;
+            if strcmp(handles.table.Data{i, 3}, '-')
+                sign = -1;
+            end
+            if str2double(handles.table.Data{i, 4}) == str2double(handles.table.Data{i, 5})
+                options_.endogenous_prior_restrictions.moment{i, 3} = sign*str2double(handles.table.Data{i, 4});
+            else
+                options_.endogenous_prior_restrictions.moment{i, 3} = sign*(str2double(handles.table.Data{i, 4}):str2double(handles.table.Data{i, 5}));
+            end
+            if isempty(handles.table.Data{i, 6})
+                options_.endogenous_prior_restrictions.moment{i, 4} = [str2double(handles.table.Data{i, 7}), str2double(handles.table.Data{i, 8})];
+            else
+                if strcmp(handles.table.Data{i, 6}, '+')
+                    options_.endogenous_prior_restrictions.moment{i, 4} = [0 inf];
+                else
+                    options_.endogenous_prior_restrictions.moment{i, 4} = [-inf 0];
+                end
+            end
+        end
+    end
+end
+
+function close_tab(~, ~, hTab)
+gui_tabs.delete_tab(hTab);
+end
-- 
GitLab