function PrintVarianceDecompositions(DSGEModel,FEVDs,LRVD,UniquenessCheck,PrintGroups,Levels,CurrINI,EstStr)
% PrintVarianceDecompositions: Writes the forecast error variance decompositions for the observed variables
%                              to a text file.
%
% USAGE:
%
%       PrintVarianceDecompositions(DSGEModel,FEVDs,LRVD,UniquenessCheck,PrintGroups,Levels,CurrINI,EstStr)
%
% REQUIRED INPUT: DSGEModel (structure) whose fields contain all required information
%                           about the model, such as input files, variable and sample
%                           data. Actual observations are not stored in this file.
%
%                 FEVDs (nx(n+q+1)xh) matrix with the forecast error variance decompositions. For each h, the nx(n+q+1) matrix
%                           is ordered such the the measurement errors are located in the first n columns, and the q economic
%                           shocks in the following columns. The remaining column captures possible signal extraction error
%                           variances. The observed variables are determined through the row numbers.
%
%                 LRVD (nx(n+q)) matrix with the long run forecast error variance decomposition.
%
%                 UniquenessCheck ((q+1) vector), with largest eigenvalues of (F-K*H'), where K is the asymptote of the
%                           Kalman gain matrix, i.e., K = F*P1*H*inv(H'*P1*H+R). Elements 1 concerns the full forecast error
%                           variance, while the following q relate to the forecast error variances obtained when economic
%                           shock j, j=1,...,q, is allowed for.
%
%                 PrintGroups (boolean) which indicates if shock groups are used (1) or not (0).
%
%                 Levels (boolean) that is 1 if levels decompositions should be studied and 0 otherwise.
%
%                 CurrINI (structure), with initialization information.
%
%                 EstStr (string vector) that takes the value "posterior mode" or "initial".
%
%
%                       Written by: Anders Warne
%                                   New Area Wide Model Project
%                                   DG-R/EMO
%                                   European Central Bank (ECB)
%                                   Email: anders.warne@ecb.europa.eu
%                                   Copyright © 2006-2009 European Central Bank.
%
%                       First version: October 25, 2006.
%                        This version: January 21, 2009.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% LICENSE INFORMATION:
%
%      YADA 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.
%
%      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, see <http://www.gnu.org/licenses/>.
%
%      YADA is released under the GNU General Public License, Version 3,
%      29 June 2007 <http://www.gnu.org/licenses/>. The current release of
%      the program was last modified by the ECB on the "This version" date
%      above.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% CHANGELOG:
%
% * 31-10-2006: Added the function input "LRVD".
%
% * 2-11-2006:  Included the shares due to the signal extraction error variance when the model has measurement
%               errors.
%
% * 8-11-2006:  Added the notes about potential errors added to signal extraction errors because of convergence
%               issues.
%
% * 21-11-2006: The new input variable "UniquenessCheck" is now taken into account.
%
% * 22-11-2006: Took the last column of FEVDs into account. Added the calculation error row in the output.
%
% * 24-11-2006: Changed how n and q are calculated.
%
% * 13-11-2007: Updated the documentation.
%
% * 18-4-2008:  Increased the length of the first column from 15 to 20. The input variable "PrintGroups" was added
%               and the code updated to take this change into account.
%
% * 22-4-2008:  Uniqueness results are only reported for the total forecast error variance.
%
% * 23-4-2008:  The members of each shock group are now written to the file.
%
% * 23-5-2008:  Updated the documentation.
%
% * 21-01-2009: Updated the documentation.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%

LevStr = '';
if Levels==1;
   LevStr = 'Levels-';
end;
if strcmp(lower(EstStr),'posterior mode')==1;
   if PrintGroups==0;
      ResFile = [DSGEModel.OutputDirectory '\PosteriorModeFEVDs-' LevStr DSGEModel.NameOfModel '.txt'];
   else;
      ResFile = [DSGEModel.OutputDirectory '\PosteriorModeFEVDs-ShockGroups-' LevStr DSGEModel.NameOfModel '.txt'];
   end;
else;
   if PrintGroups==0;
      ResFile = [DSGEModel.OutputDirectory '\InitialValueFEVDs-' LevStr DSGEModel.NameOfModel '.txt'];
   else;
      ResFile = [DSGEModel.OutputDirectory '\InitialValueFEVDs-ShockGroups-' LevStr DSGEModel.NameOfModel '.txt'];
   end;
end;
fid = fopen(ResFile,'wt');
fprintf(fid,'********************************************************************************\n');
fprintf(fid,'*                                                                              *\n');
fprintf(fid,'* F O R E C A S T   E R R O R   V A R I A N C E   D E C O M P O S I T I O N S  *\n');
fprintf(fid,'*                                                                              *\n');
fprintf(fid,'********************************************************************************\n\n');
fprintf(fid,'NOTE: Using the %s values. The Signal Extraction Error row is\n      explained in "YADA Manual - Computational Details".\n\n',lower(EstStr));
[n,vn] = size(DSGEModel.VariableNames);
if PrintGroups==0;
   [q,vq] = size(DSGEModel.StateShockNames);
   NamesMatrix = DSGEModel.StateShockNames;
else;
   [q,vq] = size(DSGEModel.ShockGroupNames);
   NamesMatrix = char(zeros(size(DSGEModel.ShockGroupNames)));
   for i=1:q;
      NamesMatrix(i,:) = strrep(DSGEModel.ShockGroupNames(i,:),'_',' ');
   end;
end;
[n,nq] = size(LRVD);
if PrintGroups==0;
   q = nq-n;
else;
   q = nq-1;
end;
%
% print uniqueness results
%
if PrintGroups==0;
   fprintf(fid,'--------------------------------------------------------------------------------\n');
   fprintf(fid,'              Uniqueness Properties of the Variance Decompositions\n');
   fprintf(fid,'                         For the 1-Step Ahead Forecasts\n');
   fprintf(fid,'--------------------------------------------------------------------------------\n');
   if UniquenessCheck<1-1e-14;
      fprintf(fid,'* Total Forecast Error Variance:%s            Unique asymptote.\n',SpaceStr(vq));
   else;
      fprintf(fid,'* Total Forecast Error Variance:%s            Multiple asymptotes possible.\n',SpaceStr(vq));
   end;
   fprintf(fid,'--------------------------------------------------------------------------------\n\n');
   fprintf(fid,'NOTE: The forecast error variance decomposition for the long run is always unique\n      when the state vector is stationary. The h-steps ahead FEVDs are unique for\n      all finite h if the 1-step ahead FEVD is.\n\n');
else;
   for i=1:q;
      iGroup = (DSGEModel.ShockGroups==i) .* (1:length(DSGEModel.ShockGroups));
      iGroup = iGroup(iGroup>0);
      ShockNames = StrWrap(vecstr(DSGEModel.StateShockNames(iGroup,:),' '),60);
      GroupName = StringTrim(NamesMatrix(i,:));
      if size(GroupName,2)<25;
         AddSpace = SpaceStr(25-size(GroupName,2));
      else;
         AddSpace = '';
      end;
      fprintf(fid,'%s:%s %s\n',GroupName,AddSpace,ShockNames(1,:));
      for j=2:size(ShockNames,1);
         if strcmp(StringTrim(ShockNames(j,:)),'')==0;
            fprintf(fid,'%s%s\n',SpaceStr(27),ShockNames(j,:));
         end;
      end;
   end;
   fprintf(fid,'\n');
end;
%
if vn<15;
   add_name_str = SpaceStr(15-vn);
else;
   add_name_str = '';
end;
if vq<20;
   add_shock_str = SpaceStr(20-vq);
else;
   add_shock_str = '';
end;
NameStr = '                    ';
MEStr = '';
prt_str = '%s';
prt_val = ['%' num2str(6+CurrINI.decimals,'%0.0f') '.' num2str(CurrINI.decimals,'%0.0f') 'f'];
for i=1:n;
   NameStr = [NameStr '   ' add_name_str DSGEModel.VariableNames(i,:)];
   if PrintGroups==0;
      MEStr = strvcat(MEStr,sprintf('Measure Error %3.0f',i));
   end;
   prt_str = [prt_str '      ' prt_val];
end;
%
for i=1:q;
   MEStr = strvcat(MEStr,sprintf('%s%s',add_shock_str,NamesMatrix(i,:)));
end;
FirstStr = MultiCharStr('=',length(NameStr));
DivStr = MultiCharStr('-',length(NameStr));
%
% Write to output for horizon h
%
for j=1:size(FEVDs,3);
   fprintf(fid,'%s\n',FirstStr);
   fprintf(fid,'Forecast Horizon: %3.0f\n',j);
   fprintf(fid,'%s\n',NameStr);
   if PrintGroups==0;
      for i=1:n+q;
         fprintf(fid,'%s\n',DivStr);
         if i==n+1;
            fprintf(fid,[prt_str '\n'],'All Measure Error   ',sum(abs(FEVDs(:,1:n,j)),2));
            fprintf(fid,'%s\n',FirstStr);
         end;
         fprintf(fid,[prt_str '\n'],MEStr(i,:),abs(FEVDs(:,i,j)));
      end;
   else;
      fprintf(fid,'%s\n',DivStr);
      fprintf(fid,[prt_str '\n'],'All Measure Error   ',abs(FEVDs(:,1,j)));
      fprintf(fid,'%s\n',FirstStr);
      for i=1:q;
         fprintf(fid,[prt_str '\n'],MEStr(i,:),abs(FEVDs(:,i+1,j)));
      end;
   end;
   fprintf(fid,'%s\n',DivStr);
   if PrintGroups==0;
      fprintf(fid,[prt_str '\n'],'All Economic Shocks ',sum(abs(FEVDs(:,n+1:n+q,j)),2));
      fprintf(fid,'%s\n',FirstStr);
      fprintf(fid,[prt_str '\n'],'Signal Extract Error',abs(FEVDs(:,n+q+1,j)));
   else;
      fprintf(fid,[prt_str '\n'],'All Economic Shocks ',sum(abs(FEVDs(:,2:1+q,j)),2));
      fprintf(fid,'%s\n',FirstStr);
      fprintf(fid,[prt_str '\n'],'Signal Extract Error',abs(FEVDs(:,q+2,j)));
   end;
   fprintf(fid,'%s\n\n',FirstStr);
end;
%
% and now the long run
%
fprintf(fid,'%s\n',FirstStr);
fprintf(fid,'Forecast Horizon: Long Run\n');
fprintf(fid,'%s\n',NameStr);
if PrintGroups==0;
   for i=1:size(LRVD,2);
      fprintf(fid,'%s\n',DivStr);
      if i==n+1;
         fprintf(fid,[prt_str '\n'],'All Measure Error   ',sum(abs(LRVD(:,1:n)),2));
         fprintf(fid,'%s\n',FirstStr);
      end;
      fprintf(fid,[prt_str '\n'],MEStr(i,:),abs(LRVD(:,i)));
   end;
   fprintf(fid,'%s\n',DivStr);
   fprintf(fid,[prt_str '\n'],'All Economic Shocks ',sum(abs(LRVD(:,n+1:n+q)),2));
else;
   fprintf(fid,'%s\n',DivStr);
   fprintf(fid,[prt_str '\n'],'All Measure Error   ',sum(abs(LRVD(:,1)),2));
   fprintf(fid,'%s\n',FirstStr);
   for i=1:q;
      fprintf(fid,[prt_str '\n'],MEStr(i,:),abs(LRVD(:,i+1)));
   end;
   fprintf(fid,'%s\n',DivStr);
   fprintf(fid,[prt_str '\n'],'All Economic Shocks ',sum(abs(LRVD(:,2:1+q)),2));
end;
fprintf(fid,'%s\n\n',FirstStr);
fprintf(fid,'Directory for file: %s\n',GetPath(ResFile));
fprintf(fid,'Name of file:       %s\n',GetFilename(ResFile));
fprintf(fid,'Output created on:  %s\n\n',datestr(now,0));
fclose(fid);

%
% end of PrintVarianceDecompositions.m
%
