IRootLab
An Open-Source MATLAB toolbox for vibrational biospectroscopy
bc_poly.m
Go to the documentation of this file.
1 %> @ingroup maths
2 %> @file
3 %> @brief Polynomial baseline correction
4 %>
5 %> <h3>References:</h3>
6 %> [1] Beier BD, Berger AJ. Method for automated background subtraction from Raman spectra containing known contaminants.
7 %> The Analyst. 2009; 134(6):1198-202. Available at: http://www.ncbi.nlm.nih.gov/pubmed/19475148.
8 %
9 %> @param X [no][nf] matrix
10 %> @param order polynomial order
11 %> @param epsilon tolerance to stop iterations. If zero or no value given, will default to <code>sqrt(1/30*nf)</code>
12 %> @param Xcont [no_cont][nf] matrix containing contaminants to be eliminated
13 %> @return Corrected matrix
14 function X = bc_poly(X, order, epsilon, Xcont)
15 
16 [no, nf] = size(X);
17 
18 if ~exist('epsilon', 'var') || epsilon <= 0
19  % epsilon will be compared to a vector norm. If we assume the error at all elements to have the same importance, it
20  % the norm of the error will be something like sqrt(nf*error_i)
21  % For the tolerance to be 1 when nf = 1500 (empirically found to work) the formula below is set.
22  epsilon = sqrt(1/90*nf);
23 end;
24 
25 flag_cont = exist('Xcont', 'var') && ~isempty(Xcont); % take contaminants into account?
26 if ~flag_cont
27  Xcont = [];
28  no_cont = 0;
29 end;
30 
31 x = 1:nf; % x-values to be powered as columns of a design matrix
32 
33 if flag_cont
34  % If contaminants are present, mounts a design matrix containing powers
35  % of x and the contaminants as different columns
36  no_cont = size(Xcont, 1);
37  M = zeros(nf, order+1+no_cont);
38  M(:, no_cont) = Xcont';
39 
40 end;
41 
42  for i = 1:order+1
43  M(:, no_cont+i) = x'.^(i-1);
44  end;
45  MM = M'*M;
46 % end;
47 
48 
49 ipro = progress2_open('Polynomial baseline correction', [], 0, no);
50 for i = 1:no
51  y = X(i, :);
52  y_save = y;
53 
54  flag_first = 1;
55  while 1
56 % if ~flag_cont
57 % % I no contaminant is present, uses MATLAB's polyfit rather
58 % % than least-squares solution. I didn't check which is faster.
59 % p = polyfit(x, y, order);
60 % yp = polyval(p, x);
61 % else
62  % all-in-one least-squares solution and linear combination of the columns of M
63 
64  % (29/03/2011) Least-Squares solution is faster than polyfit()
65 
66  warning off; %#ok<*WNOFF>
67  try
68  yp = (M*(MM\(M'*y')))';
69  warning on; %#ok<*WNON>
70  catch ME
71  warning on;
72  rethrow(ME);
73  end;
74 % end;
75 
76  % y for next iteration will be a chopped-peak version of y
77  y = min(y, yp);
78 
79  if ~flag_first
80  if norm(y-y_previous) < epsilon
81  break;
82  end;
83  else
84  flag_first = 0;
85  end;
86 
87  y_previous = y;
88  end;
89 
90 
91  X(i, :) = y_save-yp;
92 
93 
94  ipro = progress2_change(ipro, [], [], i);
95 end;
96 progress2_close(ipro);
function progress2_change(in prgrss, in title, in perc, in i, in n)
function bc_poly(in X, in order, in epsilon, in Xcont)
function progress2_close(in prgrss)
Analysis Session (AS) base class.
Definition: as.m:6