function [ wcs_out ] = insertWaveletCoeffs( wcs, wcv, level, index )
%insertWaveletCoeffs Insert a vector of wavelet coefficients in to the WCS
%at level 'level'
%   [ wcs ] = insertWaveletCoeffs( wcs, wcv, level ) inserts a vector of
%   wavelet coefficients in wcv into a Wacelet Coefficient Structure (WCS).
%   The wavelet coefficients in wcv may be those governing trends in x-, y-
%   or xy-directions (index = 1, 2, 3), or they may contain wavelet
%   coefficients in x, y and xy directions, in the same sequence that
%   extractWaveletCoeffs() does things.
% 
% INPUT:
%  wcs     : The WCS into which the vector of wavelet coefficients has to
%            be inserted.
%
%  wcv     : The vector of wavelet coefficients which are to be inserted.
%            On level 'l', there are a total of (2^l X 2^l) - 
%            (2^{l-1} X 2^{l-1}) wavelet coefficients
%
%  level   : The wavelet coefficients at at level 'level'
%
%  index   : The wavelet coefficients correspond to those that determine
%            variation in the 'index' direction. index = {1, 2, 3} = {x-,
%            y-, xy-} directions.  If you specify an index, we expect that
%            the length of the wcv vector is  [ (2^l X 2^l) - 
%            (2^{l-1} X 2^{l-1})] / 3.
%
% OUTPUT :
%  wcs      : The wavelet coefficient structure (WCS) with the wavelet
%             coefficients from wcv inserted into it at the right level.
%
% See also :
%
%     extractWaveletCoeffs
%
% Jaideep Ray, SNL, 2/25/211
% =========================================================================

% ---- make a copy
wcs_out = wcs ;
wcs_out.waveletType    = wcs.waveletType ;
wcs_out.waveletOrder   = wcs.waveletOrder ;
wcs_out.qmf            = wcs.qmf ;
wcs_out.origDataSize   = wcs.origDataSize ;
wcs_out.paddedDataSize = wcs.paddedDataSize ;
wcs_out.nlevels        = wcs.nlevels ;
wcs_out.baseVal        = wcs.baseVal ;
wcs_out.coeffs         = cell(wcs_out.nlevels, 3) ;

for l = 1 : wcs.nlevels
    for index = 1 : 3
        wcs_out.coeffs{l, index} = wcs.coeffs{l, index} ;
    end
end

% ---- What is the size of the incoming vector?
reqdSize = 2^(2*level) - 2^(2*level-2) ;
if (nargin == 4) % somebody gave me an index
    reqdSize = reqdSize / 3 ;
end
if ( numel(wcv) ~= reqdSize )
    error('insertWaveletCoeffs(): Incoming wavelet vector is of the wrong size'); 
end

% ---- If the index is specified, simply stick this into the WCS
if (level == 0)
    wcs_out.baselevel = wcv(1) ; % wcv has only 1 element if level == 0
    return ;
end

% ---- If the index is specified, reshape the vector to 2D arrays and copy
%      into the right place in the WCS
if (nargin == 4)
    tmp = reshape(wcv, size(wcs.coeffs{level, 1}, 1), ...
                       size(wcs.coeffs{level, 1}, 2) ) ;
    wcs_out.coeffs{level, index} = tmp ;
    return ;
end

% ---- No index specified, so the vector has all the wavelet coeffs on this
% level.
for index = 1 : 3
    numElements = numel(wcs.coeffs{level, index}) ;
    lb = (index - 1)*numElements + 1 ; % lb, ub of the wavelet coeffs in the vector
    ub = lb + numElements -1 ;         % that are of index 'index'
    tmp = reshape(wcv(lb:ub), size(wcs.coeffs{level, index}, 1), ...
                              size(wcs.coeffs{level, index}, 2) ) ;
    wcs_out.coeffs{level, index} = tmp ;
end

end

