Commit abcf6d90 authored by Stéphane Adjemian's avatar Stéphane Adjemian

Fixed behaviour w.r.t inplace modification.

GENERAL RULE: Methods with trailing underscore do in place modifications of the
object, while methods without trailing underscore do a copy (and leave
the original object unchanged).

Also fixed some headers and unit tests + cosmetic changes.
parent e1053598
function A = abs(B) % --*-- Unitary tests --*--
function o = abs(o) % --*-- Unitary tests --*--
%@info:
%! @deftypefn {Function File} {@var{A} =} abs (@var{B})
%! @anchor{@dseries/uminus}
%! @sp 1
%! Overloads the abs method for the Dynare time series class (@ref{dseries}).
%! @sp 2
%! @strong{Inputs}
%! @sp 1
%! @table @ @var
%! @item B
%! Dynare time series object instantiated by @ref{dseries}.
%! @end table
%! @sp 1
%! @strong{Outputs}
%! @sp 1
%! @table @ @var
%! @item A
%! Dynare time series object.
%! @end deftypefn
%@eod:
% Apply the absolute value to all the variables in a dseries object (without in place modification).
%
% INPUTS
% - o [dseries]
%
% OUTPUTS
% - o [dseries]
% Copyright (C) 2013 Dynare Team
% Copyright (C) 2011-2017 Dynare Team
%
% This file is part of Dynare.
%
......@@ -38,26 +25,63 @@ function A = abs(B) % --*-- Unitary tests --*--
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see <http://www.gnu.org/licenses/>.
A = dseries();
o = copy(o);
o.abs_;
A.data = abs(B.data);
A.dates = B.dates;
%@test:1
%$ % Define a dates object
%$ data = -ones(10,2);
%$ o = dseries(data);
%$ q = dseries(data);
%$
%$ % Call the tested routine.
%$ try
%$ p = o.abs();
%$ t(1) = true;
%$ catch
%$ t(1) = false;
%$ end
%$
%$ if t(1)
%$ t(2) = dassert(o, q);
%$ t(3) = dassert(p.data, ones(10, 2));
%$ end
%$
%$ T = all(t);
%@eof:1
A.name = cell(vobs(A), 1);
A.tex = cell(vobs(A), 1);
for i = 1:vobs(A)
A.name(i) = {[ 'abs(' B.name{i} ')']};
A.tex(i) = {[ '|' B.tex{i} '|']};
end
%@test:2
%$ % Define a dates object
%$ data = -ones(10,2);
%$ o = dseries(data);
%$ q = dseries(data);
%$
%$ % Call the tested routine.
%$ try
%$ p = o.abs();
%$ t(1) = true;
%$ catch
%$ t(1) = false;
%$ end
%$
%$ if t(1)
%$ t(2) = dassert(length(p.name), 2);
%$ t(3) = dassert(p.name{1},'abs(Variable_1)');
%$ t(4) = dassert(p.name{2},'abs(Variable_2)');
%$ t(5) = dassert(o.name{1},'Variable_1');
%$ t(6) = dassert(o.name{2},'Variable_2');
%$ end
%$
%$ T = all(t);
%@eof:2
%@test:1
%@test:3
%$ % Define a datasets.
%$ A = randn(10,2);
%$
%$ % Define names
%$ A_name = {'A1';'A2'};
%$ A_tex = {'A_1';'A_2'};
%$ t = zeros(6,1);
%$
%$ % Instantiate a time series object and compute the absolute value.
%$ try
......@@ -74,18 +98,22 @@ end
%$ t(4) = dassert(ts2.data,abs(A),1e-15);
%$ t(5) = dassert(ts2.name,{'abs(A1)';'abs(A2)'});
%$ t(6) = dassert(ts2.tex,{'|A_1|';'|A_2|'});
%$ t(7) = dassert(ts1.vobs, 2);
%$ t(8) = dassert(ts1.nobs, 10);
%$ t(9) = dassert(ts1.data, A, 1e-15);
%$ t(10) = dassert(ts1.name, {'A1';'A2'});
%$ t(11) = dassert(ts1.tex, {'A_1';'A_2'});
%$ end
%$ T = all(t);
%@eof:1
%@eof:3
%@test:2
%@test:4
%$ % Define a datasets.
%$ A = randn(10,2);
%$
%$ % Define names
%$ A_name = {'A1';'A2'};
%$ A_tex = {'A_1';'A_2'};
%$ t = zeros(6,1);
%$
%$ % Instantiate a time series object and compute the absolute value.
%$ try
......@@ -102,6 +130,11 @@ end
%$ t(4) = dassert(ts2.data,abs(A),1e-15);
%$ t(5) = dassert(ts2.name,{'abs(A1)';'abs(A2)'});
%$ t(6) = dassert(ts2.tex,{'|A_1|';'|A_2|'});
%$ t(7) = dassert(ts1.vobs, 2);
%$ t(8) = dassert(ts1.nobs, 10);
%$ t(9) = dassert(ts1.data, A, 1e-15);
%$ t(10) = dassert(ts1.name, {'A1';'A2'});
%$ t(11) = dassert(ts1.tex, {'A_1';'A_2'});
%$ end
%$ T = all(t);
%@eof:2
\ No newline at end of file
%@eof:4
function o = abs_(o) % --*-- Unitary tests --*--
% Apply the absolute value to all the variables in a dseries object (in place modification).
%
% INPUTS
% - o [dseries]
%
% OUTPUTS
% - o [dseries]
% Copyright (C) 2017 Dynare Team
%
% This file is part of Dynare.
%
% Dynare 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.
%
% Dynare 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 Dynare. If not, see <http://www.gnu.org/licenses/>.
for i=1:vobs(o)
o.name(i) = {['abs(' o.name{i} ')']};
o.tex(i) = {['|' o.tex{i} '|']};
end
o.data = abs(o.data);
%@test:1
%$ % Define a dates object
%$ data = -ones(10,2);
%$ o = dseries(data);
%$ q = o;
%$ r = copy(o);
%$
%$ % Call the tested routine.
%$ try
%$ o.abs_();
%$ t(1) = true;
%$ catch
%$ t(1) = false;
%$ end
%$
%$ if t(1)
%$ t(2) = dassert(o.data, ones(10,2));
%$ t(3) = dassert(q.data, ones(10,2));
%$ t(4) = dassert(r.data, -ones(10, 2));
%$ end
%$
%$ T = all(t);
%@eof:1
%@test:2
%$ % Define a dates object
%$ data = [ones(10,1), -ones(10,1)];
%$ o = dseries(data);
%$ q = o;
%$ r = copy(o);
%$
%$ % Call the tested routine.
%$ try
%$ o.abs_();
%$ t(1) = true;
%$ catch
%$ t(1) = false;
%$ end
%$
%$ if t(1)
%$ t(2) = dassert(length(o.name), 2);
%$ t(3) = dassert(o.name{1},'abs(Variable_1)');
%$ t(4) = dassert(o.name{2},'abs(Variable_2)');
%$ t(5) = dassert(q.name{1},'abs(Variable_1)');
%$ t(6) = dassert(q.name{2},'abs(Variable_2)');
%$ t(7) = dassert(r.name{1},'Variable_1');
%$ t(8) = dassert(r.name{2},'Variable_2');
%$ end
%$
%$ T = all(t);
%@eof:2
\ No newline at end of file
function ts = baxter_king_filter(ts, high_frequency, low_frequency, K) % --*-- Unitary tests --*--
function o = baxter_king_filter(o, high_frequency, low_frequency, K) % --*-- Unitary tests --*--
% ts = baxter_king_filter(ts, high_frequency, low_frequency, K)
%
% Implementation of Baxter and King (1999) band pass filter for dseries objects. The code is adapted from
% the one provided by Baxter and King. This filter isolates business cycle fluctuations with a period of length
% ranging between high_frequency to low_frequency (quarters).
%
% INPUTS
% o ts dseries object.
% o high_frequency positive scalar, period length (default value is 6).
% o low_frequency positive scalar, period length (default value is 32).
% o K positive scalar integer, truncation parameter (default value is 12).
% - o dseries object.
% - high_frequency positive scalar, period length (default value is 6).
% - low_frequency positive scalar, period length (default value is 32).
% - K positive scalar integer, truncation parameter (default value is 12).
%
% OUTPUTS
% o ts dseries object.
% - o dseries object.
%
% REMARKS
% This filter use a (symmetric) moving average smoother, so that K observations at the beginning and at the end of the
% sample are lost in the computation of the filter.
% Copyright (C) 2013 Dynare Team
% Copyright (C) 2013-2017 Dynare Team
%
% This file is part of Dynare.
%
......@@ -58,46 +56,11 @@ if nargin<4 || isempty(K)
end
end
% translate periods into frequencies.
hf=2.0*pi/high_frequency;
lf=2.0*pi/low_frequency;
% Set weights for the band-pass filter's lag polynomial.
weights = zeros(K+1,1); lpowers = transpose(1:K);
weights(2:K+1) = (sin(lpowers*hf)-sin(lpowers*lf))./(lpowers*pi);
weights(1) = (hf-lf)/pi;
% Set the constraint on the sum of weights.
if low_frequency>1000
% => low pass filter.
sum_of_weights_constraint = 1.0;
else
sum_of_weights_constraint = 0.0;
end
% Compute the sum of weights.
sum_of_weights = weights(1) + 2*sum(weights(2:K+1));
% Correct the weights.
weights = weights + (sum_of_weights_constraint - sum_of_weights)/(2*K+1);
% Weights are symmetric!
weights = [flipud(weights(2:K+1)); weights];
tmp = zeros(size(ts.data));
% Filtering step.
for t = K+1:nobs(ts)-K
tmp(t,:) = weights'*ts.data(t-K:t+K,:);
end
% Update dseries object.
ts.data = tmp(K+1:end-K,:);
init = firstdate(ts)+K;
ts.dates = init:init+(nobs(ts)-1);
o = copy(o);
o.baxter_king_filter_(high_frequency, low_frequency, K);
%@test:1
%$ plot_flag = 0;
%$ plot_flag = false;
%$
%$ % Create a dataset.
%$ e = .2*randn(200,1);
......@@ -113,7 +76,7 @@ ts.dates = init:init+(nobs(ts)-1);
%$ % Test the routine.
%$ try
%$ ts = dseries(y,'1950Q1');
%$ ts = ts.baxter_king_filter();
%$ ds = ts.baxter_king_filter();
%$ xx = dseries(x,'1950Q1');
%$ t(1) = 1;
%$ catch
......@@ -121,11 +84,17 @@ ts.dates = init:init+(nobs(ts)-1);
%$ end
%$
%$ if t(1)
%$ t(2) = dassert(ts.freq,4);
%$ t(3) = dassert(ts.init.freq,4);
%$ t(4) = dassert(ts.init.time,[1953, 1]);
%$ t(5) = dassert(ts.vobs,1);
%$ t(6) = dassert(ts.nobs,176);
%$ t(2) = dassert(ds.freq, 4);
%$ t(3) = dassert(ds.init.freq, 4);
%$ t(4) = dassert(ds.init.time, [1953, 1]);
%$ t(5) = dassert(ds.vobs, 1);
%$ t(6) = dassert(ds.nobs, 176);
%$ t(7) = dassert(ts.freq, 4);
%$ t(8) = dassert(ts.init.freq, 4);
%$ t(9) = dassert(ts.init.time, [1950, 1]);
%$ t(10) = dassert(ts.vobs, 1);
%$ t(11) = dassert(ts.nobs, length(y));
%$ t(12) = dassert(ts.data, y);
%$ end
%$
%$ % Show results
......
function o = baxter_king_filter_(o, high_frequency, low_frequency, K) % --*-- Unitary tests --*--
% Implementation of Baxter and King (1999) band pass filter for dseries objects. The code is adapted from
% the one provided by Baxter and King. This filter isolates business cycle fluctuations with a period of length
% ranging between high_frequency to low_frequency (quarters).
%
% INPUTS
% - o dseries object.
% - high_frequency positive scalar, period length (default value is 6).
% - low_frequency positive scalar, period length (default value is 32).
% - K positive scalar integer, truncation parameter (default value is 12).
%
% OUTPUTS
% - o dseries object.
%
% REMARKS
% This filter use a (symmetric) moving average smoother, so that K observations at the beginning and at the end of the
% sample are lost in the computation of the filter.
% Copyright (C) 2013-2017 Dynare Team
%
% This file is part of Dynare.
%
% Dynare 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.
%
% Dynare 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 Dynare. If not, see <http://www.gnu.org/licenses/>.
if nargin<4 || isempty(K)
K = 12;
if nargin<3 || isempty(low_frequency)
% Set default number of periods corresponding to the lowest frequency.
low_frequency = 32;
if nargin<2 || isempty(high_frequency)
% Set default number of periods corresponding to the highest frequency.
high_frequency = 6;
if nargin<1
error('dseries::baxter_king_filter: I need at least one argument')
end
else
if high_frequency<2
error('dseries::baxter_king_filter: Second argument must be greater than 2!')
end
if high_frequency>low_frequency
error('dseries::baxter_king_filter: Second argument must be smaller than the third argument!')
end
end
end
end
% translate periods into frequencies.
hf=2.0*pi/high_frequency;
lf=2.0*pi/low_frequency;
% Set weights for the band-pass filter's lag polynomial.
weights = zeros(K+1,1); lpowers = transpose(1:K);
weights(2:K+1) = (sin(lpowers*hf)-sin(lpowers*lf))./(lpowers*pi);
weights(1) = (hf-lf)/pi;
% Set the constraint on the sum of weights.
if low_frequency>1000
% => low pass filter.
sum_of_weights_constraint = 1.0;
else
sum_of_weights_constraint = 0.0;
end
% Compute the sum of weights.
sum_of_weights = weights(1) + 2*sum(weights(2:K+1));
% Correct the weights.
weights = weights + (sum_of_weights_constraint - sum_of_weights)/(2*K+1);
% Weights are symmetric!
weights = [flipud(weights(2:K+1)); weights];
tmp = zeros(size(o.data));
% Filtering step.
for t = K+1:nobs(o)-K
tmp(t,:) = weights'*o.data(t-K:t+K,:);
end
% Update dseries object.
o.data = tmp(K+1:end-K,:);
init = firstdate(o)+K;
o.dates = init:init+(nobs(o)-1);
%@test:1
%$ plot_flag = false;
%$
%$ % Create a dataset.
%$ e = .2*randn(200,1);
%$ u = randn(200,1);
%$ stochastic_trend = cumsum(e);
%$ deterministic_trend = .1*transpose(1:200);
%$ x = zeros(200,1);
%$ for i=2:200
%$ x(i) = .75*x(i-1) + e(i);
%$ end
%$ y = x + stochastic_trend + deterministic_trend;
%$
%$ % Test the routine.
%$ try
%$ ts = dseries(y,'1950Q1');
%$ ts = ts.baxter_king_filter_();
%$ xx = dseries(x,'1950Q1');
%$ t(1) = 1;
%$ catch
%$ t(1) = 0;
%$ end
%$
%$ if t(1)
%$ t(2) = dassert(ts.freq,4);
%$ t(3) = dassert(ts.init.freq,4);
%$ t(4) = dassert(ts.init.time,[1953, 1]);
%$ t(5) = dassert(ts.vobs,1);
%$ t(6) = dassert(ts.nobs,176);
%$ end
%$
%$ % Show results
%$ if plot_flag
%$ plot(xx(ts.dates).data,'-k');
%$ hold on
%$ plot(ts.data,'--r');
%$ hold off
%$ axis tight
%$ id = get(gca,'XTick');
%$ set(gca,'XTickLabel',strings(ts.dates(id)));
%$ legend({'Stationary component of y', 'Filtered y'})
%$ print('-depsc2','../doc/dynare.plots/BaxterKingFilter.eps')
%$ system('convert -density 300 ../doc/dynare.plots/BaxterKingFilter.eps ../doc/dynare.plots/BaxterKingFilter.png');
%$ system('convert -density 300 ../doc/dynare.plots/BaxterKingFilter.eps ../doc/dynare.plots/BaxterKingFilter.pdf');
%$ system('convert -density 300 ../doc/dynare.plots/BaxterKingFilter.eps ../doc/dynare.plots/BaxterKingFilter.jpg');
%$ end
%$
%$ T = all(t);
%@eof:1
function o = center(o, geometric) % --*-- Unitary tests --*--
% Centers @dseries object o around its mean (arithmetic or geometric).
% Centers dseries object o around its mean (arithmetic or geometric).
%
% INPUTS
% o o dseries object [mandatory].
% o geometric logical [default is false], if true returns the geometric mean.
% - o dseries object [mandatory].
% - geometric logical [default is false], if true returns the geometric mean.
%
% OUTPUTS
% o o o
% - o dseries object.
% Copyright (C) 2016 Dynare Team
% Copyright (C) 2016-2017 Dynare Team
%
% This file is part of Dynare.
%
......@@ -30,11 +30,8 @@ if nargin<2
geometric = false;
end
if geometric
o = o/mean(o, true);
else
o = o-mean(o, false);
end
o = copy(o);
o.center_(geometric);
%@test:1
%$ % Define a dataset.
......@@ -43,14 +40,15 @@ end
%$ % Instantiate a time series object and compute the mean.
%$ try
%$ ts = dseries(A);
%$ ts.center(true);
%$ ds = ts.center(true);
%$ t(1) = 1;
%$ catch
%$ t = 0;
%$ end
%$
%$ if t(1)
%$ t(2) = all(all(abs(ts.data-ones(10,2))<1e-12));
%$ t(2) = all(all(abs(ds.data-ones(10,2))<1e-12));
%$ t(3) = all(all(abs(ts.data-A)<1e-12));
%$ end
%$ T = all(t);
%@eof:1
function o = center_(o, geometric) % --*-- Unitary tests --*--
% Centers dseries object o around its mean (arithmetic or geometric).
%
% INPUTS
% - o dseries object [mandatory].
% - geometric logical [default is false], if true returns the geometric mean.
%
% OUTPUTS
% - o dseries object.
% Copyright (C) 2016-2017 Dynare Team
%
% This file is part of Dynare.
%
% Dynare 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.
%
% Dynare 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 Dynare. If not, see <http://www.gnu.org/licenses/>.
if nargin<2
geometric = false;
end
if geometric
o = o/mean(o, true);
else
o = o-mean(o, false);
end
%@test:1
%$ % Define a dataset.
%$ A = repmat([1.005, 1.05], 10, 1);
%$
%$ % Instantiate a time series object and compute the mean.
%$ try
%$ ts = dseries(A);
%$ ts.center_(true);
%$ t(1) = 1;
%$ catch
%$ t = 0;
%$ end
%$
%$ if t(1)
%$ t(2) = all(all(abs(ts.data-ones(10,2))<1e-12));
%$ end
%$ T = all(t);
%@eof:1
function vs = chain(ts,us) % --*-- Unitary tests --*--
function q = chain(o, p) % --*-- Unitary tests --*--
% Chains two dseries objects.
%
% INPUTS
% - o [dseries]
% - p [dseries]
%
% OUTPUTS
% - q [dseries]
%
% REMARKS
% The two dseries objects must have common frequency and the same number of variables. Also the
% two samples must overlap.
% Copyright (C) 2014 Dynare Team
%
......@@ -17,26 +30,8 @@ function vs = chain(ts,us) % --*-- Unitary tests --*--
% You should have received a copy of the GNU General Public License
% along with Dynare. If not, see <http://www.gnu.org/licenses/>.
if vobs(ts)-vobs(us)
error(['dseries::chain: dseries objects ' inputname(1) ' and ' inputname(2) ' must have the same number of variables!'])
end
if frequency(ts)-frequency(us)
error(['dseries::chain: dseries objects ' inputname(1) ' and ' inputname(2) ' must have common frequencies!'])
end
if lastdate(ts)<firstdate(us)
error(['dseries::chain: The last date in ' inputname(1) ' (' date2string(ts.dates(end)) ') must not preceed the first date in ' inputname(2) ' (' date2string(us.dates(1)) ')!'])
end
tdx = find(sum(bsxfun(@eq,us.dates.time,ts.dates.time(end,:)),2)==2);
GrowthFactor = us.data(tdx+1:end,:)./us.data(tdx:end-1,:);
CumulatedGrowthFactors = cumprod(GrowthFactor);
vs = ts;
vs.data = [vs.data; bsxfun(@times,CumulatedGrowthFactors,vs.data(end,:))];
vs.dates = firstdate(vs):firstdate(vs)+nobs(vs);
q = copy(o);
q.chain_(p);
%@test:1
%$ try
......@@ -49,12 +44,14 @@ vs.dates = firstdate(vs):firstdate(vs)+nobs(vs);
%$ end
%$
%$ if t(1)
%$ t(2) = dassert(vs.freq,4);
%$ t(3) = dassert(vs.init.freq,4);
%$ t(4) = dassert(vs.init.time,[1950, 1]);
%$ t(5) = dassert(ts.vobs,1);
%$ t(6) = dassert(vs.nobs,6);
%$ t(7) = isequal(vs.data,transpose(1:6));
%$ t(2) = dassert(vs.freq, 4);
%$ t(3) = dassert(vs.init.freq, 4);
%$ t(4) = dassert(vs.init.time, [1950, 1]);
%$ t(5) = dassert(vs.vobs, 1);
%$ t(6) = dassert(vs.nobs, 6);
%$ t(7) = isequal(vs.data, transpose(1:6));
%$ t(8) = isequal(ts.data, transpose(1:4));
%$ t(9) = isequal(ts.init.time, [1950, 1]);
%$ end
%$
%$ T = all(t);
......
function o = chain_(o, p) % --*-- Unitary tests --*--
% Copyright (C) 2014-2017 Dynare Team
%
% This file is part of Dynare.
%
% Dynare 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.
%
% Dynare 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 Dynare. If not, see <http://www.gnu.org/licenses/>.
if vobs(o)-vobs(p)
error(['dseries::chain: dseries objects ' inputname(1) ' and ' inputname(2) ' must have the same number of variables!'])
end
if frequency(o)-frequency(p)
error(['dseries::chain: dseries objects ' inputname(1) ' and ' inputname(2) ' must have common frequencies!'])
end
if lastdate(o)<firstdate(p)
error(['dseries::chain: The last date in ' inputname(1) ' (' date2string(o.dates(end)) ') must not preceed the first date in ' inputname(2) ' (' date2string(p.dates(1)) ')!'])
end
tdx = find(sum(bsxfun(@eq, p.dates.time, o.dates.time(end,:)),2)==2);
GrowthFactor = p.data(tdx+1:end,:)./p.data(tdx:end-1,:);
CumulatedGrowthFactors = cumprod(GrowthFactor);
o.data = [o.data; bsxfun(@times,CumulatedGrowthFactors, o.data(end,:))];
o.dates = firstdate(o):firstdate(o)+nobs(o);
%@test:1
%$ try
%$ ts = dseries([1; 2; 3; 4],dates('1950Q1')) ;
%$ us = dseries([3; 4; 5; 6],dates('1950Q3')) ;
%$ ts.chain_(us);
%$ t(1) = 1;
%$ catch
%$ t(1) = 0;
%$ end
%$
%$ if t(1)
%$ t(2) = dassert(ts.freq,4);
%$ t(3) = dassert(ts.init.freq,4);
%$ t(4) = dassert(ts.init.time,[1950, 1]);
%$ t(5) = dassert(ts.vobs,1);