1function Spec = load_spec(specfile)
2%loadSpec Load model specification for a dynamic factor model (DFM)
3%
4% Description:
5%
6%   Load model specification  'Spec' from a Microsoft Excel workbook file
7%   given by 'filename'.
8%
9% Input Arguments:
10%
11%   filename -
12%
13% Output Arguments:
14%
15% spec - 1 x 1 structure with the following fields:
16%     . series_id
17%     . name
18%     . frequency
19%     . units
20%     . transformation
21%     . category
22%     . blocks
23%     . BlockNames
24%
25
26Spec = struct;
27[~,~,raw] = xlsread(specfile,'','','basic');
28header    = strrep(raw(1,:),' ','');
29raw       = raw(2:end,:);
30
31% Find and drop series from Spec that are not in Model
32Model = cell2mat(raw(:,strcmpi('Model',header)));
33raw(Model==0,:) = [];
34
35% Parse fields given by column names in Excel worksheet
36fldnms = {'SeriesID','SeriesName','Frequency','Units','Transformation','Category'};
37for iField = 1:numel(fldnms)
38    fld = fldnms{iField};
39    jCol = find(strcmpi(fld,header),1);
40    if isempty(jCol)
41        error([fld ' column missing from model specification.']);
42        % I guess Title and Units are not necessary though
43    else
44        Spec.(fld) = raw(:,jCol);
45    end
46end
47
48% Parse blocks.
49jColBlock = strncmpi('Block',header,length('Block'));
50Blocks = cell2mat(raw(:,jColBlock));
51Blocks(isnan(Blocks)) = 0;
52if ~all(Blocks(:,1)==1)
53    error('All variables must load on global block.');
54else
55    Spec.Blocks = Blocks;
56end
57
58% Sort all fields of 'Spec' in order of decreasing frequency
59frequency = {'d','w','m','q','sa','a'};
60permutation = [];
61for iFreq = 1:numel(frequency)
62    permutation = [permutation; find(strcmp(frequency{iFreq},Spec.Frequency))]; %#ok<AGROW>
63end
64
65fldnms = fieldnames(Spec);
66for iField = 1:numel(fldnms)
67    fld = fldnms{iField};
68    Spec.(fld) = Spec.(fld)(permutation,:);
69end
70
71Spec.BlockNames = regexprep(header(jColBlock),'Block\d-','');
72
73Spec.UnitsTransformed = Spec.Transformation;
74Spec.UnitsTransformed = strrep(Spec.UnitsTransformed,'lin','Levels (No Transformation)');
75Spec.UnitsTransformed = strrep(Spec.UnitsTransformed,'chg','Change (Difference)');
76Spec.UnitsTransformed = strrep(Spec.UnitsTransformed,'ch1','Year over Year Change (Difference)');
77Spec.UnitsTransformed = strrep(Spec.UnitsTransformed,'pch','Percent Change');
78Spec.UnitsTransformed = strrep(Spec.UnitsTransformed,'pc1','Year over Year Percent Change');
79Spec.UnitsTransformed = strrep(Spec.UnitsTransformed,'pca','Percent Change (Annual Rate)');
80Spec.UnitsTransformed = strrep(Spec.UnitsTransformed,'cch','Continuously Compounded Rate of Change');
81Spec.UnitsTransformed = strrep(Spec.UnitsTransformed,'cca','Continuously Compounded Annual Rate of Change');
82Spec.UnitsTransformed = strrep(Spec.UnitsTransformed,'log','Natural Log');
83
84% Summarize model specification
85fprintf('Table 1: Model specification \n');
86try
87    tabular = table(Spec.SeriesID,Spec.SeriesName,Spec.Units,Spec.UnitsTransformed,...
88                'VariableNames',{'SeriesID','SeriesName','Units','Transformation'});
89    disp(tabular);
90catch
91end
92
93end
94
95