function pred = apply_tree_final( forest, NaNNbre, nan_placement, xtest_rk, xtest_rk_normalized, xtrain_rk_normalized_sorted, xtrain_rk )
%   APPLY_TREE calculates a single tree's contribution to the prediction
%
%   pred = apply_tree( tree, xtrain, NaNNbre) calculates the contributions
%       from tree on data in xtrain. NaNNbre is the number of non-NaN
%       entries in each column of xtrain.
%
%   pred = apply_tree( tree, xtrain, NaNNbre, xtrain_normalized) allows the
%   user to input xtrain_normalized, which is the value of xtrain if it
%   were used to generate a normal variable with zero mean and unit
%   standard deviation. This will speed up the function.
%
% tree is a vector has the following parameters
% - 1-3: Variables indices for first three nodes
% - 4-5: Threshods for nodes 1 and 2
% - 6: slope
% - 7-9 : missing value param for nodes 1 to 3
% - 10 : architechture type (1,2,3,4), i.e. location of the final node in the tree
% - 11: intercept

%	$LastChangedBy: alistair $
%	$LastChangedDate: 2012-05-16 13:48:37 +0100 (Wed, 16 May 2012) $
%	$Revision: 10 $
%	Originally written on GLNXA64 by Alistair Johnson, 09-May-2012 16:26:13
%	Contact: alistairewj@gmail.com

% treeidx = 1;
% tree = forest(1,:,treeidx);
Ntrees = size(forest,2);
if Ntrees > 1
    Ntrees = Ntrees-1; % do not include intercept in forest calcs
end
%% APPLY TREE
N = size(xtest_rk,1);

%% First Node
% first split value [0,1] * number of non-nan values
i1 = forest(1,1:Ntrees);
i4 = forest(4,1:Ntrees);
i7 = forest(7,1:Ntrees);
i1_NaN = NaNNbre(i1);
obs1 = bsxfun(@gt,xtest_rk(:,i1),i4.*i1_NaN); % get observations in 1st split
%         obs1 = xtrain(:,tree(1)) > tree(4)*NaNNbre(tree(1));
% rank greater than...
% if number of NaNs * missingness for that param < number of values in the split
%         if(NaNNbre(tree(1))*tree(7)<sum(obs1))
%             obs1(isnan(obs1))=1;
%         end % missing values

% obs1train = bsxfun(@gt, xtrain_rk(:,i1),i4.*i1_NaN);
% obs1train = i1_NaN.*i7 < sum(obs1train,1);

obs1(isnan(xtest_rk(:,i1)) & repmat(nan_placement(1,:), N, 1)) = true;

i10 = repmat(forest(10,1:Ntrees) < 3,N,1);
obs1(i10) = ~obs1(i10); % include fraction of missing values in split

%% Second Node
i2 = forest(2,1:Ntrees);
i5 = forest(5,1:Ntrees);
i8 = forest(8,1:Ntrees);
i2_NaN = NaNNbre(i2);

obs2 = bsxfun(@gt,xtest_rk(:,i2),i5.*i2_NaN);

% obs2train = bsxfun(@gt, xtrain_rk(:,i2),i5.*i2_NaN);
% obs2train = i2_NaN.*i8<sum(obs2train,1);

obs2(isnan(xtest_rk(:,i2)) & repmat(nan_placement(2,:),N,1)) = true;

i10 = repmat(mod(forest(10,1:Ntrees),2)==0,N,1);
obs2(i10) = ~obs2(i10);

%% Third node (final leaf)
obs1 = obs1 & obs2; % take the intersection
% obs1 now contains only the data to be evaluated by the tree

i3 = forest(3,1:Ntrees);
% now s1 aren't missing, s2 are missing (again indices logicals)
obs1nans = obs1 & isnan(xtest_rk(:,i3)); % missing values
obsTot = obs1 & ~isnan(xtest_rk(:,i3)); % non-missing values

% take the ranks, assume normal distribution and synthetize the
% data: don't give a #*& about the values
% THIS STEP SHOULD BE DONE BEFORE THE MCMC LOOP.

%=== Need to extract the values at obsTot for the features indexed in i3
% Will use obsTot as a multiplicative factor to select/de-select obs
% x_normalized = bsxfun(@minus,xtest_rk_normalized(:,i3),nanmean(xtrain_rk_normalized(:,i3),1));
x_normalized = xtest_rk_normalized(:,i3);

%=== Find the value selected from the training data to be a surrogate 
% for missing values
i6 = forest(6,1:Ntrees); % multiplicative factor on the training values

% do not sort - assume normalized is already sorted
% temp2=bsxfun(@times,i6,sort(xtrain_rk_normalized_sorted(:,i3),1,'ascend'));

% temp 2 contains all the training values - index into it for the selected
% value used to represent missing data
i9 = forest(9,1:Ntrees);
idxMV = ceil(i9.*(NaNNbre(i3)-1));
idxMV = sub2ind([size(xtrain_rk_normalized_sorted,1),Ntrees],idxMV,1:Ntrees);

% /***/ replaced with 1 row style
% temp2=bsxfun(@times,i6,xtrain_rk_normalized_sorted(:,i3));
temp2 = xtrain_rk_normalized_sorted(:,i3);
temp2 = temp2(idxMV); 
temp2 = i6 .* temp2;
temp2 = repmat(reshape(temp2,[1,Ntrees]),N,1);

pred = zeros(N,Ntrees);

i11 = repmat(forest(11,1:Ntrees),N,1); % intercept
pred(obs1nans) = i11(obs1nans) + temp2(obs1nans);
predTot = bsxfun(@times, i6, x_normalized);
pred(obsTot) = i11(obsTot) + predTot(obsTot);
pred(isnan(pred))=0;
pred = sum(pred,2);

end
