classdef tree_structure
    %% This API object helps you navigate an MRIO.
    % For example to quickly find the indices for France in the T
    % matrix you can say:
    %    tinds = tr.indexT{tr.a3('FRA')};
    %
    % For reading Eora MRIOs the preferred constructor is:
    %   tr = tree_structure(199,74,'usecache');
    % This means to load a TreeStructure for dataset v199.74, reading the
    % tree structure info from a cached .mat file if available (this is
    % faster, but does introduce the risk of a stale cache)
    %
    % For navigating non-Eora MRIOs the preferred constructor is:
    %   tr = tree_structure('K:/indecol/USERS/Dan Moran/CREEA_ProdProdMRIO/TreeStructure/');
    % where that path contains a set of .txt files like
    % RowGrandchildren.txt, etc, which describe the MRIO structure.
    %
    % For more examples on how to use the TreeStructure, read the inline
    % documentation below or visit the documentation at
    %     http://worldmrio.com/api_tutorial.html
    %
    % Author: Dan Moran and Keiichiro Kanemoto. 2012.
    %
    
    properties
        phase;		% The major identifier number for an Eora MRIO
        loop;		% The minor identifier number for an Eora MRIO
        inning;		% Nearly always the MRIO, say, 199.61, will be linked to the Satellite account ("inning") 199.61. However it is possible to link the MRIO 199.61 to, say, Inning 199.60.
        phasestr;	% like '199'
        loopstr;    % like '061'
        mrio;		% a struct. DEPRECATED
        sat;		% a struct. DEPRECATED
        
        years;          % Vector containing years covered e.g. [2000 2001 2002]
        year;           % Same as years
        year_range; 	% Same as years
        
        
        isEORA;         % True iff this tree_structure represents an Eora MRIO
        isCCC;          % Is a common classification tree structure
        isCCCCJ;        % is a Chris Jones common classification
        base_loop;      % If isCCC or isCCCCJ then base_loop is loop-250 or -500.
        base_loopstr;
        
        Tdim;			% dimension of the T matrix excluding PI and FD
        Mdim			% dimension of the T matrix including PI and FD
        Ydim;			% NCOUNTRIES * 6 (because we have 6 FD categories)
        Vdim;			% NCOUNTRIES * 6 (because we have 6 PI categories)
        Qdim;			% How mayn satellite indicator rows
        
        NCOUNTRIES;     % How many countries (including RoW). This is the same as country_number.
        country_number;	% How many countries (including RoW). This is the same as NCOUNTRIES.
        country_number_without_row; % How many countries (exlcuding RoW, if it is present in this MRIO)
        
        NINDICATORS;    % How many indicators
        sheets;         % How many sheets. Usually 5.
        
        
        path;           % e.g. '/import/penelope1/isa/WorldMRIO/Project/Comptuations/Phase100/Loop001/'
        sat_path;        % Same, but for Inning
        
        base_path;      % The location of the base loop. Only different if isCCC or isCCCCJ
        base_sat_path;
        
        countries;      % Cell array like {'AFG','ARG','ANT'... }
        country;        % same
        country_acronyms; %same
        
        tree_path;      % e.g. '/import/penelope1/isa/WorldMRIO/Project/Comptuations/Phase100/Loop001/TreeStructure'
        tree_satpath;   % Same, but for Inning. Note that for legacy reasons the Inning tree structure lives in the "harmonzized" subfolder.
        tree_satpath_orig; % The Inning tree structure folder before it has been "harmonized". Rarely used.
        
        row;            % NCOUNTRIES x 3 matrix. Col 1 and 2 contain IND and COM dimensions. Col 3 contains Y/V dimension
        row_cls;        % NCOUNTRIES x 3 cell array, each cell contains the classification name e.g. ISA-FD or ISA-CCC-I
        col;            % Same, but for columns
        col_cls;
        
        row_sat;        % NINDICATORS vector with the # of rows for each indicator. However, if flag 'natsatcla' is specified, this will be NCOUNTRIESxNINDICATORS.
        row_sat_cls;    % NINDICATORSx2 cell vector with the classification and indicatorID for each indicator. However, if flag 'natsatcla' is specified, this will much different!!
        indicator;		% UNDOCUMENTED
        
        DSN;            % Eora only. Data Source Number e.g. 006 or 005. This is -1 if no file 'DataNumber' is found.
        
        indexT;         % NCOUNTRIES cell array, where each entry contains a vector like 1:26 with its indices into T
        indexYV;        % Ditto, but indices into Y/V
        indexM;         % Ditto, but indices into a T/Y/V interwoven matrix
        indexQ;         % NINDICATORS cell array, where each entry contains a vector like 1:9 with that indicators indices into Q rows
        indexTforSat;   % Like indexT, but for SUT countries instead of containing IND+COM columns, contains only INDustry columns (ie. the satellite inputs)
        indexMforSat;   % Like indexM, but for SUT countries instead of containing IND+COM columns, contains only INDustry columns (ie. the satellite inputs)
        
        indexTforUse;   % Like indexT, but for SUT countries holds only the Supply table. Yes, you read that right, Supply. The variable is named wrong.
        labsT;          % Tdim x 4 cell array with columns like ['Afghanistan', 'AFG','Industries','Agriculture']. If no labels are found or 'nolabs' flag is passed, only column 2 is populated
        labsV;
        labsY;
        labsM;
        labsMrows; labsMcols;
        labsQ;          % Tdim x 2 cell array with columns like ['GHG-CO2 (Gg)', 'Public electricty and heat production']
        
        secLabsT;       % Tdim x 1 cell array, where each entry contains the sector label for T (e.g. 'Agriculture'). Entries may be [] if no labels can be found.
        secLabsM;       % Ditto, but for M
        secLabsV;       % Ditto, but for V (PI block)
        secLabsY;       % Ditto, but for Y (FD block)
        secLabsQ;       % Ditto, but for Q (Satellite block)
        secLabsMrows;
        secLabsMcols;
        sector_name;	% UNDOCUMENTED
        
        
        
        
        coIsSUT;        % NCOUNTRIES logical vector
        isSUT;          % Tdim logical vector
        iotype;         % NCOUNTRIES x1 cell array, where each entry is one of 'CIOT','IIOT', or 'SUT'
        type;			% UNDOCUMENTED
        
        
        % For backwards compatiblity:
        row_d_data;     % Same as row_cls
        col_d_data;     % Same as col_cl
        row_tree_data;	% ditto
        col_tree_data;	% ditto
        
        private_treestrucfiles_cachedhashcode; % Internal use
        
    end;
    %
    methods
        %% Constructor. Usage:
        % tr = tree_structure();  - creates an empty tree
        % tr = tree_structure(path, [flags])  - where path is like '/path/of/Aisha/Experiment/Loop100'
        %       e.g:   tr = tree_structure('c:/MyData/Eora/v199.74/', 'usecache');
        % tr = tree_structure(199,28, [flags]) - loads the tree structure for 199.28
        % tr = tree_structure(100,5, [flags], handles) - Uses handles.workdirectory{1} to find the MRIO.
        %
        % flags is an optional space-delimited string of flags. Can be '' or []. Valid flags are:
        % 	nolabs  - skip loading secLab* (tree will load faster)
        %   natsatcla - read the satellite tree structure out of "./InningXXX/TreeStructure/", not "./InningXXX/TreeStucture/harmonised/"
        %   nocache - DEPRECIATED. ignore the cached tree_structure.mat file (if it exists)
        %   deletecache - Deletes the cached .mat file, if it exists
        %   quiet - skip most information messages
        %   usecache - use a cached tree_structure.mat file if it exists. USE AT YOUR OWN RISK! You may be reading a stale cachefile.
        %
        function obj = tree_structure(mrio_phase, mrio_loop, flags, handles)
            
            % What arguments were provided? Find
            % Signature=0: tr = new tree_structure()
            % Signature=1: tr = new tree_structure(path, [flags])
            % Signature=2: tr = new tree_structure(199, 28, [flags], handles)
            % For details please open tree_structure.m and check line
            % 156.. for available flags. Currently: ''nolabs','usecache'
            signature = nargin;
            if nargin==2 && isnumeric(mrio_phase) && ~isnumeric(mrio_loop), signature=1; flags=mrio_loop; handles=[]; end;
            if nargin==2 && isnumeric(mrio_phase) && isnumeric(mrio_loop), signature=2; flags=''; handles=[]; end;
            if nargin==3, signature=2; handles=[]; end;
            if nargin==4, signature=2; end;
            
            obj.isEORA=1;
            
            % Create an all-empty tree_structure
            if signature==0,
                obj.phase = 0;
                obj.loop = 0;
                
                obj.isCCC = 0;
                obj.isCCCCJ = 0;
                obj.base_loop = 0;
                
                obj.phasestr=num2str(obj.phase); obj.loopstr=num2str(obj.loop); obj.base_loopstr = num2str(obj.base_loop);
                
                obj.countries = cell(0); obj.country = ucfirst(cell(0));
                
                % Interpret based on the path provided
            elseif signature==1,
                obj.path = strrep(mrio_phase,'\','/');
                if ~strcmp(obj.path(end),'/'), obj.path=[obj.path '/']; end;
                obj.base_path = obj.path;
                
                i = strfind(obj.path,'/Phase'); mrio_phase = str2double(obj.path(i+6:i+8));
                i = strfind(obj.path,'/Loop'); mrio_loop = str2double(obj.path(i+5:i+7));
                if isnan(mrio_phase), obj.isEORA = 0;  end;
                flags='';
                
            end;
            
            % Normal constructor
            if signature==1 || signature==2
                
                flags = split(' ', lower(flags));
                flag_nolabs = any(strncmp(flags,'nolabs',6));
                flag_natsatcla = any(strcmp(flags,'natsatcla'));
                flag_usecache = any(strcmp(flags,'usecache'));
                if any(strcmp(flags,'nocache')), warning(0,'flag ''nocache'' in tree_structure() is deprecated'); end;
                flag_quiet= any(strcmp(flags,'quiet'));
                flags_deletecache = any(strcmp(flags,'deletecache'));
                
                
                obj.phase = mrio_phase;
                obj.loop = mrio_loop;
                obj.inning = obj.loop;
                obj.phasestr=num2str(obj.phase); obj.loopstr=num2str(obj.loop);
                
                obj.isCCC = obj.loop >250  & obj.loop<500;
                obj.isCCCCJ = obj.loop >500& obj.loop<750;
                obj.base_loop = obj.loop; if obj.isCCC, obj.base_loop = obj.loop-250; end; if obj.isCCCCJ, obj.base_loop= obj.loop-500; end;
                obj.base_loopstr = num2str(obj.base_loop);
                
                
                if ~exist('findloop'),
                    obj.path = [pwd filesep];
                    obj.sat_path=obj.path;
                else
                    if obj.isEORA
                        [obj.path, ~, obj.sat_path] = findloop(mrio_phase, mrio_loop, handles);
                    end;
                end;
                
                if isempty(obj.path),
                    error(['Could not find path to experiment ' num2str(mrio_phase) '.' num2str(mrio_loop)]);
                end;
                
                obj.mrio.pathstr = obj.path;
                obj.sat.pathstr = obj.sat_path;
                
                % Tree path
                obj.mrio.treepathstr = [obj.path 'TreeStructure/'];
                obj.sat.treepathstr = [obj.sat_path 'TreeStructure/'];
                
                
                obj.base_path = obj.path;
                if obj.isCCC || obj.isCCCCJ, obj.base_path = strrep(obj.base_path,sprintf('Loop%03d',obj.loop),sprintf('Loop%03d',obj.base_loop)); end;
                obj.base_sat_path = strrep(obj.base_path,'/Loop','/Inning');
                
                try
                    
                    % Sometimes users accidentally provide
                    % '/my/path/TreeStructure/' as the path. Here we
                    % correct this so that path is just '/my/path/'
                    if strcmpi(obj.path(end-12:end),'TreeStructure'), obj.path = obj.path(1:end-1);  end;
                    if strcmpi(obj.path(end-13:end),'TreeStructure/'),obj.path = obj.path(1:end-14);  end;
                    
                    
                    % Get d Path
                    obj.tree_path = [obj.path,'TreeStructure'];
                    
                    
                    % Handle cached tree_structure.mat files
                    if flags_deletecache && exist([obj.tree_path '/tree_structure.mat'],'file'),
                        delete([obj.tree_path '/tree_structure.mat']);
                    end;
                    if flag_usecache && exist([obj.tree_path '/tree_structure.mat'],'file')
                        try
                            dispIf(~flag_quiet, 'tree_structure is loading cached tree_structure.mat');
                            tmp = load([obj.tree_path '/tree_structure.mat']); obj = tmp.obj;
                            
                            % For old files without the hash field, the hash check should always fail:
                            if ~isfield(obj,'private_treestrucfiles_cachedhashcode'), obj.private_treestrucfiles_cachedhashcode='-1'; end;
                            if ~isfield(obj,'isEORA'), obj.isEORA=1; end; 
                            return;
                            
                            
                            %% THE FOLLOWING LINES ARE DEPRECATED.
                            % I tried to test whether the cached file is dirty. But the HashcodeFromDirectorylisting() function
                            % is so slow (2 seconds, because it uses dir()) that when I added this code there is no gain
                            % from using a cached .mat file.
                            % Has the hash changed? If so, this cached file is dirty
                            if strcmp(obj.private_treestrucfiles_cachedhashcode, HashcodeFromDirectorylisting(obj.tree_path))
                                return; % Hash is unchanged. We're OK.
                            else
                                % This cache file is dirty. Delete it.
                                delete([obj.tree_path '/tree_structure.mat']);
                            end;
                        catch E
                            getReport(E);
                            % fail silently
                        end
                    end;
                    
                    
                    obj.tree_satpath = [obj.sat_path,'/TreeStructure/harmonized/'];
                    obj.tree_satpath_orig  = [obj.sat_path,'/','TreeStructure/'];
                    if ~exist(obj.tree_satpath, 'dir'), obj.tree_satpath = obj.tree_satpath_orig; end;
                    if flag_natsatcla, obj.tree_satpath = obj.tree_satpath_orig; end;
                    
                    % Row dimensions
                    fn = ff(obj.tree_path,'TreeStructure',4,'Rowgrandchildren',6); if strcmpi(fn{1},'None') fn = ff(obj.tree_path,'Rowgrandchildren',0); end;
                    tmp = cellread([obj.tree_path,'/',fn{1}]);
                    obj.row = cellstr2num(tmp(:,2:end));
                    obj.mrio.row = obj.row;
                    % Row Classification
                    fn = ff(obj.tree_path,'TreeStructure',4,'RowClassification',6);  if strcmpi(fn{1},'None') fn = ff(obj.tree_path,'RowClassification',0); end;
                    obj.row_cls = cellread([obj.tree_path,'/',fn{1}]); obj.row_d_data=obj.row_cls; obj.row_tree_data = obj.row_cls;
                    obj.mrio.row_cls = obj.row_cls;
                    
                    
                    % Col dimensions
                    fn = ff(obj.tree_path,'TreeStructure',4,'Columngrandchildren',6);  if strcmpi(fn{1},'None') fn = ff(obj.tree_path,'Columngrandchildren',0); end;
                    tmp = cellread([obj.tree_path,'/',fn{1}]);
                    obj.col = cellstr2num(tmp(:,2:end));
                    obj.mrio.col=obj.col;
                    % Col Classification
                    fn = ff(obj.tree_path,'TreeStructure',4,'ColumnClassification',6);  if strcmpi(fn{1},'None') fn = ff(obj.tree_path,'ColumnClassification',0); end;
                    obj.col_cls = cellread([obj.tree_path,'/',fn{1}]); obj.col_d_data=obj.col_cls; obj.col_tree_data = obj.col_cls;
                    obj.mrio.col_cls = obj.col_cls;
                    
                    
                    
                    % Satellite rows
                    fn = ff(obj.tree_satpath ,'TreeStructure',4,'Rowgrandchildren',6);  if strcmpi(fn{1},'None') fn = ff(obj.tree_path,'Satgrandchildren',0); end;
                    if strcmp(fn{1},'None'),
                        obj.row_sat = [];
                        obj.sat.row = [];
                        obj.sat.row_cls=[];
                        obj.row_sat_cls = [];
                        obj.Qdim = 0;
                        obj.NINDICATORS = 0;
                        
                        obj.indexQ = cell(0);
                        
                    else
                        if exist([obj.tree_satpath fn{1}],'file'),
                            tmp = cellread([obj.tree_satpath fn{1}]);
                        else
                            tmp = cellread([obj.tree_path '/' fn{1}]);
                        end
                        
                        obj.row_sat = cellstr2num(tmp(:,2:end));
                        obj.sat.row = obj.row_sat;
                        obj.sat.col = obj.mrio.col(1:end-1, :);
                        if ~flag_natsatcla, obj.row_sat = obj.row_sat(1,:)'; end;
                        %obj.row_sati = [0, cumsum(obj.row_sat)'];
                        obj.NINDICATORS = size(obj.row_sat,1);
                        if flag_natsatcla, obj.NINDICATORS = size(obj.row_sat,2); end;
                        
                        % Row Sat Classification
                        fn = ff(obj.tree_satpath ,'TreeStructure',4,'RowQClassification',6);  if strcmpi(fn{1},'None') fn = ff(obj.tree_path,'RowQClassification',0); end;
                        if exist([obj.tree_satpath ,fn{1}],'file'),
                            tmp = cellread([obj.tree_satpath ,fn{1}]);
                        else
                            tmp = cellread([obj.tree_path '/' fn{1}]);
                        end
                        obj.indicator = tmp(:, 2:2:end);
                        if flag_natsatcla,
                            obj.row_sat_cls = tmp(:, 2:end);
                        else
                            obj.row_sat_cls = cell(obj.NINDICATORS,2);
                            obj.row_sat_cls(:,1) = tmp(1, 2:2:obj.NINDICATORS*2+1); %indicator code
                            obj.row_sat_cls(:,2) = tmp(1, 3:2:obj.NINDICATORS*2+1);  %classification
                            
                            obj.indexQ = cell(obj.NINDICATORS, 1);
                            tmp2 = [0, cumsum(obj.row_sat)']';
                            for i=1:obj.NINDICATORS
                                obj.indexQ{i} = tmp2(i)+1:tmp2(i+1);
                            end
                        end;
                        obj.sat.row_cls = obj.row_sat_cls;
                        
                        obj.Qdim = sum(sum(obj.row_sat));
                        
                        
                    end
                    
                    % Country
                    obj.countries = upper(obj.row_cls(:,1));
                    obj.country_acronyms = obj.countries;
                    wt3([obj.tree_path '/a3codes.txt'],obj.countries); %%DDMX
                    
                    
                    % How many sheets (default =5)
                    try
                        fn = ff(obj.tree_path,'TreeStructure',4,'Margins',6); if strcmpi(fn{1},'None') fn = ff(obj.tree_path,'Margins',0); end;
                        obj.sheets = dlmread([obj.tree_path,'/',fn{1}]);
                        obj.sat.margin = 1;
                        obj.mrio.margin = obj.sheets;
                    catch E
                        disp(getReport(E));
                        boldwarning('Could not find number of margins for tree. Defaulting to 5');
                        obj.sheets=5;
                    end;
                    
                    % Year Range
                    try
                        fn = ff(obj.tree_path,'TreeStructure',4,'YearRange',6); if strcmpi(fn{1},'None') fn = ff(obj.tree_path,'YearRange',0); end;
                        tmp = dlmread([obj.tree_path,'/',fn{1}]);
                        obj.years = tmp(1):tmp(2);
                    catch E
                        disp(getReport(E));
                        boldwarning('Could not find year range for tree. Defaulting to [2000]');
                        obj.years = 2000;
                    end;
                    obj.year=obj.years; %only exists for backwards compatiblity
                    obj.year_range = obj.years; %ditto
                    
                    
                    % Data Standard Number
                    fn = ff(obj.tree_path,'TreeStructure',4,'DataNumber',6);
                    if strcmp(fn{1},'None')
                        obj.DSN = -1;
                    else
                        obj.DSN = dlmread([obj.tree_path,'/',fn{1}]);
                    end
                    
                    obj.Tdim = sum(sum(obj.col(:,1:2)));
                    obj.Ydim = sum(sum(obj.col(:,3)));
                    obj.Vdim = sum(sum(obj.col(:,3)));
                    obj.Mdim = obj.Tdim + obj.Ydim;
                    obj.NCOUNTRIES = size(obj.row,1);
                    obj.country_number = obj.NCOUNTRIES;
                    if strcmpi(obj.countries(end, 1), 'row'),
                        obj.country_number_without_row = obj.country_number - 1;
                    else
                        obj.country_number_without_row = obj.country_number;
                    end;
                    
                    
                    obj.indexT = cell(obj.NCOUNTRIES, 1);
                    tmp = sum(obj.col(:,1:2),2); % country Tdims
                    tmp2 = [0, cumsum(tmp)']';
                    for i=1:obj.NCOUNTRIES
                        obj.indexT{i} = tmp2(i)+1:tmp2(i+1);
                        if obj.col(i,1)>0 && obj.col(i,2)>0, % SUT?
                            obj.indexTforSat{i} = tmp2(i)+1:tmp2(i)+obj.col(i,1); %Just ind columns
                            obj.indexTforUse{i} = tmp2(i)+1+obj.col(i,1):tmp2(i)+obj.col(i,1)+obj.col(i,2); % just com columns
                        else
                            obj.indexTforSat{i} =  obj.indexT{i}; %normal
                            obj.indexTforUse{i} = obj.indexT{i};
                        end;
                    end
                    
                    obj.indexYV = cell(obj.NCOUNTRIES, 1);
                    tmp = sum(obj.col(:,3),2); % country Tdims
                    tmp2 = [0, cumsum(tmp)']';
                    for i=1:obj.NCOUNTRIES
                        obj.indexYV{i} = tmp2(i)+1:tmp2(i+1);
                    end
                    
                    obj.indexM = cell(obj.NCOUNTRIES, 1);
                    tmp = sum(obj.col(:,1:3),2); % country Mdims
                    tmp2 = [0, cumsum(tmp)']';
                    for i=1:obj.NCOUNTRIES
                        obj.indexM{i} = tmp2(i)+1:tmp2(i+1);
                        if obj.col(i,1)>0 && obj.col(i,2)>0, % SUT?
                            obj.indexMforSat{i} = [tmp2(i)+1:tmp2(i)+obj.col(i,1),  (1:6)+tmp2(i)+obj.col(i,1)+obj.col(i,2)]; %Just ind columns and FD columns
                        else
                            obj.indexMforSat{i} =  obj.indexM{i}; %normal
                        end;
                    end
                    
                    
                    
                    % IO table types (CIOT/IIOT/SUT)
                    obj.iotype = cell(obj.NCOUNTRIES,1);
                    obj.coIsSUT= zeros(obj.NCOUNTRIES,1);
                    for i=1:obj.NCOUNTRIES,
                        obj.iotype{i} = 'IIOT';
                        if obj.row(i,1) ==0, obj.iotype{i} = 'CIOT'; end;
                        if obj.row(i,1)>0 && obj.row(i,2)>0, obj.iotype{i} = 'SUT'; obj.coIsSUT(i)=1; end;
                    end;
                    obj.type = cell(obj.NCOUNTRIES, 1);
                    obj.type(all(obj.mrio.row(:, 1), 2), 1) = {'IIOT'};
                    obj.type(all(obj.mrio.row(:, 2), 2), 1) = {'CIOT'};
                    obj.type(all(obj.mrio.row(:, 1:2), 2), 1) = {'SUT'};
                    
                    
                    % Logical vector isSUT
                    obj.isSUT = zeros(obj.Tdim,1);
                    for i=1:obj.NCOUNTRIES, obj.isSUT(obj.indexT{i}) = obj.row(i,1)>0 & obj.row(i,2)>0; end;
                    
                    
                    % Load the sector labels
                    try
                        % Create them using Java if they don't exist already
                        if ~exist([obj.base_path '/TreeStructure/index_t.csv'],'file') && ~flag_nolabs,
                            if obj.DSN==-1,
                                obj = create_NonEora_indexfiles(obj);
                            else
                                unix(['/import/penelope1/danm/treeonly ' obj.phasestr ' ' obj.loopstr]);
                            end
                        end;
                        obj.secLabsT = cell(obj.Tdim,1);
                        obj.secLabsY = cell(obj.Ydim,1);
                        obj.secLabsV = cell(obj.Vdim,1);
                        obj.secLabsQ = cell(obj.Qdim,1);
                        obj.secLabsM = cell(obj.Mdim,1);
                        obj.secLabsMrows=obj.secLabsM; obj.secLabsMcols=obj.secLabsM;
                        
                        obj.labsT = cell(obj.Tdim,4);
                        for i=1:obj.NCOUNTRIES, obj.labsT(obj.indexT{i},2) = repmat( cellstr(obj.countries{i}), length(obj.indexT{i}),1); end;
                        obj.labsV = cell(obj.Vdim, 4);
                        for i=1:obj.NCOUNTRIES, obj.labsV(obj.indexYV{i},2) = repmat( cellstr(obj.countries{i}), length(obj.indexYV{i}),1); end;
                        obj.labsY = cell(obj.Ydim, 4);
                        for i=1:obj.NCOUNTRIES, obj.labsY(obj.indexYV{i},2) = repmat( cellstr(obj.countries{i}), length(obj.indexYV{i}),1); end;
                        obj.labsM = cell(obj.Mdim, 4);
                        for i=1:obj.NCOUNTRIES, obj.labsM(obj.indexM{i},2) = repmat( cellstr(obj.countries{i}), length(obj.indexM{i}),1); end;
                        %obj.labsMrows =strrep( obj.labsM,'Final demand','Primary input');
                        %obj.labsMcols = obj.labsM;
                        
                        if exist([obj.path '/TreeStructure/index_t.csv'],'file') && ~flag_nolabs,
                            if exist([obj.path '/TreeStructure/index_t.csv'],'file'), obj.secLabsT = cellread([obj.path '/TreeStructure/index_t.csv']); obj.labsT = obj.secLabsT(2:end,[2,3,4,5]); obj.secLabsT = obj.secLabsT(2:end,end); end;
                            if exist([obj.path '/TreeStructure/index_y.csv'],'file'), obj.secLabsY = cellread([obj.path '/TreeStructure/index_y.csv']); obj.labsY = obj.secLabsY(2:end,[2,3,4,5]); obj.secLabsY = obj.secLabsY(2:end,end); end;
                            if exist([obj.path '/TreeStructure/index_v.csv'],'file'), obj.secLabsV = cellread([obj.path '/TreeStructure/index_v.csv']); obj.labsV = obj.secLabsV(2:end,[2,3,4,5]); obj.secLabsV = obj.secLabsV(2:end,end); end;
                            if exist([obj.path '/TreeStructure/index_m.csv'],'file'), obj.secLabsM = cellread([obj.path '/TreeStructure/index_m.csv']); obj.labsM = obj.secLabsM(2:end,[2,3,4,5]); obj.secLabsM = obj.secLabsM(2:end,end); obj.secLabsMrows =strrep(obj.secLabsM,'Final demand','Primary input'); obj.secLabsMcols=obj.secLabsM; end;
                            if ~flag_natsatcla,
                                if exist([obj.base_path '/TreeStructure/index_q.csv'],'file'), obj.secLabsQ = cellread([obj.base_path '/TreeStructure/index_q.csv']); obj.labsQ = obj.secLabsQ(2:end,[3,4]); obj.secLabsQ = obj.secLabsQ(2:end,end); else boldwarning('No sector labels found for satellite block'); end;
                            end;
                        else
                        end;
                    catch EE
                        disp(['Could not find secLabs files index_* in ' obj.tree_path]);
                        disp(getReport(EE));
                    end
                    
                    
                    
                    
                    % Save cached copy in .mat format if we haven't already done so
                    if (isempty(flags) || isempty(flags{1})) && ~exist([obj.tree_path '/tree_structure.mat'],'file'),
                        save([obj.tree_path '/tree_structure.mat'],'obj');
                        %disp(['Saved ' obj.tree_path '/tree_structure.mat']);
                    end;
                    
                catch E
                    disp(['Could not construct tree from ' obj.tree_path]);
                    disp(getReport(E));
                    obj=[];
                end;
                
                
                
            else
                error('Invalid arguments passed to atree() constructor');
            end;
        end; %end tree_structure constructor
        
        
        
        
        
        
        %
        function tree = rd_sec_name(tree, pathstr)
            %
            pathstr = [pathstr, '/', 'data_standards'];
            %
            for i = 1:tree.country_number_without_row,
                %
                country_pathstr = [pathstr, '/', upper(tree.country_acronyms{i})];
                %
                tree.sector_name.(tree.country_acronyms{i}).IND ...
                    = cellread([country_pathstr, '/', rd(ff(country_pathstr, 'Industries', 5),1)]);
                tree.sector_name.(tree.country_acronyms{i}).COM ...
                    = cellread([country_pathstr, '/', rd(ff(country_pathstr, 'Commodities', 5),1)]);
                tree.sector_name.(tree.country_acronyms{i}).FD ...
                    = cellread([country_pathstr, '/', rd(ff(country_pathstr, 'FinalDemand', 5),1)]);
                tree.sector_name.(tree.country_acronyms{i}).PI ...
                    = cellread([country_pathstr, '/', rd(ff(country_pathstr, 'PrimaryInputs', 5),1)]);
            end;
        end
        %
        function [whole_sector_name complete_sector_label]= mk_whole_sector_name(tree, dim)
            %
            whole_sector_name = cell(sum(tree.mrio.row(:)), 1);
            complete_sector_label = cell(sum(tree.mrio.row(:)), 3);
            %
            ii = 0;
            %
            ENT = {'IND', 'COM'}; if dim == 1, ENT = [ENT, {'PI'}]; else ENT = [ENT, {'FD'}]; end
            %
            for i = 1:tree.country_number_without_row,
                for j = 1:length(ENT),
                    %
                    name = tree.sector_name.(tree.country_acronyms{i}).(ENT{j});
                    if (~isempty(name))
                        complete_sector_label(ii+1:ii+length(name),1) = repmat(tree.country_acronyms(i),length(name),1);
                        complete_sector_label(ii+1:ii+length(name),2) = repmat(ENT(j),length(name),1);
                        for kk=1:length(name), complete_sector_label{ii+kk,3}=name{kk};end;
                    end;
                    whole_sector_name(ii+1:ii+length(name)) = name; ii = ii + length(name);
                end;
            end;
        end
        
        
        
        
        
        function [country_index, entity_index, sector_index] = det_index(tree, country, entity, sector)
            %
            country_index=[]; entity_index=[]; sector_index=[];
            if isempty(tree.sector_name),
                warning('please run tree_structure.rd_sect_name first before running tree_structure.det_index');
                return;
            end;
            country_index = find(strncmpi(tree.country_acronyms, country, length(country)));
            if isempty(country_index), return; end;
            entity_index = find(strcmp({'IND', 'COM'}, entity));
            sector=strtrim(sector);
            sector_index = find(strncmpi(tree.sector_name.(country).(entity), sector,length(sector)));
            boldwarningIf(isempty(sector_index),['WARNING: tree_structure.det_index count not find sector [''' sector '''] for ' country '/' entity]);
        end
        %
        function dim = getTDim(obj)
            dim = obj.Tdim;
        end;
        %
        function dim = getYDim(obj)
            dim = obj.Ydim;
        end;
        %
        function dim = getVDim(obj)
            dim = obj.Vdim;
        end;
        %
        function dim = getQDim(obj)
            dim = obj.Qdim;
        end;
        %
        function dim = getMDim(obj)
            dim = obj.Tdim + obj.Ydim;
        end;
        %
        % Call this if you change .col or .row entries (e.g if you add or remove a country)!
        function obj2 = recalcInds(obj)
            obj2=obj;
            obj2.Tdim = sum(sum(obj2.col(:,1:2)));
            obj2.Ydim = sum(sum(obj2.col(:,3)));
            obj2.Vdim = sum(sum(obj2.col(:,3)));
            obj2.Mdim = obj2.Tdim + obj2.Ydim;
            obj2.NCOUNTRIES = size(obj2.row,1);
            
            obj2.indexT = cell(obj2.NCOUNTRIES, 1);
            tmp = sum(obj2.col(:,1:2),2); % country Tdims
            tmp2 = [0, cumsum(tmp)']';
            for i=1:obj2.NCOUNTRIES
                obj2.indexT{i} = tmp2(i)+1:tmp2(i+1);
                if obj2.col(i,1)>0 && obj2.col(i,2)>0, % SUT?
                    obj2.indexTforSat{i} = tmp2(i)+1:tmp2(i)+obj2.col(i,1); %Just ind columns
                else
                    obj2.indexTforSat{i} =  obj2.indexT{i}; %normal
                end;
            end
            
            obj2.indexYV = cell(obj2.NCOUNTRIES, 1);
            tmp = sum(obj2.col(:,3),2); % country Tdims
            tmp2 = [0, cumsum(tmp)']';
            for i=1:obj2.NCOUNTRIES
                obj2.indexYV{i} = tmp2(i)+1:tmp2(i+1);
            end
            
            obj2.indexM = cell(obj2.NCOUNTRIES, 1);
            tmp = sum(obj2.col(:,1:3),2); % country Mdims
            tmp2 = [0, cumsum(tmp)']';
            for i=1:obj2.NCOUNTRIES
                obj2.indexM{i} = tmp2(i)+1:tmp2(i+1);
                if obj2.col(i,1)>0 && obj2.col(i,2)>0, % SUT?
                    obj2.indexMforSat{i} = [tmp2(i)+1:tmp2(i)+obj2.col(i,1),  (1:6)+tmp2(i)+obj2.col(i,1)+obj2.col(i,2)]; %Just ind columns and FD columns
                else
                    obj2.indexMforSat{i} =  obj2.indexM{i}; %normal
                end;
            end
            
            
            
            % IO table types (CIOT/IIOT/SUT)
            obj2.iotype = cell(obj2.NCOUNTRIES,1);
            obj2.coIsSUT= zeros(obj2.NCOUNTRIES,1);
            for i=1:obj2.NCOUNTRIES,
                obj2.iotype{i} = 'IIOT';
                if obj2.row(i,1) ==0, obj2.iotype{i} = 'CIOT'; end;
                if obj2.row(i,1)>0 && obj2.row(i,2)>0, obj2.iotype{i} = 'SUT'; obj2.coIsSUT(i)=1; end;
            end;
            
            % Logical vector isSUT
            obj2.isSUT = zeros(obj2.Tdim,1);
            for i=1:obj2.NCOUNTRIES, obj2.isSUT(obj2.indexT{i}) = obj2.row(i,1)>0 & obj2.row(i,2)>0; end;
            
        end; %recalcInds()
        
        
        
        
        %
        function [ qrows ] = findRowindicesQByIndicatorName( obj, indic)
            %FINDROWINDICESQBYINDICATORNAME (qrows) Find the row indices of indicator like 'I-GHG-TOTAL' or 'I-GHG-*'. Returns a vector of row indices, or [] if not found.
            
            qrows= [];
            
            iCodes = obj.row_sat_cls(:,1);
            iNames = obj.row_sat_cls(:,2);
            
            if strfind(indic, '*'),
                indic = ['^' strrep(indic,'*','.+') '$'];
                i = ~cellfun(@isempty,regexpi(iCodes, indic,'start'));
                i=find(i);
            else
                i = find(strcmp(iCodes, indic));
            end;
            if ~isempty(i)
                qrows = horzcat(obj.indexQ{i});
                return;
            end;
            
            
            if strfind(indic, '*'),
                indic = ['^' strrep(indic,'*','.+') '$'];
                i = ~cellfun(@isempty,regexpi(iNames, indic,'start'));
                i=find(i);
            else
                i = find(strcmp(iNames, indic));
            end;
            if ~isempty(i)
                qrows = horzcat(obj.indexQ{i});
                return;
            end;
            
            return;
            
        end; % end findRowindicesQByIndicatorName()
        
        
        
        
        function [ idx ] = a3( obj, a3, verbose)
            % idx = tr.a3('FRA'); Finds the position of country a3. For example, tr.a3('AFG') = 1
            if ~exist('verbose','var'), verbose=0; end;
            
            
            % Valid input?
            if iscell(a3), a3=char(a3{1}); end;
            if ~ischar(a3) || length(a3)~=3
                idx=0;
                if verbose, warning('bad input to atree.indexOf(). Provide a country a3 code'); end;
                return;
            end;
            
            
            % Case insensitive search of the first 3 characters in the 'a3' string
            idx = strncmpi(obj.countries,a3,3);
            
            
            % Found zero matches
            if sum(idx) == 0
                idx=0;
                if verbose, warning(['Did not find ' a3 ' in this experiment']); end;
                return;
            end;
            
            % Found multiple matches
            if sum(idx) > 1
                idx=0;
                if verbose, warning(['Found ' num2str(sum(idx)) ' matches for ' a3]); end;
                return;
            end;
            
            % Found 1 match
            idx = find(idx);
            
        end; % a3()
        
        
        
        function [ tf ] = a3exists( obj, a3)
            %A3EXISTS Returns true if and only if the a3 code is valid and names a
            %country part of this experiment
            
            % Convert from cell to char if needed
            if iscell(a3), a3=char(a3{1}); end;
            
            % Valid a3 code?
            if ~ischar(a3) || length(a3)~=3
                tf=0;
                return;
            end;
            
            % Exists?
            idx = strncmpi(obj.countries,a3,3);
            tf = sum(idx)==1;
        end; % a3exists()
        
        
        
        
        function [ ret ] = addRoW( obj, addFD )
            %ADDROW Usage: tr=tr.addRoW(1). Adds a RoW country. If optional argument is true, adds 6 PI and
            % FD rows/cols.
            if ~strcmpi(obj.countries(end),'ROW'),
                idx = obj.NCOUNTRIES+1;
                
                obj.NCOUNTRIES = obj.NCOUNTRIES + 1;
                
                obj.row_cls{idx,1} = 'ROW';
                obj.row_cls{idx,2} = 'TOTAL';
                obj.row_cls{idx,3} = '';
                obj.row_cls{idx,4} = '';
                
                obj.col_cls{idx,1} = 'ROW';
                obj.col_cls{idx,2} = 'TOTAL';
                obj.col_cls{idx,3} = '';
                obj.col_cls{idx,4} = '';
                
                obj.countries(idx) = 'ROW';
                
                obj.row(idx,:) = [1, 0, 0];
                obj.col(idx,:) = [1, 0, 0];
                
                obj.Tdim = obj.Tdim + 1;
                obj.Mdim = obj.Mdim + 1;
                
            end;
            
            idx = obj.NCOUNTRIES;
            
            if exist('addFD','var') && addFD
                obj.col_cls{idx,4} = 'ISA-FD';
                obj.row_cls{idx,4} = 'ISA-PI';
                obj.row(idx,:) = [1, 0, 6];
                obj.col(idx,:) = [1, 0, 6];
                
                obj.Ydim = obj.Ydim + 6;
                obj.Vdim = obj.Vdim + 6;
                obj.Mdim = obj.Mdim + 6;
                
            end;
            
            ret = obj;
            
            
            
        end; % end addRoW()
        
        
        
        
        function clearCachedMATfile(obj)
            % Deletes the 'tree_structure.mat' cachefile (if it exists)
            % The cached file is used if it exists and if the 'usecache'
            % flag is passed to the constructor.
            if exist([obj.tree_path '/tree_structure.mat'],'file'), delete([obj.tree_path '/tree_structure.mat']); end;
        end
        
        
        
        
        
        
        function B = matchThisMRIO(destTr, A, dim, origTr, verbose)
            % Restructures A (a matrix or vector) from an MRIO described by
            % origTr along dimension DIM to match this MRIO.
            %
            % Use:   B = tr.matchThisMRIO(A, dim, origTr, verbose)
            %
            % If size(A,dim)==origTr.NCOUNTRIES this function will delete
            % countries or add all-zero countries to create B. These will
            % be inserted/deleted as single columns or rows (depending on dim).
            %
            % If size(A,dim)==origTr.Tdim, this function will operate the
            % same but will add/remove the entire block of rows/cols for that
            % country.
            %
            % if dim==1, treat rows. If dim==2, treats cols. if dim==3, treats both rows and cols.
            %
            % Specify verbose=0 to suppress commentary on what was added/removed.
            
            if ~exist('verbose','var'), verbose=1; end;
            
            % Handle row+col case by recursively calling myself twice
            if dim==3,
                B = destTr.matchThisMRIO(A,1, origTr, verbose);
                B = destTr.matchThisMRIO(B,2, origTr, 0);
                return;
            end;
            
            % If this tree and original tree are identical, our job here is done.
            if origTr.NCOUNTRIES==destTr.NCOUNTRIES && nnz(origTr.row - destTr.row)==0
                B=A;
                return;
            end
            if min(size(A))==1, if size(A,1)==1, dim=2; else dim=1; end; end; % For vectors, ensure dim is always the non-singleton dimension
            
            
            % Are we operating with 1 row/col per country, or with a block
            % of rows (TDIM) for each country?
            DONCOUNTRIES=1;
            DOTDIM=2;
            if size(A,dim) == origTr.NCOUNTRIES, mode=DONCOUNTRIES; else mode=DOTDIM; end;
            
            if dim==1,
                if mode==1
                    B = zeros(destTr.NCOUNTRIES, size(A,1));
                else
                    B = zeros(destTr.Tdim, size(A,1));
                end
            elseif dim==2
                if mode==1,
                    B = zeros(size(A,1), destTr.NCOUNTRIES);
                else
                    B = zeros(size(A,1), destTr.Tdim);
                end
            end
            
            for coo=1:origTr.NCOUNTRIES
                cod = destTr.a3(origTr.countries{coo});
                if cod==0, continue; end; % If this country is missing in the destination, dont copy the values from A to B
                if dim==1,
                    if mode==DONCOUNTRIES
                        B(cod,:) = A(coo,:);
                    else
                        B(destr.indexT{cod},:) = A(origTr.indexT{coo},:);
                    end
                else
                    if mode==DONCOUNTRIES
                        B(:,cod) = A(:,coo);
                    else
                        B(:,destr.indexT{cod}) = A(:,origTr.indexT{coo});
                    end
                end;
            end
            
            if verbose,
                [aa]=ismember(destTr.countries, origTr.countries);
                dispIf(any(~aa), ['matchThisMRIO() says: these countries were missing in the input data: ' join(', ', destTr.countries(~aa)')]);
                [aa]=ismember(origTr.countries, destTr.countries);
                dispIf(any(~aa), ['matchThisMRIO() says: these countries were removed from the input data: ' join(', ', origTr.countries(~aa)') ', which together contained ' num2str(100 - sum(B(:)) / sum(A(:))*100)  '% of the total input value']);
            end;
            
        end % matchThisMRIO
        
        
        
        
        function t = collapseTdim(tr, T, dim)
            % t=tr.collapseTdim(T, dim) collapses maxtrix having dimension
            % 'dim'= tr.Tdim to have just 1 row/col per country
            % T a matrix with either rowdim or coldim of Tdim
            % which dimension to compress. 1=collapse rows, 2= collapse cols
            
            if dim==1,
                t = zeros(tr.NCOUNTRIES, size(T,2));
            else
                t = zeros(size(T,1), tr.NCOUNTRIES);
            end;
            
            idx = 1;
            for co=1:tr.NCOUNTRIES
                coTdim = sum(tr.row(co,1:2), 2);
                if dim==1,
                    t(co, :) = sum(  T(idx:idx+coTdim-1, :), 1);
                else
                    t(:, co) = sum(  T(:, idx:idx+coTdim-1), 2);
                end;
                idx = idx + coTdim;
            end
        end %collapseTdim
        
        
        function q = collapseQdim(tr, Q)
            % q=tr.collapseQdim(Q) collapses a Qdim x Tdim size matrix to a qdim x Tdim sized matrix where
            % qdim is the number of indicators (~51), not the number of indicator-sectors
            % (~1794)
            
            nind = tr.NINDICATORS; %(size(tr.sat_row_cls,2)-1) / 2; % number of indicators
            q = zeros(nind, size(Q,2));
            rowinds = [0; cumsum(tr.row_sat)]; rowinds = rowinds+1;
            for ind=1:nind
                q(ind,:) = sum( Q(rowinds(ind):rowinds(ind+1)-1, :),1);
            end
        end %collapseQdim
        
        
        
        function y = collapseYdim(tr, Y, dim)
            % y=tr.collapseYdim(Y, dim) collapses maxtrix having dimension 'dim'= tr.Ydim
            % Y a matrix with either rowdim or coldim of Ydim
            % which dimension to compress. 1=collapse rows, 2= collapse cols
            
            if dim==1,
                y = zeros(tr.NCOUNTRIES, size(Y,2));
            else
                y = zeros(size(Y,1), tr.NCOUNTRIES);
            end;
            
            idx = 1;
            for co=1:tr.NCOUNTRIES
                coYdim = tr.row(co,3);
                
                % Correct for missing or short RoW PI/FD case
                if co==tr.NCOUNTRIES
                    if size(Y,1) >= (tr.NCOUNTRIES-1) * 6 && size(Y,1) >= (tr.NCOUNTRIES) * 6,  Y = vertcat(Y, zeros((tr.NCOUNTRIES*6)-size(Y,1), size(Y,2))); end;
                    if size(Y,2) >= (tr.NCOUNTRIES-1) * 6 && size(Y,2) >= (tr.NCOUNTRIES) * 6,  Y = horzcat(Y, zeros(size(Y,1), (tr.NCOUNTRIES*6)-size(Y,2))); end;
                end; %RoW case
                
                if dim==1,
                    y(co, :) = sum(  Y(idx:idx+coYdim-1, :), 1);
                else
                    y(:, co) = sum(  Y(:, idx:idx+coYdim-1), 2);
                end;
                idx = idx + coYdim;
            end
        end %collapseYdim
        
    end;% end methods section
    
end % classdef tree_structure










function tr = create_NonEora_indexfiles(o)
% Creates tr.labsT, and writes index_t.csv, etc, for MRIOs other than Eora.
tr = o;

classifations_fn = dir([tr.tree_path '/classifications/']);
cla = struct;
for i=1:length(classifations_fn)
    fn = classifations_fn(i).name;
    if fn(1) == '.', continue; end;
    if strcmpi(fn,'None'), continue; end;
    cn = strrep(fn,'-','_'); cn = cn(1:end-4);
    cla.(cn) = cellread([tr.tree_path '/classifications/' fn]);
end
cla.EMPTY = {}; % 0-sector classification
cla.TOTAL= {'TOTAL'}; % single-sector classificaiton

tr.labsT = cell(sum(sum(tr.row(:,1:2))), 4); % Fullname, A3, Ind/Com, Sectorname
tr.labsY = cell(sum(sum(tr.row(:,3))), 4); % Fullname, A3, 'Final Demand', Sectorname
tr.labsV = cell(sum(sum(tr.row(:,3))), 4); % Fullname, A3, 'Primary Input', Sectorname
tr.labsM = cell(sum(sum(tr.row(:,1:3))), 4); % Fullname, A3, Ind/Com, Sectorname
tr.labsQ = cell(tr.Qdim, 2); % Full indicator name, line item name
for co=1:tr.NCOUNTRIES
    
    for e=1:2,
        mycla = strrep(tr.row_cls{co,e+1},'-','_');
        if tr.isSUT(co),
            if e==1,
                tr.labsT(tr.indexTforSat{co},4) = cla.(mycla);
                tr.labsT(tr.indexTforSat{co},3) = {'Industries'};
            else
                tr.labsT(tr.indexTforUse{co},4) = cla.(mycla);
                tr.labsT(tr.indexTforUse{co},3) = {'Commodities'};
            end
        else % Not a SUT table
            if e==1 && tr.row(co,1)>0, %Handle IIOT
                tr.labsT(tr.indexT{co},4) = cla.(mycla);
                tr.labsT(tr.indexT{co},3) = {'Industries'};
            elseif e==2 && tr.row(co,2)>0 % Handle CIOT
                tr.labsT(tr.indexT{co},4) = cla.(mycla);
                tr.labsT(tr.indexT{co},3) = {'Commodities'};
            end
        end
    end
    tr.labsT(tr.indexT{co},2) = {upper(tr.row_cls{co,1})}; %A3 code
    tr.labsT(tr.indexT{co},1) = {upper(tr.row_cls{co,1})}; %country name
    
    % Handle PI
    picla = strrep(tr.row_cls{co,4},'-','_');
    tr.labsV(tr.indexYV{co},4) =  cla.(picla);
    tr.labsV(tr.indexYV{co},3) =  {'Primary input'};
    tr.labsV(tr.indexYV{co},2) = {upper(tr.row_cls{co,1})}; %A3 code
    tr.labsV(tr.indexYV{co},1) = {upper(tr.row_cls{co,1})}; %country name
    
    % Handle FD
    fdcla = strrep(tr.col_cls{co,4},'-','_');
    tr.labsY(tr.indexYV{co},4) =  cla.(fdcla);
    tr.labsY(tr.indexYV{co},3) =  {'Final demand'};
    tr.labsY(tr.indexYV{co},2) = {upper(tr.row_cls{co,1})}; %A3 code
    tr.labsY(tr.indexYV{co},1) = {upper(tr.row_cls{co,1})}; %country name
    
    % Create labsM
    minds = tr.indexM{co};
    tr.labsM(minds(1:length(tr.indexT{co})),:) = tr.labsT(tr.indexT{co},:);
    tr.labsM(minds(length(tr.indexT{co})+1:end),:) = tr.labsY(tr.indexYV{co},:);
end

% Create labsQ
for q=1:length(tr.row_sat)
    tr.labsQ(tr.indexQ{q},1) = {tr.row_sat_cls{q}};
    qcla = strrep(tr.row_sat_cls{q,2},'-','_');
    tr.labsQ(tr.indexQ{q},2) = cla.(qcla);
end

tmp = vertcat({'Index','Country','CountryA3','Entity','Sector'}, horzcat(num2cellstr(1:tr.Tdim)', tr.labsT)); % Add numerical index col and header row
wt3([tr.tree_path '/index_t.csv'],tmp);
tmp = vertcat({'Index','Country','CountryA3','Entity','Sector'}, horzcat(num2cellstr(1:tr.Ydim)', tr.labsY)); % Add numerical index col and header row
wt3([tr.tree_path '/index_y.csv'],tmp);
tmp = vertcat({'Index','Country','CountryA3','Entity','Sector'}, horzcat(num2cellstr(1:tr.Ydim)', tr.labsV)); % Add numerical index col and header row
wt3([tr.tree_path '/index_v.csv'],tmp);
tmp = vertcat({'Index','Country','CountryA3','Entity','Sector'}, horzcat(num2cellstr(1:tr.Mdim)', tr.labsM)); % Add numerical index col and header row
wt3([tr.tree_path '/index_m.csv'],tmp);
tmp = vertcat({'Indicator row','Indicator Codename','Indicator','Sector'}, horzcat(num2cellstr(1:tr.Qdim)', tr.labsQ(:,1), tr.labsQ)); % Add numerical index col and header row
wt3([tr.tree_path '/index_q.csv'],tmp);


end %create_NonEora_indexfiles



function [  ] = dispIf( condition, msg)
%DISPIF calls disp(msg) if condition is true
if condition, disp(msg); end;
end



function boldwarningIf( condition, msg )
% boldwarningIf Calls boldwarning(msg) if condition is true
if condition,
    boldwarning(msg);
end;

end
