1  function [wt,info] = wfbtinit(wtdef,varargin)
2%-*- texinfo -*-
3%@deftypefn {Function} wfbtinit
4%@verbatim
5%WFBTINIT Initialize Filterbank Tree
6%   Usage:  wt = wfbtinit(wtdef);
7%
8%   Input parameters:
9%         wtdef : Filterbank tree definition.
10%
11%   Output parameters:
12%         wt    : Structure describing the filter tree.
13%
14%   WFBTINIT({w,J,flag}) creates a filterbank tree of depth J. The
15%   parameter w defines a basic wavelet filterbank. For all possible
16%   formats see FWT.  The following optional flags (still inside of the
17%   cell-array) are recognized:
18%
19%   'dwt','full','doubleband','quadband','octaband'
20%     Type of the tree to be created.
21%
22%   WFBTINIT({w,J,flag,'mod',mod}) creates a filterbank tree as before,
23%   but modified according to the value of mod.
24%   Recognized options:
25%
26%   'powshiftable'
27%      Changes subsampling factors of the root to 1. This results in redundant
28%      near-shift invariant representation.
29%
30%   The returned structure wt has the following fields:
31%
32%   .nodes
33%      Cell-array of structures obtained from FWTINIT. Each element
34%      define a basic wavelet filterbank.
35%
36%   .children
37%      Indexes of children nodes
38%
39%   .parents
40%      Indexes of a parent node
41%
42%   .forder
43%      Frequency ordering of the resultant frequency bands.
44%
45%   The structure together with functions from the wfbtmanip
46%   subdirectory acts as an abstract data structure tree.
47%
48%   Regular WFBTINIT flags:
49%
50%   'freq','nat'
51%     Frequency or natural ordering of the coefficient subbands. The direct
52%     usage of the wavelet tree ('nat' option) does not produce coefficient
53%     subbans ordered according to the frequency. To achieve that, some
54%     filter shuffling has to be done ('freq' option).
55%
56%@end verbatim
57%@strong{Url}: @url{http://ltfat.github.io/doc/wavelets/wfbtinit.html}
58%@seealso{wfbtput, wfbtremove}
59%@end deftypefn
60
61% Copyright (C) 2005-2016 Peter L. Soendergaard <peter@sonderport.dk>.
62% This file is part of LTFAT version 2.3.1
63%
64% This program is free software: you can redistribute it and/or modify
65% it under the terms of the GNU General Public License as published by
66% the Free Software Foundation, either version 3 of the License, or
67% (at your option) any later version.
68%
69% This program is distributed in the hope that it will be useful,
70% but WITHOUT ANY WARRANTY; without even the implied warranty of
71% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
72% GNU General Public License for more details.
73%
74% You should have received a copy of the GNU General Public License
75% along with this program.  If not, see <http://www.gnu.org/licenses/>.
76
77% AUTHOR: Zdenek Prusa
78
79% TO DO: Do some caching
80
81% Output structure definition.
82% Effectively, it describes a ADT tree.
83% .nodes, .children, .parents ale all arrays of the same length and the j-th
84% node in the tree is desribed by wt.nodes{j}, wt.children{j} and
85% wt.parents(j). wt.nodes{j} is the actual data stored in the tree node
86% (a structure returned form fwtinit) and wt.parents(j) and wt.children{j}
87% define relationship to other nodes. wt.parents(j) is an index of the
88% parent in the arrays. wt.children{j} is an array of indexes of the
89% children nodes.
90%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
91wt.nodes = {};
92wt.children = {};
93wt.parents = [];
94wt.freqOrder = 0;
95%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
96info.istight = 0;
97
98% return empty struct if no argument was passed
99if(nargin<1)
100    return;
101end
102
103
104do_strict = 0;
105do_dual = 0;
106
107% Check 'strict'
108if iscell(wtdef) && ischar(wtdef{1}) && strcmpi(wtdef{1},'strict')
109   do_strict = 1;
110   wtdef = wtdef{2:end};
111end
112% Check 'dual'
113if iscell(wtdef) && ischar(wtdef{1}) && strcmpi(wtdef{1},'dual')
114   do_dual = 1;
115   wtdef = wtdef{2:end};
116end
117
118definput.import = {'wfbtcommon'};
119[flags,kv]=ltfatarghelper({},definput,varargin);
120
121% If wtdef is already a structure
122if (isstruct(wtdef)&&isfield(wtdef,'nodes'))
123    if isempty(wtdef.nodes)
124        error('%s: The tree struct is empty.',upper(mfilename));
125    end
126
127    wt = wtdef;
128
129    if do_dual || do_strict
130       nodesArg = wt.nodes;
131       if do_dual
132          nodesArg = cellfun(@(nEl) {'dual',nEl},nodesArg,'UniformOutput',0);
133       end
134       if do_strict
135          nodesArg = cellfun(@(nEl) {'strict',nEl},nodesArg,'UniformOutput',0);
136       end
137       info.istight = 1;
138       wt.nodes = {};
139       for ii=1:numel(nodesArg)
140        % wt.nodes = cellfun(@(nEl) fwtinit(nEl),nodesArg,'UniformOutput',0);
141          [wt.nodes{ii},infotmp] = fwtinit(nodesArg{ii});
142          if info.istight
143              info.istight = infotmp.istight;
144          end
145       end
146       % Do the filter frequency shuffling again, since the filters were
147       % overwritten in fwtinit.
148       if wt.freqOrder
149          wt = nat2freqOrder(wt);
150       end
151    end
152
153    % Do filter shuffling if flags.do_freq differs from the wt.freqOrder.
154    % Frequency and natural oreding coincide for DWT.
155    if wt.freqOrder ~= flags.do_freq
156       wt = nat2freqOrder(wt);
157       wt.freqOrder = ~wt.freqOrder;
158    end
159    return;
160end
161
162% break if the input parameter is not in the correct format
163if ~(iscell(wtdef)) || isempty(wtdef)
164    error('%s: Unsupported filterbank tree definition.',upper(mfilename));
165end
166
167% Creating new tree
168% Now wtdef is this {w,J,flag}
169wdef = wtdef{1};
170definput = [];
171definput.flags.treetype = {'full','dwt','doubleband','quadband',...
172                           'octaband','root'};
173definput.keyvals.mod = [];
174definput.keyvals.overcomplete = [];
175definput.keyvals.J = [];
176[flags2,kv2,J]=ltfatarghelper({'J'},definput,wtdef(2:end));
177
178complainif_notposint(J,'J');
179
180if do_dual
181   wdef = {'dual',wdef};
182end
183
184if do_strict
185   wdef = {'strict',wdef};
186end
187
188do_powshiftable = 0;
189% Is the first level filterbank different?
190if ~isempty(kv2.mod)
191    if ischar(kv2.mod)
192        if strcmpi(kv2.mod,'powshiftable')
193           if ~flags2.do_dwt
194              error('%s: powshiftable is only valid with the dwt flag.',...
195                    upper(mfilename));
196           end
197           do_powshiftable = 1;
198        else
199           error('%s: Not recognized value for the mod key.',upper(mfilename));
200        end
201    else
202        error('%s: Not recognized value for the first key.',upper(mfilename));
203    end
204end
205
206if ~isempty(kv2.overcomplete)
207     error('%s: TO DO: overcomplete.',upper(mfilename));
208end
209
210
211[w, info] = fwtinit(wdef);
212
213% Doing one-node tree
214if flags2.do_root
215   J = 1;
216end
217
218if flags2.do_dwt
219   % fill the structure to represent a DWT tree
220   for jj=0:J-1
221      wt = wfbtput(jj,0,w,wt);
222   end
223elseif flags2.do_full
224   % fill the structure to represent a full wavelet tree
225   for jj=0:J-1
226     % for ii=0:numel(w.g)^(jj)-1
227         wt = wfbtput(jj,0:numel(w.g)^(jj)-1,w,wt);
228     % end
229   end
230elseif flags2.do_doubleband
231   % fill the structure to represent a double band tree
232   for jj=0:J-1
233     % for ii=0:numel(w.g)^(jj)-1
234         wt = wfbtput(2*jj,0,w,wt);
235         wt = wfbtput(2*jj+1,0:1,w,wt);
236     % end
237   end
238
239elseif flags2.do_quadband
240   % fill the structure to represent a quad band tree
241   for jj=0:J-1
242     % for ii=0:numel(w.g)^(jj)-1
243         wt = wfbtput(3*jj,0,w,wt);
244         wt = wfbtput(3*jj+1,0:1,w,wt);
245         wt = wfbtput(3*jj+2,0:3,w,wt);
246     % end
247   end
248elseif flags2.do_octaband
249   % fill the structure to represent a octa band tree
250   for jj=0:J-1
251     % for ii=0:numel(w.g)^(jj)-1
252         wt = wfbtput(4*jj,0,w,wt);
253         wt = wfbtput(4*jj+1,0:1,w,wt);
254         wt = wfbtput(4*jj+2,0:3,w,wt);
255         wt = wfbtput(4*jj+3,0:7,w,wt);
256     % end
257   end
258end
259
260% Do filter shuffling if frequency ordering is required,
261wt.freqOrder = flags.do_freq;
262if flags.do_freq
263   wt = nat2freqOrder(wt);
264end
265
266if do_powshiftable
267    % Change subsampling factors of the root to 1
268    wt.nodes{wt.parents==0}.a(:) = 1;
269end
270
271
272
273
274
275