mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
Loading...
Searching...
No Matches
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#include <iostream>
33
34namespace mx
35{
36namespace sigproc
37{
38
39/// Perform Gram-Schmidt ortogonalization of a basis set, and normalize the result.
40/** Performs the stabilized Gram-Schmidt procedure on the input basis set, which
41 * is the columns of the array. Optionally the output is normalized.
42 *
43 * \tparam progress if true, then the loop index is printed for progress reporting
44 * \tparam eigenTout is the Eigen array type of the desired output
45 * \tparam eigenTin is the Eigen array type of the input
46 *
47 * \ingroup signal_processing
48 */
49template <int progress = 0, typename eigenTout, typename eigenTin>
50void gramSchmidt( eigenTout &out, ///< [out] the orthonormal basis set constructed from the input
51 const eigenTin &in, ///< [in] a basis set, where each column represents one vector.
52 bool normalize = true ///< [in] [optional] whether or not to normalize the output
53)
54{
55 out.resize( in.rows(), in.cols() );
56
57 out.col( 0 ) = in.col( 0 );
58
59 for( int i = 1; i < in.cols(); ++i )
60 {
61 if( progress )
62 {
63 std::cout << i + 1 << "/" << in.cols() << "\n";
64 }
65
66 // out.col(i) = in.col(i);
67
68 out.col( i ) = in.col( i ) - ( ( in.col( i ).matrix().dot( out.col( 0 ).matrix() ) ) /
69 ( out.col( 0 ).matrix().dot( out.col( 0 ).matrix() ) ) ) *
70 out.col( 0 );
71
72 for( int j = 1; j < i; ++j )
73 {
74 out.col( i ) = out.col( i ) - ( ( out.col( i ).matrix().dot( out.col( j ).matrix() ) ) /
75 ( out.col( j ).matrix().dot( out.col( j ).matrix() ) ) ) *
76 out.col( j );
77 }
78 }
79
80 if( normalize )
81 {
82 for( int i = 0; i < out.cols(); ++i )
83 {
84 out.col( i ) = out.col( i ) / out.col( i ).matrix().norm();
85 }
86 }
87}
88
89/// Perform Gram-Schmidt ortogonalization of a basis set on a window, and normalize the result.
90/** Performs the stabilized Gram-Schmidt procedure on the input basis set over a window (or
91 * weight function), followed by normalization of the result.
92 *
93 * \param out [out] is the orthonormal basis set constructed from the input
94 * \param in [in] is a basis set, where each column represents one vector.
95 * \param window [in] is the window, or weighting function
96 *
97 * \tparam progress if true, then the loop index is printed for progress reporting
98 * \tparam eigenTout is the Eigen array type of the desired output
99 * \tparam eigenTin is the Eigen array type of the input
100 * \tparam eigenTWin is the Eigen array type of the window
101 *
102 * \ingroup signal_processing
103 */
104template <int progress = 0, typename eigenTout, typename eigenTin, typename eigenTWin>
105void gramSchmidt( eigenTout &out, const eigenTin &in, const eigenTWin &window )
106{
107 // out.resize(in.rows(), in.cols());
108
109 out.col( 0 ) = in.col( 0 );
110
111 for( int i = 1; i < in.cols(); ++i )
112 {
113 if( progress )
114 {
115 std::cout << i + 1 << "/" << in.cols() << "\n";
116 }
117
118 // out.col(i) = in.col(i);
119
120 out.col( i ) = in.col( i ) - ( ( ( in.col( i ) * window ).matrix().dot( out.col( 0 ).matrix() ) ) /
121 ( ( out.col( 0 ) * window ).matrix().dot( out.col( 0 ).matrix() ) ) ) *
122 out.col( 0 );
123
124 for( int j = 1; j < i; ++j )
125 {
126 out.col( i ) = out.col( i ) - ( ( ( out.col( i ) * window ).matrix().dot( out.col( j ).matrix() ) ) /
127 ( ( out.col( j ) * window ).matrix().dot( out.col( j ).matrix() ) ) ) *
128 out.col( j );
129 }
130 }
131
132 for( int i = 0; i < out.cols(); ++i )
133 {
134 out.col( i ) = out.col( i ) / ( out.col( i ) * window.sqrt() ).matrix().norm();
135 }
136}
137
138// Unwraps the gram schmidt coefficients to give a spectrum in terms of the original basis set
139// Helper function for gramSchmidtSpectrum (below)
140template <int progress = 0, typename eigenT>
141void baseSpectrum( eigenT &bspect, eigenT &gsspect )
142{
143 bspect.resize( gsspect.rows(), gsspect.cols() );
144 bspect.setZero();
145
146 // #pragma omp parallel for
147 for( int i = 0; i < gsspect.rows(); ++i )
148 {
149 bspect( i, i ) = gsspect( i, i );
150
151 for( int j = i - 1; j >= 0; --j )
152 {
153 bspect.row( i ) -= gsspect( i, j ) * bspect.row( j );
154 }
155 }
156}
157
158/// Perform Gram-Schmidt ortogonalization of a basis set, and normalize the result, while recording the spectrum.
159/** Performs the stabilized Gram-Schmidt procedure on the input basis set, followed
160 * by normalization of the result. Also records the spectrum, that is the coefficients of the linear expansion
161 * in the orginal basis set for the resultant basis set.
162 *
163 *
164 * \tparam progress if true, then the loop index is printed for progress reporting
165 * \tparam eigenTout is the Eigen array type of the output orthogonalized array
166 * \tparam eigenTout2 is the Eigen array type of the spectrum
167 * \tparam eigenTin is the Eigen array type of the input
168 *
169 * \ingroup signal_processing
170 */
171template <int progress = 0, typename eigenTout, typename eigenTout2, typename eigenTin>
173 eigenTout &out, ///< [out] the orthonormal basis set constructed from the input
174 eigenTout2 &spect, ///< [out] the spectrum
175 const eigenTin &in, ///< [in] a basis set, where each column represents one vector
176 typename eigenTin::Scalar normPix = 0.0 /**< [in] [optional] area of (usually number of pixels in) the orthogonal
177 region for normalization. If 0 the basis is not renormalized */
178)
179{
180 typedef typename eigenTout::Scalar Scalar;
181
182 out.resize( in.rows(), in.cols() );
183
184 eigenTout2 gsspect;
185
186 gsspect.resize( in.cols(), in.cols() );
187 gsspect.setZero();
188
189 out.col( 0 ) = in.col( 0 );
190 gsspect( 0, 0 ) = 1;
191
192 for( int i = 1; i < in.cols(); ++i )
193 {
194 if( progress )
195 {
196 std::cout << i + 1 << "/" << in.cols() << "\n";
197 }
198
199 gsspect( i, i ) = 1;
200
201 gsspect( i, 0 ) = ( ( in.col( i ).matrix().dot( out.col( 0 ).matrix() ) ) /
202 ( out.col( 0 ).matrix().dot( out.col( 0 ).matrix() ) ) );
203 out.col( i ) = in.col( i ) - gsspect( i, 0 ) * out.col( 0 );
204
205 for( int j = 1; j < i; ++j )
206 {
207 gsspect( i, j ) = ( ( out.col( i ).matrix().dot( out.col( j ).matrix() ) ) /
208 ( out.col( j ).matrix().dot( out.col( j ).matrix() ) ) );
209 out.col( i ) = out.col( i ) - gsspect( i, j ) * out.col( j );
210 }
211 }
212
213 // Here we unwrap the gram schmidt coefficients, giving us the coefficients in the original basis
214 baseSpectrum( spect, gsspect );
215
216 if( normPix > 0 )
217 {
218 Scalar norm;
219
220 for( int i = 0; i < out.cols(); ++i )
221 {
222 norm = sqrt( out.col( i ).square().sum() / normPix );
223
224 out.col( i ) /= norm;
225 // spect.row(i) /= norm;
226 }
227 }
228}
229
230} // namespace sigproc
231} // namespace mx
232
233#endif // gramSchmidt_hpp
void gramSchmidtSpectrum(eigenTout &out, eigenTout2 &spect, const eigenTin &in, typename eigenTin::Scalar normPix=0.0)
Perform Gram-Schmidt ortogonalization of a basis set, and normalize the result, while recording the s...
void gramSchmidt(eigenTout &out, const eigenTin &in, bool normalize=true)
Perform Gram-Schmidt ortogonalization of a basis set, and normalize the result.
The mxlib c++ namespace.
Definition mxlib.hpp:37