From 3cfcc98ed7c0a698a9e81654d463615c07421d14 Mon Sep 17 00:00:00 2001
From: Johannes Pfeifer <jpfeifer@gmx.de>
Date: Thu, 3 Oct 2024 20:44:43 +0200
Subject: [PATCH] GetAllPosteriorDraws.m: make routine more efficient by
 enabling to output full parameters matrix instead of column vectors

Also factorizes loading of record file to obtain MCMC info by moving it into GetAllPosteriorDraws.m
---
 .../mcmc_diagnostics.m                        |  7 +-
 matlab/estimation/GetAllPosteriorDraws.m      | 91 +++++++++++++------
 .../GetPosteriorParametersStatistics.m        | 33 +------
 .../estimation/mh_autocorrelation_function.m  | 15 +--
 .../estimation/prior_posterior_statistics.m   | 18 +---
 matlab/estimation/trace_plot.m                | 23 +----
 6 files changed, 82 insertions(+), 105 deletions(-)

diff --git a/matlab/convergence_diagnostics/mcmc_diagnostics.m b/matlab/convergence_diagnostics/mcmc_diagnostics.m
index 6872074fb..ad216be37 100644
--- a/matlab/convergence_diagnostics/mcmc_diagnostics.m
+++ b/matlab/convergence_diagnostics/mcmc_diagnostics.m
@@ -59,16 +59,14 @@ if issue_an_error_message
 end
 
 % compute inefficiency factor
-FirstLine = record.KeepedDraws.FirstLine;
-TotalNumberOfMhFiles = sum(record.MhDraws(:,2));
 TotalNumberOfMhDraws = sum(record.MhDraws(:,1));
-FirstMhFile = record.KeepedDraws.FirstMhFile;
 NumberOfDraws = TotalNumberOfMhDraws-floor(options_.mh_drop*TotalNumberOfMhDraws);
 
 param_name = {};
 param_name_tex = {};
 
 Ifac=NaN(nblck,npar);
+AllDraws = GetAllPosteriorDraws(options_, M_.dname, M_.fname, 'all');
 for jj = 1:npar
     if options_.TeX
         [par_name_temp, par_name_tex_temp] = get_the_name(jj, options_.TeX, M_,estim_params_, options_.varobs);
@@ -79,8 +77,7 @@ for jj = 1:npar
         par_name_temp = get_the_name(jj, options_.TeX, M_, estim_params_, options_.varobs);
         param_name = vertcat(param_name, par_name_temp);
     end
-    Draws = GetAllPosteriorDraws(options_, M_.dname, M_.fname, jj, FirstMhFile, FirstLine, TotalNumberOfMhFiles, NumberOfDraws, nblck);
-    Draws = reshape(Draws, [NumberOfDraws nblck]);
+    Draws = reshape(AllDraws(:,jj), [NumberOfDraws nblck]);
     Nc = min(1000, NumberOfDraws/2);
     for ll = 1:nblck
         Ifac(ll,jj) = mcmc_ifac(Draws(:,ll), Nc);
diff --git a/matlab/estimation/GetAllPosteriorDraws.m b/matlab/estimation/GetAllPosteriorDraws.m
index fabf390af..6c1fd0211 100644
--- a/matlab/estimation/GetAllPosteriorDraws.m
+++ b/matlab/estimation/GetAllPosteriorDraws.m
@@ -1,26 +1,22 @@
-function draws = GetAllPosteriorDraws(options_, dname, fname, column, FirstMhFile, FirstLine, TotalNumberOfMhFile, NumberOfDraws, nblcks, blck)
-
+function draws = GetAllPosteriorDraws(options_, dname, fname, column, FirstLine , FirstMhFile, blck)
+% function draws = GetAllPosteriorDraws(options_, dname, fname, column, FirstLine , FirstMhFile, blck)
 % Gets all posterior draws.
 %
 % INPUTS
-% - options_               [struct]   Dynare's options.
-% - dname                  [char]     name of directory with results.
-% - fname                  [char]     name of mod file.
-% - column                 [integer]  scalar, parameter index.
-% - FirstMhFile            [integer]  scalar, first MH file.
-% - FirstLine              [integer]  scalar, first line in first MH file.
-% - TotalNumberOfMhFile    [integer]  scalar, total number of MH file.
-% - NumberOfDraws          [integer]  scalar, number of posterior draws.
-% - nblcks                 [integer]  scalar, total number of blocks.
-% - blck:                  [integer]  scalar, desired block to read.
+% - options_               [struct]             Dynare's options.
+% - dname                  [char]               name of directory with results.
+% - fname                  [char]               name of mod file.
+% - column                 [integer or string]  scalar, parameter index
+%                                               'all' if all parameters are 
+%                                               requested
+% - FirstMhFile            [integer]            optional scalar, first MH file to be used
+% - FirstLine              [integer]            optional scalar, first line in first MH file to be used
+% - blck:                  [integer]  scalar, desired block to read (optional)
 %
 % OUTPUTS
 % - draws:                 [double]   NumberOfDraws×1 vector, draws from posterior distribution.
-%
-% REMARKS
-% Only the first and third input arguments are required for SMC samplers.
 
-% Copyright © 2005-2023 Dynare Team
+% Copyright © 2005-2024 Dynare Team
 %
 % This file is part of Dynare.
 %
@@ -37,23 +33,35 @@ function draws = GetAllPosteriorDraws(options_, dname, fname, column, FirstMhFil
 % You should have received a copy of the GNU General Public License
 % along with Dynare.  If not, see <https://www.gnu.org/licenses/>.
 
+if isnumeric(column) && column<0
+    error('GetAllPosteriorDraws:: column cannot be negative');
+end
+
 if issmc(options_)
     if ishssmc(options_)
         % Load draws from the posterior distribution
         pfiles = dir(sprintf('%s/hssmc/particles-*.mat', dname));
         posterior = load(sprintf('%s/hssmc/particles-%u-%u.mat', dname, length(pfiles), length(pfiles)));
-        if column==0
-            draws = posterior.tlogpostkernel;
+        if column>0 || strcmp(column,'all')
+            if strcmp(column,'all')
+                draws = transpose(posterior.particles);
+            else
+                draws = transpose(posterior.particles(column,:));
+            end
         else
-            draws = transpose(posterior.particles(column,:));
+            draws = posterior.tlogpostkernel;
         end
     elseif isdime(options_)
         posterior = load(sprintf('%s%s%s%schains.mat', dname, filesep(), 'dime', filesep()));
         tune = posterior.tune;
         chains = posterior.chains(end-tune:end,:,:);
-        if column>0
+        if column>0 || strcmp(column,'all')
             chains = reshape(chains, [], size(chains, 3));
-            draws = chains(:,column);
+            if strcmp(column,'all')
+                draws = chains;
+            else
+                draws = chains(:,column);
+            end
         else
             draws = posterior.lprobs;
         end
@@ -61,11 +69,26 @@ if issmc(options_)
         error('GetAllPosteriorDraws:: case should not happen. Please contact the developers')
     end
 else
+    DirectoryName = CheckPath('metropolis',dname);
+    record=load_last_mh_history_file(DirectoryName,fname);
+    if nargin<5 || isempty(FirstLine)
+        FirstLine = record.KeepedDraws.FirstLine;
+    end
+    if nargin<6 || isempty(FirstMhFile)
+        FirstMhFile = record.KeepedDraws.FirstMhFile;
+    end
+    TotalNumberOfMhFile = sum(record.MhDraws(:,2));
+    TotalNumberOfMhDraws = sum(record.MhDraws(:,1));
+    NumberOfDraws = TotalNumberOfMhDraws-floor(options_.mh_drop*TotalNumberOfMhDraws);
+    [nblcks, npar] = size(record.LastParameters);
     iline = FirstLine;
     linee = 1;
-    DirectoryName = CheckPath('metropolis',dname);
-    if nblcks>1 && nargin<10
-        draws = zeros(NumberOfDraws*nblcks,1);
+    if nblcks>1 && nargin<7
+        if strcmp(column,'all')
+            draws = zeros(NumberOfDraws*nblcks,npar);
+        else
+            draws = zeros(NumberOfDraws*nblcks,1);
+        end
         iline0=iline;
         if column>0
             for blck = 1:nblcks
@@ -73,7 +96,11 @@ else
                 for file = FirstMhFile:TotalNumberOfMhFile
                     load([DirectoryName '/'  fname '_mh' int2str(file) '_blck' int2str(blck)],'x2')
                     NumberOfLines = size(x2(iline:end,:),1);
-                    draws(linee:linee+NumberOfLines-1) = x2(iline:end,column);
+                    if strcmp(column,'all')
+                        draws(linee:linee+NumberOfLines-1,:) = x2(iline:end,:);
+                    else
+                        draws(linee:linee+NumberOfLines-1) = x2(iline:end,column);
+                    end
                     linee = linee+NumberOfLines;
                     iline = 1;
                 end
@@ -90,15 +117,25 @@ else
                 end
             end
         end
-    else
+    else %read desired block
         if nblcks==1
             blck=1;
         end
+        if strcmp(column,'all')
+            draws = zeros(NumberOfDraws,npar);
+        else
+            draws = zeros(NumberOfDraws,1);
+        end
+
         if column>0
             for file = FirstMhFile:TotalNumberOfMhFile
                 load([DirectoryName '/'  fname '_mh' int2str(file) '_blck' int2str(blck)],'x2')
                 NumberOfLines = size(x2(iline:end,:),1);
-                draws(linee:linee+NumberOfLines-1) = x2(iline:end,column);
+                if strcmp(column,'all')
+                    draws(linee:linee+NumberOfLines-1,:) = x2(iline:end,:);
+                else
+                    draws(linee:linee+NumberOfLines-1) = x2(iline:end,column);
+                end
                 linee = linee+NumberOfLines;
                 iline = 1;
             end
diff --git a/matlab/estimation/GetPosteriorParametersStatistics.m b/matlab/estimation/GetPosteriorParametersStatistics.m
index 299ccdaca..208a37779 100644
--- a/matlab/estimation/GetPosteriorParametersStatistics.m
+++ b/matlab/estimation/GetPosteriorParametersStatistics.m
@@ -44,17 +44,7 @@ np      = estim_params_.np ;
 latexFolder = CheckPath('latex',M_.dname);
 FileName = M_.fname;
 
-if ~issmc(options_)
-    MetropolisFolder = CheckPath('metropolis',M_.dname);
-    record=load_last_mh_history_file(MetropolisFolder,FileName);
-    FirstLine = record.KeepedDraws.FirstLine;
-    TotalNumberOfMhFiles = sum(record.MhDraws(:,2));
-    TotalNumberOfMhDraws = sum(record.MhDraws(:,1));
-    FirstMhFile = record.KeepedDraws.FirstMhFile;
-    NumberOfDraws = TotalNumberOfMhDraws-floor(options_.mh_drop*TotalNumberOfMhDraws);
-    mh_nblck = size(record.LastParameters,1);
-    clear record;
-end
+[~, ~, num_draws]=set_number_of_subdraws(M_,options_); %get number of draws
 
 header_width = row_header_width(M_, estim_params_, bayestopt_);
 hpd_interval=[num2str(options_.mh_conf_sig*100), '% HPD interval'];
@@ -67,31 +57,18 @@ skipline()
 
 if ishssmc(options_)
     dprintf('Log data density is %f.', oo_.MarginalDensity.hssmc);
-    % Set function handle for GetAllPosteriorDraws
-    getalldraws = @(i) GetAllPosteriorDraws(options_, M_.dname, [], i);
+    hpd_draws = round((1-options_.mh_conf_sig)*num_draws);
 elseif isdime(options_)
-    getalldraws = @(i) GetAllPosteriorDraws(options_, M_.dname, [], i);
+    hpd_draws = round((1-options_.mh_conf_sig)*num_draws);
 else
     if ~isfield(oo_,'MarginalDensity') || (issmc(options_) && ~isfield(oo_.MarginalDensity,'ModifiedHarmonicMean'))
         [~, oo_] = marginal_density(M_, options_, estim_params_, oo_, bayestopt_);
     end
     fprintf('Log data density (Modified Harmonic Mean) is %f.', oo_.MarginalDensity.ModifiedHarmonicMean);
-    % Set function handle for GetAllPosteriordraws
-    getalldraws = @(i) GetAllPosteriorDraws(options_, M_.dname, M_.fname, i, FirstMhFile, FirstLine, TotalNumberOfMhFiles, NumberOfDraws, mh_nblck);
-end
-
-if ishssmc(options_)
-    num_draws = options_.posterior_sampler_options.hssmc.particles;
-    hpd_draws = round((1-options_.mh_conf_sig)*num_draws);
-elseif isdime(options_)
-    nchain = options_.posterior_sampler_options.current_options.nchain;
-    tune = options_.posterior_sampler_options.current_options.tune;
-    num_draws = nchain*tune;
-    hpd_draws = round((1-options_.mh_conf_sig)*num_draws);
-else
-    num_draws=NumberOfDraws*mh_nblck;
     hpd_draws = round((1-options_.mh_conf_sig)*num_draws);
 end
+% Set function handle for GetAllPosteriorDraws
+getalldraws = @(i) GetAllPosteriorDraws(options_, M_.dname, M_.fname, i);
 
 if hpd_draws<2
     fprintf('posterior_moments: There are not enough draws computes to compute HPD Intervals. Skipping their computation.\n')
diff --git a/matlab/estimation/mh_autocorrelation_function.m b/matlab/estimation/mh_autocorrelation_function.m
index 953b542ef..04ef6fb2c 100644
--- a/matlab/estimation/mh_autocorrelation_function.m
+++ b/matlab/estimation/mh_autocorrelation_function.m
@@ -45,21 +45,8 @@ if isempty(column)
     return
 end
 
-% Get informations about the posterior draws:
-MetropolisFolder = CheckPath('metropolis',M_.dname);
-record=load_last_mh_history_file(MetropolisFolder, M_.fname);
-
-FirstMhFile = record.KeepedDraws.FirstMhFile;
-FirstLine = record.KeepedDraws.FirstLine; ifil = FirstLine;
-TotalNumberOfMhFiles = sum(record.MhDraws(:,2));
-TotalNumberOfMhDraws = sum(record.MhDraws(:,1));
-NumberOfDraws = TotalNumberOfMhDraws-floor(options_.mh_drop*TotalNumberOfMhDraws);
-nblck = size(record.LastParameters,1);
-
-clear record;
-
 % Get all the posterior draws:
-PosteriorDraws = GetAllPosteriorDraws(options_, M_.dname, M_.fname, column, FirstMhFile, FirstLine, TotalNumberOfMhFiles, NumberOfDraws, nblck, blck);
+PosteriorDraws = GetAllPosteriorDraws(options_, M_.dname, M_.fname, column, [],[], blck);
 
 % Compute the autocorrelation function:
 [~,autocor] = sample_autocovariance(PosteriorDraws,options_.mh_autocorrelation_function_size);
diff --git a/matlab/estimation/prior_posterior_statistics.m b/matlab/estimation/prior_posterior_statistics.m
index 519a58296..0768a4d30 100644
--- a/matlab/estimation/prior_posterior_statistics.m
+++ b/matlab/estimation/prior_posterior_statistics.m
@@ -203,20 +203,12 @@ localVars.bayestopt_=bayestopt_;
 
 
 if strcmpi(type,'posterior')
-    record=load_last_mh_history_file(DirectoryName, M_.fname);
-    [nblck, npar] = size(record.LastParameters);
-    FirstMhFile = record.KeepedDraws.FirstMhFile;
-    FirstLine = record.KeepedDraws.FirstLine;
-    TotalNumberOfMhFiles = sum(record.MhDraws(:,2));
-    TotalNumberOfMhDraws = sum(record.MhDraws(:,1));
-    NumberOfDraws = TotalNumberOfMhDraws-floor(options_.mh_drop*TotalNumberOfMhDraws);
-    mh_nblck = options_.mh_nblck;
-    if B==NumberOfDraws*mh_nblck
+    [~, ~, NumberOfDraws]=set_number_of_subdraws(M_,options_);
+
+    if B==NumberOfDraws
         % we load all retained MH runs !
-        logpost=GetAllPosteriorDraws(options_, M_.dname, M_.fname, 0, FirstMhFile, FirstLine, TotalNumberOfMhFiles, NumberOfDraws, nblck);
-        for column=1:npar
-            x(:,column) = GetAllPosteriorDraws(options_, M_.dname, M_.fname, column, FirstMhFile, FirstLine, TotalNumberOfMhFiles, NumberOfDraws, nblck);
-        end
+        logpost=GetAllPosteriorDraws(options_, M_.dname, M_.fname, 0);
+        x = GetAllPosteriorDraws(options_, M_.dname, M_.fname, 'all');
     else
         [x, logpost]=get_posterior_subsample(M_,options_,B);
     end
diff --git a/matlab/estimation/trace_plot.m b/matlab/estimation/trace_plot.m
index a3bb401ab..2d0dd7c2d 100644
--- a/matlab/estimation/trace_plot.m
+++ b/matlab/estimation/trace_plot.m
@@ -53,17 +53,7 @@ if isempty(column)
 end
 
 if ~issmc(options_)
-    % Get informations about the posterior draws:
-    MetropolisFolder = CheckPath('metropolis',M_.dname);
-    record=load_last_mh_history_file(MetropolisFolder, M_.fname);
-
-    FirstMhFile = 1;
-    FirstLine = 1;
-    TotalNumberOfMhFiles = sum(record.MhDraws(:,2));
-    TotalNumberOfMhDraws = sum(record.MhDraws(:,1));
-    [mh_nblck] = size(record.LastParameters,2);
-    clear record;
-
+    options_.mh_drop=0; % locally, do not drop as we want all draws
     n_nblocks_to_plot=length(blck);
 else
     if ishssmc(options_)
@@ -73,14 +63,11 @@ else
     end
 end
 
+[~, ~, TotalNumberOfMhDraws]=set_number_of_subdraws(M_,options_); 
+
 if n_nblocks_to_plot==1
 % Get all the posterior draws:
-    if ishssmc(options_)
-        PosteriorDraws = GetAllPosteriorDraws(options_, M_.dname,[],column);
-        TotalNumberOfMhDraws=length(PosteriorDraws);
-    else
-        PosteriorDraws = GetAllPosteriorDraws(options_, M_.dname,M_.fname,column, FirstMhFile, FirstLine, TotalNumberOfMhFiles, TotalNumberOfMhDraws, mh_nblck, blck);
-    end
+    PosteriorDraws = GetAllPosteriorDraws(options_, M_.dname,M_.fname,column, 1, 1, blck);
 else
     PosteriorDraws=NaN(TotalNumberOfMhDraws,n_nblocks_to_plot);
     save_string='';
@@ -88,7 +75,7 @@ else
         title_string_tex='';
     end
     for block_iter=1:n_nblocks_to_plot
-        PosteriorDraws(:,block_iter) = GetAllPosteriorDraws(options_, M_.dname, M_.fname, column, FirstMhFile, FirstLine, TotalNumberOfMhFiles, TotalNumberOfMhDraws, mh_nblck, blck(block_iter));
+        PosteriorDraws(:,block_iter) = GetAllPosteriorDraws(options_, M_.dname, M_.fname, column, 1, 1, blck(block_iter));
         save_string=[save_string,'_',num2str(blck(block_iter))];
         if options_.TeX
             title_string_tex=[title_string_tex, ', ' num2str(blck(block_iter))];
-- 
GitLab