function [CreatedDataMatrix,CreatedDataNames,Status,ErrorStr] = CreateDataFcn(CreateDataStructure,VariableData,VariableNames,CreatedDataMatrix,CreatedDataNames,AnnualizeData,IsComparisonData)
% CreateDataFcn: Creates new variables using endogenous and exogenous variables
%
% USAGE:
%
%       [CreatedDataMatrix,CreatedDataNames,Status,ErrorStr] = CreateDataFcn(CreateDataStructure,VariableData,VariableNames,...
%                                                            CreatedDataMatrix,CreatedDataNames,AnnualizeData,IsComparisonData)
%
% REQUIRED INPUT:  CreateDataStructure (structure) with fields "names" with names of variables to create. Each such name is also a field
%                                      that must have the sub-fields "createbeforefcn", "createafterfcn" "createx", "createy" and "before".
%                                      In addition, if before is 1, then the sub-fields "fcn", "partial", "annualizefcn", "annualizepartial",
%                                      "initial", and "x" must also exist.
%
%                  VariableData (matrix) of dimension Txc with the c endogenous variables that can be used when creating data.
%
%                  VariableNames (string matrix) of dimension cxc1 with the names of of endogenous variables.
%
%                  CreatedDataMatrix (matrix) of dimension Txk with the previously created data for the variables
%                                      to create. If the matrix is empty then data will be created from scratch.
%
%                  CreatedDataNames (string matrix) of dimension kxk1 with names of the created variables.
%
%                  AnnualizeData (boolean) that is only used if annualizations should be applied to the variables
%                                      that have the boolean variable before set to 1.
%
%                  IsComparisonData (boolean) that takes on the value 1 if the data in VariableData are comparison
%                                      data and 0 otherwise. When IsComparisonData is 1, then "createcompx" is used
%                                      instead of "createx". Similarly, "compinitial" and "compx" are used instead
%                                      of "initial" and "x", respectively.
%
% REQUIRED OUTPUT: CreatedDataMatrix (matrix) of dimension Txk with the new data for the variables to create.
%
%                  CreatedDataNames (string matrix) of dimension kxk1 with names of the created variables.
%
%                  Status (boolean) that is 1 if the data was created successfully and 0 otherwise.
%
%                  ErrorStr (string vector) with an error message if the creation didn't go as planned.
%
%
%                       Written by: Anders Warne
%                                   New Area Wide Model Project
%                                   DG-R/EMO
%                                   European Central Bank (ECB)
%                                   Email: anders.warne@ecb.europa.eu
%                                   Copyright © 2006-2008 European Central Bank.
%
%                       First version: August 28, 2008.
%                        This version: December  18, 2008.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% 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:
%
% * 17-9:2008:  Fixed a bug where variables computed through the "TransformData" function
%               were not added to the "CreatedDataMatrix" output matrix. Changed to break calls
%               to the proper return since they were not inside loops.
%
% * 18-9-2008:  Solved a bug when determining the ordering of the variables via "YADASymvar". The
%               bug also affected "YADAInline".
%
% * 18-12-2008: Updated the documentation.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%

[T,c] = size(VariableData);
k = length(CreateDataStructure.names);
Status = 0;
ErrorStr = '';
if isempty(CreatedDataMatrix)==1;
   %
   % the data has not been created yet
   %
   CreatedDataNames = '';
   for i=1:k;
      CurrVariable = StringTrim(CreateDataStructure.names{i});
      CreatedDataNames = strvcat(CreatedDataNames,CurrVariable);
      %
      % get the create data structure for the variable
      %
      CurrField = getfield(CreateDataStructure,CurrVariable);
      Y = [];
      if IsComparisonData==0;
         X = CurrField.createx;
      else;
         X = CurrField.createcompx;
      end;
      GoodYVar = 1;
      if isempty(CurrField.createy)==0;
         for j=1:length(CurrField.createy);
            VarPos = loc(VariableNames,StringTrim(CurrField.createy{j}));
            if isempty(VarPos)==1;
               ErrorStr = ['Unable to locate the variable "' StringTrim(CurrField.createy{j}) '" among the data. This variable is needed by the creation function for "' CurrVariable '".'];
               GoodYVar = 0;
               break;
            else;
               Y = [Y VariableData(:,VarPos)];
            end;
         end;
         if GoodYVar==0;
            break;
         end;
      end;
      %
      if (isempty(X)==0)&(isempty(Y)==0);
         if size(X,1)~=size(Y,1);
            if size(X,2)==size(Y,1);
               X = X';
            else;
               ErrorStr = ['The number of observations for the data (' int2str(size(Y,1)) ') and the exogenous data (' int2str(size(X,1)) ') don''t match for "' CurrVariable '".'];
               break;
            end;
         end;
      end;
      %
      % create the inline function
      %
      try;
         YADAfcn = YADAInline(CurrField.createbeforefcn);
      catch;
         ErrorStr = ['The was an error creating the inline function for ' CurrVariable '. The following message was caught: ' lasterr];
         break;
      end;
      %
      % create the vector of variables
      %
      InputVars = YADASymvar(CurrField.createbeforefcn);
      %
      % check if we should locate positions of the y and x variables
      %
      Ypositions = [];
      if isempty(CurrField.createy)==0;
         for i1=1:length(InputVars);
            for j=1:length(CurrField.createy);
               if strcmp(InputVars{i1},CurrField.createy{j})==1;
                  Ypositions = [Ypositions i1];
               end;
            end;
         end;
      end;
      Xpositions = [];
      if isempty(X)==0;
         Xpositions = setdiff((1:length(InputVars)),Ypositions);
      end;
      %
      % create the input data that has the same ordering as
      % the InputVars that YADAfcn requires
      %
      if isempty([X Y])==0;
         InputData = zeros(size([X Y]));
         if isempty(Xpositions)==0;
            InputData(:,Xpositions) = X;
         end;
         if isempty(Ypositions)==0;
            InputData(:,Ypositions) = Y;
         end;
      else;
         InputData = [];
      end;
      %
      % set up the command line
      %
      RunArg = '';
      for i1=1:size(InputData,2);
         eval(['x' int2str(i1) ' = InputData(:,' int2str(i1) ');']);
         if i1>1;
            RunArg = [RunArg ',x' int2str(i1)];
         else;
            RunArg = 'x1';
         end;
      end;
      %
      % try to execute the function
      %
      try;
         eval(['y = YADAfcn(' RunArg ');']);
      catch;
         ErrorStr = ['YADA caught the following error message while applying the export function for the variable "' CurrVariable '": ' lasterr];
         break;
      end;
      %
      if length(y)<T;
         y = [NaN*ones(T-length(y),1);y];
      elseif length(y)>T;
         y = y(length(y)-T+1:length(y));
      end;
      %
      CreatedDataMatrix = [CreatedDataMatrix y];
   end;
else;
   %
   % check the input
   %
   if k~=size(CreatedDataMatrix,2);
      CreatedDataMatrix = CreatedDataMatrix';
   end;
   [T1,k1] = size(CreatedDataMatrix);
   %
   if T1~=T;
      ErrorStr = ['The number of observations for the created data (' int2str(T1) ') don''t match the number of observation for the data used (' int2str(T) ').'];
      return;;
   end;
   if k1~=k;
      ErrorStr = ['The number of variables to create (' int2str(k) ') doesn''t match the number of such variables that were previously created (' int2str(k1) ').'];
      return;
   end;
   %
   % and now for some action
   %
   for i=1:k;
      CurrVariable = StringTrim(CreateDataStructure.names{i});
      %
      % get the create data structure for the variable
      %
      CurrField = getfield(CreateDataStructure,CurrVariable);
      if CurrField.before==1;
         %
         % apply the transformation function to the variable
         %
         if IsComparisonData==1;
            CurrField.x = CurrField.compx;
            CurrField.initial = CurrField.compinitial;
            CreateDataStructure = setfield(CreateDataStructure,CurrVariable,CurrField);
         end;
         [y,TStatus,ErrorStr,HeaderStr,FcnStr] = TransformData(CreatedDataMatrix(:,i),CreateDataStructure,CurrVariable,AnnualizeData);
         if TStatus~=0;
            CreatedDataMatrix = [];
            break;
         else;
            if length(y)<T;
               y = [NaN*ones(T-length(y),1);y];
            elseif length(y)>T;
               y = y(length(y)-T+1:length(y));
            end;
            CreatedDataMatrix(:,i) = y;
         end;
      else;
         %
         % apply the creation function to the variable
         %
         Y = [];
         if IsComparisonData==0;
            X = CurrField.createx;
         else;
            X = CurrField.createcompx;
         end;
         GoodYVar = 1;
         if isempty(CurrField.createy)==0;
            for j=1:length(CurrField.createy);
               VarPos = loc(VariableNames,StringTrim(CurrField.createy{j}));
               if isempty(VarPos)==1;
                  ErrorStr = ['Unable to locate the variable "' StringTrim(CurrField.createy{j}) '" among the data. This variable is needed by the creation function for "' CurrVariable '".'];
                  GoodYVar = 0;
                  break;
               else;
                  Y = [Y VariableData(:,VarPos)];
               end;
            end;
            if GoodYVar==0;
               break;
            end;
         end;
         %
         if (isempty(X)==0)&(isempty(Y)==0);
            if size(X,1)~=size(Y,1);
               if size(X,2)==size(Y,1);
                  X = X';
               else;
                  ErrorStr = ['The number of observations for the data (' int2str(size(Y,1)) ') and the exogenous data (' int2str(size(X,1)) ') don''t match for "' CurrVariable '".'];
                  break;
               end;
            end;
         end;
         %
         % create the inline function
         %
         try;
            YADAfcn = YADAInline(CurrField.createafterfcn);
         catch;
            ErrorStr = ['The was an error creating the inline function for ' CurrVariable '. The following message was caught: ' lasterr];
            break;
         end;
         %
         % create the vector of variables
         %
         InputVars = YADASymvar(CurrField.createafterfcn);
         %
         % check if we should locate positions of the y and x variables
         %
         Ypositions = [];
         if isempty(CurrField.createy)==0;
            for i1=1:length(InputVars);
               for j=1:length(CurrField.createy);
                  if strcmp(InputVars{i1},CurrField.createy{j})==1;
                     Ypositions = [Ypositions i1];
                  end;
               end;
            end;
         end;
         Xpositions = [];
         if isempty(X)==0;
            Xpositions = setdiff((1:length(InputVars)),Ypositions);
         end;
         %
         % create the input data that has the same ordering as
         % the InputVars that YADAfcn requires
         %
         if isempty([X Y])==0;
            InputData = zeros(size([X Y]));
            if isempty(Xpositions)==0;
               InputData(:,Xpositions) = X;
            end;
            if isempty(Ypositions)==0;
               InputData(:,Ypositions) = Y;
            end;
         else;
            InputData = [];
         end;
         %
         % set up the command line
         %
         RunArg = '';
         for i1=1:size(InputData,2);
            eval(['x' int2str(i1) ' = InputData(:,' int2str(i1) ');']);
            if i1>1;
               RunArg = [RunArg ',x' int2str(i1)];
            else;
               RunArg = 'x1';
            end;
         end;
         %
         % try to execute the function
         %
         try;
            eval(['y = YADAfcn(' RunArg ');']);
         catch;
            ErrorStr = ['YADA caught the following error message while applying the export function for the variable "' CurrVariable '": ' lasterr];
            break;
         end;
         %
         if length(y)<T;
            y = [NaN*ones(T-length(y),1);y];
         elseif length(y)>T;
            y = y(length(y)-T+1:length(y));
         end;
         CreatedDataMatrix(:,i) = y;
      end;
   end;
end;
if size(CreatedDataMatrix,2)==k;
   Status = 1;
end;

%
% end of CreateDataFcn.m
%
