mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
gramSchmidt.hpp
Go to the documentation of this file.
1 /** \file gramSchmidt.hpp
2  * \brief Procedures to orthogonalize vector basis sets
3  *
4  * \author Jared R. Males (jaredmales@gmail.com)
5  *
6  * \ingroup signal_processing_files
7  *
8  */
9 
10 //***********************************************************************//
11 // Copyright 2015, 2016, 2017 Jared R. Males (jaredmales@gmail.com)
12 //
13 // This file is part of mxlib.
14 //
15 // mxlib is free software: you can redistribute it and/or modify
16 // it under the terms of the GNU General Public License as published by
17 // the Free Software Foundation, either version 3 of the License, or
18 // (at your option) any later version.
19 //
20 // mxlib is distributed in the hope that it will be useful,
21 // but WITHOUT ANY WARRANTY; without even the implied warranty of
22 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 // GNU General Public License for more details.
24 //
25 // You should have received a copy of the GNU General Public License
26 // along with mxlib. If not, see <http://www.gnu.org/licenses/>.
27 //***********************************************************************//
28 
29 #ifndef gramSchmidt_hpp
30 #define gramSchmidt_hpp
31 
32 namespace mx
33 {
34 
35 namespace sigproc
36 {
37 
38 ///Perform Gram-Schmidt ortogonalization of a basis set, and normalize the result.
39 /** Performs the stabilized Gram-Schmidt procedure on the input basis set, followed
40  * by normalization of the result.
41  *
42  * \param out [out] is the orthonormal basis set constructed from the input
43  * \param int [in] is a basis set, where each column represents one vector.
44  *
45  * \tparam progress if true, then the loop index is printed for progress reporting
46  * \tparam eigenTout is the Eigen array type of the desired output
47  * \tparam eigenTin is the Eigen array type of the input
48  *
49  * \ingroup signal_processing
50  */
51 template<int progress=0, typename eigenTout, typename eigenTin>
52 void gramSchmidt(eigenTout & out, const eigenTin & in)
53 {
54  out.resize(in.rows(), in.cols());
55 
56  out.col(0) = in.col(0);
57 
58  for(int i=1;i< in.cols(); ++i)
59  {
60  if(progress)
61  {
62  std::cout << i+1 << "/" << in.cols() << "\n";
63  }
64 
65  //out.col(i) = in.col(i);
66 
67  out.col(i) = in.col(i) - ((in.col(i).matrix().dot(out.col(0).matrix())) / (out.col(0).matrix().dot(out.col(0).matrix())) )* out.col(0);
68 
69  for(int j=1;j<i; ++j)
70  {
71  out.col(i) = out.col(i) - ((out.col(i).matrix().dot(out.col(j).matrix()))/(out.col(j).matrix().dot(out.col(j).matrix())))* out.col(j);
72  }
73  }
74 
75  for(int i=0; i<out.cols(); ++i)
76  {
77  out.col(i) = out.col(i)/ out.col(i).matrix().norm();
78  }
79 }
80 
81 
82 ///Perform Gram-Schmidt ortogonalization of a basis set on a window, and normalize the result.
83 /** Performs the stabilized Gram-Schmidt procedure on the input basis set over a window (or
84  * weight function), followed by normalization of the result.
85  *
86  * \param out [out] is the orthonormal basis set constructed from the input
87  * \param in [in] is a basis set, where each column represents one vector.
88  * \param window [in] is the window, or weighting function
89  *
90  * \tparam progress if true, then the loop index is printed for progress reporting
91  * \tparam eigenTout is the Eigen array type of the desired output
92  * \tparam eigenTin is the Eigen array type of the input
93  * \tparam eigenTWin is the Eigen array type of the window
94  *
95  * \ingroup signal_processing
96  */
97 template<int progress=0, typename eigenTout, typename eigenTin, typename eigenTWin>
98 void gramSchmidt(eigenTout & out, const eigenTin & in, const eigenTWin & window)
99 {
100  //out.resize(in.rows(), in.cols());
101 
102  out.col(0) = in.col(0);
103 
104  for(int i=1;i< in.cols(); ++i)
105  {
106  if(progress)
107  {
108  std::cout << i+1 << "/" << in.cols() << "\n";
109  }
110 
111  //out.col(i) = in.col(i);
112 
113  out.col(i) = in.col(i) - (((in.col(i)*window).matrix().dot(out.col(0).matrix())) / ( (out.col(0)*window).matrix().dot(out.col(0).matrix())) )* out.col(0);
114 
115  for(int j=1;j<i; ++j)
116  {
117  out.col(i) = out.col(i) - (( (out.col(i)*window).matrix().dot(out.col(j).matrix()))/((out.col(j)*window).matrix().dot(out.col(j).matrix())))* out.col(j);
118  }
119  }
120 
121  for(int i=0; i<out.cols(); ++i)
122  {
123  out.col(i) = out.col(i)/ (out.col(i)*window.sqrt()).matrix().norm();
124  }
125 }
126 
127 
128 
129 //Unwraps the gram schmidt coefficients to give a spectrum in terms of the original basis set
130 //Helper function for gramSchmidtSpectrum (below)
131 template<int progress=0, typename eigenT>
132 void baseSpectrum(eigenT & bspect, eigenT & gsspect)
133 {
134  bspect.resize(gsspect.rows(), gsspect.cols());
135  bspect.setZero();
136 
137 //#pragma omp parallel for
138  for(int i=0; i< gsspect.rows(); ++i)
139  {
140  bspect(i,i) = gsspect(i,i);
141 
142  for(int j=i-1; j >=0; --j)
143  {
144  bspect.row(i) -= gsspect(i,j)*bspect.row(j);
145  }
146  }
147 }
148 
149 ///Perform Gram-Schmidt ortogonalization of a basis set, and normalize the result, while recording the spectrum.
150 /** Performs the stabilized Gram-Schmidt procedure on the input basis set, followed
151  * by normalization of the result. Also records the spectrum, that is the coefficients of the linear expansion
152  * in the orginal basis set for the resultant basis set.
153  *
154  *
155  * \tparam progress if true, then the loop index is printed for progress reporting
156  * \tparam eigenTout is the Eigen array type of the output orthogonalized array
157  * \tparam eigenTout2 is the Eigen array type of the spectrum
158  * \tparam eigenTin is the Eigen array type of the input
159  *
160  * \ingroup signal_processing
161  */
162 template<int progress=0, typename eigenTout, typename eigenTout2, typename eigenTin>
163 void gramSchmidtSpectrum( eigenTout & out, ///< [out] the orthonormal basis set constructed from the input
164  eigenTout2 & spect, ///< [out] the spectrum
165  const eigenTin & in, ///< [in] a basis set, where each column represents one vector
166  typename eigenTin::Scalar normPix = 1.0 ///< [in] [optional] area of (usually number of pixels in) the orthogonal region for normalization.
167  )
168 {
169  typedef typename eigenTout::Scalar Scalar;
170 
171  out.resize(in.rows(), in.cols());
172 
173  eigenTout2 gsspect;
174 
175  gsspect.resize(in.cols(), in.cols());
176  gsspect.setZero();
177 
178  out.col(0) = in.col(0);
179  gsspect(0,0) = 1;
180 
181  for(int i=1;i< in.cols(); ++i)
182  {
183  if(progress)
184  {
185  std::cout << i+1 << "/" << in.cols() << "\n";
186  }
187 
188  gsspect(i,i)=1;
189 
190  gsspect(i,0) = ((in.col(i).matrix().dot(out.col(0).matrix())) / (out.col(0).matrix().dot(out.col(0).matrix())) );
191  out.col(i) = in.col(i) - gsspect(i,0) * out.col(0);
192 
193  for(int j=1;j<i; ++j)
194  {
195  gsspect(i,j) = ((out.col(i).matrix().dot(out.col(j).matrix()))/(out.col(j).matrix().dot(out.col(j).matrix())));
196  out.col(i) = out.col(i) - gsspect(i,j)* out.col(j);
197  }
198  }
199 
200  //Here we unwrap the gram schmidt coefficients, giving us the coefficients in the original basis
201  baseSpectrum(spect, gsspect);
202 
203  Scalar norm;
204 
205  for(int i=0; i<out.cols(); ++i)
206  {
207  norm = sqrt(out.col(i).square().sum() / normPix);
208 
209  out.col(i) /= norm;
210  //spect.row(i) /= norm;
211  }
212 }
213 
214 
215 
216 } //namespace sigproc
217 } //namespace mx
218 
219 #endif //gramSchmidt_hpp
220 
221 
void gramSchmidt(eigenTout &out, const eigenTin &in, const eigenTWin &window)
Perform Gram-Schmidt ortogonalization of a basis set on a window, and normalize the result.
Definition: gramSchmidt.hpp:98
void gramSchmidtSpectrum(eigenTout &out, eigenTout2 &spect, const eigenTin &in, typename eigenTin::Scalar normPix=1.0)
Perform Gram-Schmidt ortogonalization of a basis set, and normalize the result, while recording the s...
The mxlib c++ namespace.
Definition: mxError.hpp:107