Contents

Introducing the FDA Toolbox

Disclaimer -- the FDA toolbox is not an official Matlab toolbox; it is a collection of privately-written functions and comes with no garuantees.

To get the toolbox

1. Visit functionaldata.org

2. Click on software and follow the link at the bottom of the page

3. Alternatively, go straight to

<ftp://ego.psych.mcgill.ca/pub/ramsay/FDAfuns/Matlab>

4. Dowload Matlabfunctions.zip

5. Follow the instruction in INSTALL.MATLAB.WIN.txt

   Linux users; the installation is analagous
   I keep my fda package in
     F://work/External/matlab_packages/fdaM

Now in order to make use of these functions, you need to add them to your path:

addpath('C://work/External/matlab_packages/fdaM')

% Alternatively, you can add the directory to your path permanently using
% the menus:
%
%     File -> Set Path ...
%
% and using the "Add Folder" option -- you do not need to select "add
% subfolders".
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Now let's load some data

load 'handwriting.mat'

% Now we would like to start smoothing the data
Warning: Name is nonexistent or not a directory: C:\work\External\matlab_packages\fdaM.

Defining a Basis

help basis

% All basis objects require a range to be specified:

basis_range = [min(fdatime) max(fdatime)];

% Starting with a B-spline basis:

breaks = linspace(basis_range(1),basis_range(2),11);

figure(1)
plot(breaks,'.')

% I'll choose cubic B-splines

norder = 4;

% And that gives

nbasis = length(breaks) + norder - 2;

% This is enough to define the basis

bspline_obj = create_bspline_basis(basis_range,nbasis,norder,breaks);

% Now that I've got a basis, I can evaluate it:

basisvals = eval_basis(fdatime,bspline_obj);

size(basisvals)

figure(2)
plot(fdatime,basisvals)

% There is also a shortcut

figure(3)
plot(bspline_obj)


% Lets look at just one

figure(4)
plot(fdatime,basisvals(:,4),'linewidth',2)
hold on
plot([breaks; breaks],[-ones(1,length(breaks)); ones(1,length(breaks))],'r--')


% Now I can evaluate some derivatives; the third argument in eval_basis
% gives an order of derivative to evaluate.

bbasisvals = eval_basis(fdatime,bspline_obj,1);
b2basisvals = eval_basis(fdatime,bspline_obj,2);

plot(fdatime,bbasisvals(:,7)/3,'m','linewidth',2)
plot(fdatime,b2basisvals(:,10)/40,'k','linewidth',2)
hold off

% Here I have had to scale the derivatives in order to make them comparable
% in size. This is important numerically -- using a very fine basis can
% mean that taking derivatives leads to numerical overflow or underflow.


% To give a comparison, let's try a linear basis

norder = 2;
nbasis = length(breaks);

bspline_obj = create_bspline_basis(basis_range,nbasis,norder,breaks);
basisvals = eval_basis(fdatime,bspline_obj);

figure(5)
plot(fdatime,basisvals)

axis([0 2.3 0 2])

% There is probably not enough resolving power in this basis, so I'll try
% more knots

norder = 4;

breaks = linspace(basis_range(1),basis_range(2),101);
nbasis = length(breaks) + norder - 2;

bspline_obj = create_bspline_basis(basis_range,nbasis,norder,breaks);

basisvals = eval_basis(fdatime,bspline_obj);

figure(6)
plot(fdatime,basisvals)
axis([0 2.3 0 1])

% Lets try a fourier basis:

nbasis_f = 10;
period = basis_range(2)-basis_range(1);

fourier_obj = create_fourier_basis(basis_range,nbasis_f,period);

fbasisvals = eval_basis(fdatime,fourier_obj);

figure(7)
plot(fdatime,fbasisvals(:,1:5));

% And maybe a polynomial basis on a centered range

nbasis_p = 10;
exponents = 0:9;    % Note that I do not need to use integer exponents here

monomial_obj = create_monomial_basis(basis_range,nbasis_p,exponents);

mbasisvals = eval_basis(fdatime,monomial_obj);

figure(8)
plot(fdatime,mbasisvals)


% Accessing aspects of a basis object

getbasisrange(bspline_obj)   % range of the basis

getnbasis(bspline_obj)       % number of basis functions

bvals = getbasismatrix(fdatime,fourier_obj);   % same as eval_basis
size(bvals)
  BASIS  Creates a functional data basis.
  CREATE_BASIS  An alternative call to CREATE_BASIS_fd.
  DISPLAY  Display a functional data basis object.
 EQ assesses whether two bases are equivalent.
  GETBASISMATRIX   Computes the basis matrix evaluated at arguments in
  GETBASISPAR   Extracts the basis parameters from basis object BASISOBJ.
  GETBASISRANGE   Extracts the range from basis object BASISOBJ.
  GETBASISTYPE   Extracts the type of basis from basis object BASISOBJ.
  GETDROPIND   Extracts the indices of basis functions to be dropped
  GETNBASIS   Extracts the type of basis from basis object BASISOBJ.
  GETQUADVALS   Extracts the quadrature points and weights
  Return values of the derivative of order NDERIV of basis 
  ISA_BASIS  checks a struct object for fields for basis objects
  Plot a basis object.
  PUQUADVALS   Enters drop indices for
  PUQUADVALS   Enters the quadrature points and weights
  PUTVALUES   Enters a cell array of values of basis functions
 TIMES for two basis objects sets up a basis suitable for 


basis is both a directory and a function.

   BASIS  Creates a functional data basis.
   Arguments:
   BASISTYPE ... a string indicating the type of basis.  This may be one of
                'Fourier', 'fourier', 'Fou', 'fou',
                'Bspline', 'bspline', 'Bsp', 'bsp',
                'pol', 'poly', 'polynomial',
                'mon', 'monom', 'monomial',
                'con', 'const', 'constant'
                'exp', 'exponen', 'exponential'
                'polyg' 'polygon', 'polygonal'
   RANGEVAL ... an array of length 2 containing the lower and upper
                boundaries for the rangeval of argument values
   NBASIS   ... the number of basis functions
   PARAMS   ... If the basis is 'fourier', this is a single number indicating
                  the period.  That is, the basis functions are periodic on
                  the interval (0,PARAMS) or any translation of it.
                If the basis is 'bspline', the values are interior points at
                  which the piecewise polynomials join.
                  Note that the number of basis functions NBASIS is equal
                  to the order of the Bspline functions plus the number of
                  interior knots, that is the length of PARAMS.
                This means that NBASIS must be at least 1 larger than the
                  length of PARAMS.
   DROPIND ... A set of indices in 1:NBASIS of basis functions to drop
                 when basis objects are arguments.  Default is [];  Note
                 that argument NBASIS is reduced by the number of indices,
                 and the derivative matrices in VALUES are also clipped.
   QUADVALS .. A NQUAD by 2 matrix.  The first column contains quadrature
                 points to be used in a fixed point quadrature.  The second
                 contains quadrature weights.  For example, for Simpson's 
                 rule for NQUAD = 7, the points are equally spaced and the 
                 weights are delta.*[1, 4, 2, 4, 2, 4, 1]/3.  DELTA is the
                 spacing between quadrature points.  The default is [].
   VALUES  ... A cell array, with entries containing the values of
                 the basis function derivatives starting with 0 and
                 going up to the highest derivative needed.  The values
                 correspond to quadrature points in QUADVALS and it is
                 up to the user to decide whether or not to multiply
                 the derivative values by the square roots of the 
                 quadrature weights so as to make numerical integration
                 a simple matrix multiplication.   
                 Values are checked against QUADVALS to ensure the correct
                 number of rows, and against NBASIS to ensure the correct
                 number of columns.
                 The default is VALUES{1} = [];
   Returns
   BASISOBJ  ... a basis object with slots
          type
          rangeval
          nbasis
          params
          dropind
          quadvals
          values
   Slot VALUES contains values of basis functions and derivatives at
    quadrature points weighted by square root of quadrature weights.
    These values are only generated as required, and only if slot
    quadvals is not empty.
 
   An alternative name for this function is CREATE_BASIS, but PARAMS argument
      must be supplied.
   Specific types of bases may be set up more conveniently using functions
   CREATE_BSPLINE_BASIS    ...  creates a b-spline basis
   CREATE_FOURIER_BASIS    ...  creates a fourier basis
   CREATE_POLYGON_BASIS    ...  creates a polygonal basis
   CREATE_MONOM_BASIS      ...  creates a monomial basis
   CREATE_POLYNOMIAL_BASIS ...  creates a polynomial basis
   CREATE_CONSTANT_BASIS   ...  creates a constant basis


ans =

        1401          13


ans =

         0    2.3000


ans =

   103


ans =

        1401          11

Creating Functional Data Objects

fd objects combine a basis with coefficients

coefs = randn(getnbasis(fourier_obj),1);

fd_obj = fd(coefs,fourier_obj);

figure(9)
plot(fd_obj)

% Alternatively

fvals = eval_fd(fdatime,fd_obj);

figure(10)
plot(fdatime,fvals);


% We can also define collections of fd objects

coefs = randn(getnbasis(fourier_obj),10);

fdnames = {'fdatime','reps','height'};

fd_obj = fd(coefs,fourier_obj,fdnames);

figure(11)
plot(fd_obj)

% I can evaluate derivatives by

fvals = eval_fd(fdatime,fd_obj,3);

size(fvals)

figure(12)
plot(fdatime,fvals);
ans =

        1401          10

Smoothing Data

% We saw in class that smoothing with a basis expansion just requires
% solving the normal equations. There is a function to do this
% automatically:

fdax_b = data2fd(fdarray(:,:,1),fdatime,bspline_obj);

figure(13)
plot(fdax_b)

figure(12)
plotfit_fd(fdarray(:,:,1),fdatime,fdax_b)

% Now if I want to plot a derivative:

figure(14)
plot(fdax_b,1)

% compare this with

figure(15)
plot(fdatime(1:1400),diff(fdarray(:,:,1)))

% Let's look at a fourrier basis:

fdax_f = data2fd(fdarray(:,:,1),fdatime,fourier_obj);

plotfit_fd(fdarray(:,:,1),fdatime,fdax_f);


% Or a monomial basis

fdax_m = data2fd(fdarray(:,:,1),fdatime,monomial_obj);

plotfit_fd(fdarray(:,:,1),fdatime,fdax_m);


% I can recover various

coef_f = getcoef(fdax_f);

basis_f = getbasis(fdax_f);

basis_f
Basis:
  Type: fourier
  Range: 0 to 2.3
  Number of basis functions: 11
  Period: 2.3

Numerical Quadrature

% For approximating quadrature; usually.

% I can set quadrature points and weights.

r_b = getbasisrange(basis_f);

m = 1000;

quadpts = linspace(r_b(1),r_b(2),2*m+1);  % Define a fine grid over the range

quadwts = ones(2*m+1,1);                  % Simpson's rule quadrature weights
quadwts(2*(1:(m-1))) = 2;
quadwts(2*(1:m)+1) = 4;

quadwts = quadwts*(r_b(2)-r_b(1))/(6*m);

basis_f = putquadvals(basis_f,[quadpts' quadwts]);

quads = getquadvals(basis_f);

size(quads)

% There are times when it may be useful to have quick access to derivatives
% of the basis values at the quadrature points.

k = 2;  % number of derivatives I'm interested in

values = cell(3,1);

for i = 0:k, values{i+1} = diag(sqrt(quadwts))*eval_basis(quadpts,basis_f,i); end

basis_f = putvalues(basis_f,values);

vals = getvalues(basis_f,1);

size(vals)

figure(16)
plot(vals)

% Note that I multiplied by the square-root of quadwts. This is because I
% will usually be interested in estimating the integral of one basis
% against another.
%
% If I have B1 and B2 evaluated at quadrature points, then their inner
% product is
%
% B1'*diag(quadwts)*B2
%
% multiplying by the square root of quadwts avoids using the middle term.
ans =

        2001           2


ans =

        2001          11

Multiple Knots

% In order to demonstrate the use of B-splines for known discontinuities

fda = [fdarrayx; fdarrayy];

fdatime2 = [fdatime; max(fdatime)+ fdatime(2) + fdatime];

% Now set up a order-4 B-splines with three knots at 2.3.

r_f = [min(fdatime2) max(fdatime2)];

breaks = linspace(r_f(1),r_f(2),201);

knots = sort([breaks 2.3*ones(1,2)]);

norder = 4;

nbasis = length(knots)+norder-2;

basis_b = create_bspline_basis(r_f,nbasis,norder,knots);

fd_obj = data2fd(fda(:,1),fdatime2,basis_b);

fda1 = eval_fd(fdatime2,fd_obj);

figure(17)
plot(fdatime2,fda1)