Skip to content

Commit 2fa1361

Browse files
authored
Merge pull request #1685 from jcollfont/master
Closes #1346, closes #1106, closes #956, closes #934, closes #1025, closes #1171.
2 parents ff43353 + 0ea4de8 commit 2fa1361

File tree

43 files changed

+5876
-1119
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+5876
-1119
lines changed

src/Core/Algorithms/Factory/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ ENDIF()
7171
TARGET_LINK_LIBRARIES(Algorithms_Factory
7272
Algorithms_Base
7373
Algorithms_BrainStimulator
74+
Algorithms_Legacy_Inverse
7475
Core_Algorithms_Legacy_Fields
7576
Algorithms_Math
7677
Algorithms_DataIO

src/Core/Algorithms/Legacy/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,6 @@ ADD_SUBDIRECTORY(Fields)
3030
ADD_SUBDIRECTORY(DataIO)
3131
ADD_SUBDIRECTORY(Converter)
3232
ADD_SUBDIRECTORY(Forward)
33+
ADD_SUBDIRECTORY(Inverse)
3334
ADD_SUBDIRECTORY(Geometry)
3435
ADD_SUBDIRECTORY(FiniteElements)
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
#
2+
# For more information, please see: http://software.sci.utah.edu
3+
#
4+
# The MIT License
5+
#
6+
# Copyright (c) 2015 Scientific Computing and Imaging Institute,
7+
# University of Utah.
8+
#
9+
#
10+
# Permission is hereby granted, free of charge, to any person obtaining a
11+
# copy of this software and associated documentation files (the "Software"),
12+
# to deal in the Software without restriction, including without limitation
13+
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
14+
# and/or sell copies of the Software, and to permit persons to whom the
15+
# Software is furnished to do so, subject to the following conditions:
16+
#
17+
# The above copyright notice and this permission notice shall be included
18+
# in all copies or substantial portions of the Software.
19+
#
20+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21+
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23+
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25+
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26+
# DEALINGS IN THE SOFTWARE.
27+
#
28+
29+
SET(Algorithms_Legacy_Inverse_SRCS
30+
TikhonovAlgoAbstractBase.cc
31+
TikhonovImpl.cc
32+
SolveInverseProblemWithStandardTikhonovImpl.cc
33+
SolveInverseProblemWithTikhonovSVD_impl.cc
34+
SolveInverseProblemWithTikhonovTSVD_impl.cc
35+
)
36+
37+
SET(Algorithms_Legacy_Inverse_HEADERS
38+
TikhonovAlgoAbstractBase.h
39+
TikhonovImpl.h
40+
SolveInverseProblemWithStandardTikhonovImpl.h
41+
SolveInverseProblemWithTikhonovSVD_impl.h
42+
SolveInverseProblemWithTikhonovTSVD_impl.h
43+
share.h
44+
)
45+
46+
SCIRUN_ADD_LIBRARY(Algorithms_Legacy_Inverse
47+
${Algorithms_Legacy_Inverse_HEADERS}
48+
${Algorithms_Legacy_Inverse_SRCS}
49+
)
50+
51+
TARGET_LINK_LIBRARIES(Algorithms_Legacy_Inverse
52+
Core_Datatypes #matrices
53+
Core_Datatypes_Legacy_Field
54+
Algorithms_Math
55+
Core_Geometry_Primitives #vectors
56+
Core_Basis #field basis
57+
Core_Algorithms_Legacy_Fields
58+
Algorithms_Base
59+
${SCI_BOOST_LIBRARY}
60+
)
61+
62+
IF(BUILD_SHARED_LIBS)
63+
ADD_DEFINITIONS(-DBUILD_Algorithms_Legacy_Inverse)
64+
ENDIF(BUILD_SHARED_LIBS)
65+
66+
#SCIRUN_ADD_TEST_DIR(Tests)
Lines changed: 315 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,315 @@
1+
/*
2+
For more information, please see: http://software.sci.utah.edu
3+
4+
The MIT License
5+
6+
Copyright (c) 2015 Scientific Computing and Imaging Institute,
7+
University of Utah.
8+
9+
10+
Permission is hereby granted, free of charge, to any person obtaining a
11+
copy of this software and associated documentation files (the "Software"),
12+
to deal in the Software without restriction, including without limitation
13+
the rights to use, copy, modify, merge, publish, distribute, sublicense,
14+
and/or sell copies of the Software, and to permit persons to whom the
15+
Software is furnished to do so, subject to the following conditions:
16+
17+
The above copyright notice and this permission notice shall be included
18+
in all copies or substantial portions of the Software.
19+
20+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21+
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23+
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26+
DEALINGS IN THE SOFTWARE.
27+
*/
28+
29+
// File : SolveInverseProblemWithTikhonov.cc
30+
// Author : Jaume Coll-Font, Moritz Dannhauer, Ayla Khan, Dan White
31+
// Date : September 06th, 2017 (last update)
32+
33+
#include <boost/bind.hpp>
34+
#include <boost/lexical_cast.hpp>
35+
36+
#include <Core/Algorithms/Legacy/Inverse/TikhonovAlgoAbstractBase.h>
37+
#include <Core/Algorithms/Legacy/Inverse/SolveInverseProblemWithStandardTikhonovImpl.h>
38+
39+
#include <Core/Datatypes/Matrix.h>
40+
#include <Core/Datatypes/DenseMatrix.h>
41+
#include <Core/Datatypes/DenseColumnMatrix.h>
42+
#include <Core/Datatypes/SparseRowMatrix.h>
43+
#include <Core/Datatypes/MatrixTypeConversions.h>
44+
45+
#include <Core/Algorithms/Base/AlgorithmPreconditions.h>
46+
47+
#include <Core/Logging/LoggerInterface.h>
48+
#include <Core/Utils/Exception.h>
49+
50+
using namespace SCIRun;
51+
using namespace SCIRun::Core;
52+
using namespace SCIRun::Core::Datatypes;
53+
using namespace SCIRun::Core::Logging;
54+
using namespace SCIRun::Core::Algorithms;
55+
using namespace SCIRun::Core::Algorithms::Inverse;
56+
57+
58+
/////////////////////////
59+
///////// compute Inverse solution
60+
DenseMatrix SolveInverseProblemWithStandardTikhonovImpl::computeInverseSolution( double lambda, bool inverseCalculation) const
61+
{
62+
//............................
63+
// OPERATIONS PERFORMED IN THIS SECTION:
64+
// The description of these operations is general and applies to underdetermined or overdetermined equations depending on the definition given to M1, M2, M3 and y (look at the selection of underdetermined or overdetermined for details)
65+
//............................
66+
//
67+
// G = (M1 + lambda^2 * M2)
68+
// b = G^-1 * y
69+
// x = M3 * b
70+
//
71+
// A^-1 = M3 * G^-1 * M4
72+
//...........................................................................................................
73+
const int sizeB = M1.ncols();
74+
const int sizeSolution = M3.nrows();
75+
const int numTimeSamples = y.ncols();
76+
DenseMatrix inverseG(sizeB,sizeB);
77+
78+
DenseMatrix b(sizeB);
79+
DenseMatrix solution(sizeSolution,numTimeSamples);
80+
DenseMatrix G;
81+
82+
G = M1 + lambda * lambda * M2;
83+
84+
b = G.lu().solve(y).eval();
85+
86+
solution = M3 * b;
87+
88+
// if (inverseCalculation)
89+
// {
90+
// inverseG = G.inverse().eval();
91+
// inverseMatrix_.reset( new DenseMatrix( (M3 * inverseG) * M4) );
92+
// }
93+
// inverseSolution_.reset(new DenseMatrix(solution));
94+
return solution;
95+
}
96+
//////// fi compute inverse solution
97+
////////////////////////
98+
99+
/////// precomputeInverseMatrices
100+
///////////////
101+
void SolveInverseProblemWithStandardTikhonovImpl::preAlocateInverseMatrices(const SCIRun::Core::Datatypes::DenseMatrix& forwardMatrix_, const SCIRun::Core::Datatypes::DenseMatrix& measuredData_ , const SCIRun::Core::Datatypes::DenseMatrix& sourceWeighting_, const SCIRun::Core::Datatypes::DenseMatrix& sensorWeighting_, const int regularizationChoice_, const int regularizationSolutionSubcase_, const int regularizationResidualSubcase_)
102+
{
103+
104+
// TODO: use DimensionMismatch exception where appropriate
105+
// DIMENSION CHECK!!
106+
const int M = forwardMatrix_.nrows();
107+
const int N = forwardMatrix_.ncols();
108+
109+
// PREALOCATE VARIABLES and MATRICES
110+
DenseMatrix forward_transpose = forwardMatrix_.transpose();
111+
112+
// get Parameters
113+
// auto regularizationChoice_ = get(regularizationChoice).toInt();
114+
// auto regularizationChoice_ = get(regularizationSolutionSubcase).toInt();
115+
// auto regularizationResidualSubcase_ = get(regularizationResidualSubcase).toInt();
116+
117+
// select underdetermined case if user decides so or the option is set to automatic and number of measurements is smaller than number of unknowns.
118+
if ( ( (M < N) && (regularizationChoice_ == TikhonovAlgoAbstractBase::automatic) ) || (regularizationChoice_ == TikhonovAlgoAbstractBase::underdetermined))
119+
{
120+
//UNDERDETERMINED CASE
121+
//.........................................................................
122+
// OPERATE ON DATA:
123+
// Compute X = (R^T * R)^-1 * A^T (A * (R^T*R)^-1 * A^T + LAMBDA * LAMBDA * (C^T*C)^-1 ) * Y
124+
// X = M3 * G^-1 * (M4) * Y
125+
// Will set:
126+
// M1 = A * (R^T*R)^-1 * A^T
127+
// M2 = (C^T*C)^-1
128+
// M3 = (R * R^T)^-1 * A^T
129+
// M4 = identity
130+
// y = measuredData
131+
//.........................M1,................................................
132+
133+
DenseMatrix RRtr(N,N);
134+
DenseMatrix iRRtr(N,N);
135+
DenseMatrix CCtr(M,M);
136+
DenseMatrix iCCtr(M,M);
137+
138+
// DEFINITIONS AND PREALOCATION OF SOURCE REGULARIZATION MATRIX 'R'
139+
// if R does not exist, set as identity of size equal to N (columns of fwd matrix)
140+
if (true)//(&sourceWeighting_==NULL)
141+
{
142+
RRtr = DenseMatrix::Identity(N, N);
143+
iRRtr = RRtr;
144+
}
145+
else
146+
{
147+
148+
// if provided the non-squared version of R
149+
if( regularizationSolutionSubcase_ == TikhonovAlgoAbstractBase::solution_constrained )
150+
{
151+
RRtr = sourceWeighting_.transpose() * sourceWeighting_;
152+
}
153+
// otherwise, if the source regularization is provided as the squared version (RR^T)
154+
else if ( regularizationSolutionSubcase_ == TikhonovAlgoAbstractBase::solution_constrained_squared )
155+
{
156+
RRtr = sourceWeighting_;
157+
}
158+
159+
// check if squared regularization matrix is invertible
160+
auto LURRtr = RRtr.fullPivLu();
161+
if ( !LURRtr.isInvertible() )
162+
{
163+
164+
THROW_ALGORITHM_INPUT_ERROR_SIMPLE("Regularization matrix in the source space is not invertible.");
165+
}
166+
167+
// COMPUTE inverse
168+
iRRtr = LURRtr.inverse().eval();
169+
170+
}
171+
172+
173+
// DEFINITIONS AND PREALOCATIONS OF MEASUREMENTS COVARIANCE MATRIX 'C'
174+
// if C does not exist, set as identity of size equal to M (rows of fwd matrix)
175+
if (true)//(&sensorWeighting_==NULL)
176+
{
177+
CCtr = DenseMatrix::Identity(M, M);
178+
iCCtr = CCtr;
179+
180+
}
181+
else
182+
{
183+
// if measurement covariance matrix provided in non-squared form
184+
if (regularizationResidualSubcase_ == TikhonovAlgoAbstractBase::residual_constrained)
185+
{
186+
// check that the matrix is of appropriate size (equal number of rows as rows in fwd matrix)
187+
if(M != sensorWeighting_.ncols())
188+
{
189+
CCtr = sensorWeighting_.transpose() * sensorWeighting_;
190+
}
191+
}
192+
// otherwise if the source covariance matrix is provided in squared form
193+
else if ( regularizationResidualSubcase_ == TikhonovAlgoAbstractBase::residual_constrained_squared )
194+
{
195+
CCtr = sensorWeighting_;
196+
}
197+
198+
// check if squared regularization matrix is invertible
199+
auto LUCCtr = CCtr.fullPivLu();
200+
if ( !LUCCtr.isInvertible() )
201+
{
202+
THROW_ALGORITHM_INPUT_ERROR_SIMPLE("Residual covariance matrix is not invertible.");
203+
}
204+
iCCtr = LUCCtr.inverse().eval();
205+
206+
207+
208+
}
209+
210+
// DEFINE M1 = (A * (R^T*R)^-1 * A^T MATRIX FOR FASTER COMPUTATION
211+
DenseMatrix RAtr = iRRtr * forward_transpose;
212+
M1 = forwardMatrix_ * RAtr;
213+
214+
// DEFINE M2 = (C^TC)^-1
215+
M2 = iCCtr;
216+
217+
// DEFINE M3 = (R^TR)^-1 * A^T
218+
M3 = RAtr;
219+
220+
// DEFINE M4 = identity (size of number of measurements)
221+
M4 = DenseMatrix::Identity(M, N);
222+
223+
// DEFINE measurement vector
224+
y = measuredData_;
225+
226+
227+
228+
}
229+
//OVERDETERMINED CASE,
230+
//similar procedure as underdetermined case (documentation comments similar, see above)
231+
else if ( ( (regularizationChoice_ == TikhonovAlgoAbstractBase::automatic) && (M>=N) ) || (regularizationChoice_ == TikhonovAlgoAbstractBase::overdetermined) )
232+
{
233+
//.........................................................................
234+
// OPERATE ON DATA:
235+
// Computes X = (A^T * C^T * C * A + LAMBDA * LAMBDA * R^T * R) * A^T * C^T * C * Y
236+
// X = (M3) * G^-1 * M4 * Y
237+
//.........................................................................
238+
// Will set:
239+
// M1 = A * C^T*C * A^T
240+
// M2 = R^T*R
241+
// M3 = identity
242+
// M4 = A^TC^TC
243+
// y = A * C^T*C * measuredData
244+
//.........................................................................
245+
246+
247+
// prealocations
248+
DenseMatrix RtrR(N,N);
249+
DenseMatrix CtrC(M,M);
250+
251+
252+
// DEFINITIONS AND PREALOCATION OF SOURCE REGULARIZATION MATRIX 'R'
253+
254+
// if R does not exist, set as identity of size equal to N (columns of fwd matrix)
255+
if (true)//(&sourceWeighting_==NULL)
256+
{
257+
RtrR = DenseMatrix::Identity(N, N);
258+
}
259+
else
260+
{
261+
// if provided the non-squared version of R
262+
if( regularizationSolutionSubcase_ == TikhonovAlgoAbstractBase::solution_constrained )
263+
{
264+
RtrR = sourceWeighting_.transpose() * sourceWeighting_;
265+
}
266+
// otherwise, if the source regularization is provided as the squared version (RR^T)
267+
else if ( regularizationSolutionSubcase_ == TikhonovAlgoAbstractBase::solution_constrained_squared )
268+
{
269+
RtrR = sourceWeighting_;
270+
}
271+
}
272+
273+
274+
// DEFINITIONS AND PREALOCATIONS OF MEASUREMENTS COVARIANCE MATRIX 'C'
275+
// if C does not exist, set as identity of size equal to M (rows of fwd matrix)
276+
if (true)//(&sensorWeighting_==NULL)
277+
{
278+
CtrC = DenseMatrix::Identity(M, M);
279+
}
280+
else
281+
{
282+
// if measurement covariance matrix provided in non-squared form
283+
if (regularizationResidualSubcase_ == TikhonovAlgoAbstractBase::residual_constrained)
284+
{
285+
CtrC = sensorWeighting_.transpose() * sensorWeighting_;
286+
}
287+
// otherwise if the source covariance matrix is provided in squared form
288+
else if ( regularizationResidualSubcase_ == TikhonovAlgoAbstractBase::residual_constrained_squared )
289+
{
290+
CtrC = sensorWeighting_;
291+
}
292+
293+
}
294+
295+
// DEFINE M1 = (A * (R*R^T)^-1 * A^T MATRIX FOR FASTER COMPUTATION
296+
DenseMatrix CtrCA = CtrC * (forwardMatrix_);
297+
M1 = forward_transpose * CtrCA;
298+
299+
// DEFINE M2 = (CC^T)^-1
300+
M2 = RtrR;
301+
302+
// DEFINE M3 = identity (size of number of measurements)
303+
M3 = DenseMatrix::Identity(N, N);
304+
305+
// DEFINT M4 = A^T* C^T * C
306+
M4 = CtrCA.transpose();
307+
308+
// DEFINE measurement vector
309+
y = CtrCA.transpose() * measuredData_;
310+
311+
}
312+
313+
}
314+
//////// End of prealocation of matrices
315+
////////////

0 commit comments

Comments
 (0)