29 #include "tnt/tnt_array1d_utils.h"
109 m_filePattern = pattern;
174 double &resid, GMatrix &atai,
AffineRadio &affrad) {
183 double rshift = radio.Shift();
184 double rgain = radio.Gain();
186 int maxPnts((pattern.
Samples()-2) * (pattern.
Lines()-2));
187 GMatrix a(maxPnts, 8);
188 GVector lvec(maxPnts);
193 for(
int line = 2 ; line < pattern.
Lines() ; line++) {
194 for(
int samp = 2; samp < pattern.
Samples() ; samp++) {
196 if(!pattern.
IsValid(samp, line))
continue;
197 if(!subsearch.
IsValid(samp, line))
continue;
198 if(!subsearch.
IsValid(samp + 1, line))
continue;
199 if(!subsearch.
IsValid(samp - 1, line))
continue;
200 if(!subsearch.
IsValid(samp, line - 1))
continue;
201 if(!subsearch.
IsValid(samp, line + 1))
continue;
204 double x0 = (double)(samp - tackSamp);
205 double y0 = (double)(line - tackLine);
208 double gxtemp = subsearch.
GetValue(samp + 1, line) -
210 double gytemp = subsearch.
GetValue(samp, line + 1) -
214 a[npts][1] = gxtemp * x0;
215 a[npts][2] = gxtemp * y0;
217 a[npts][4] = gytemp * x0;
218 a[npts][5] = gytemp * y0;
220 a[npts][7] = subsearch.
GetValue(samp, line);
222 double ell = pattern.
GetValue(samp, line) -
223 (((1.0 + rgain) * subsearch.
GetValue(samp, line)) +
227 resid += (ell * ell);
235 std::ostringstream mess;
237 <<
") criteria not met (" << npts <<
")";
238 return (
logError(NotEnoughPoints, mess.str().c_str()));
243 for(
int i = 0 ; i < 8 ; i++) {
244 for(
int j = 0 ; j < 8 ; j++) {
246 for (
int k = 0 ; k < npts ; k++) {
247 temp += (a[k][i] * a[k][j]);
257 GMatrix b = Identity(8);
259 atai =
Cholsl(atai, p, b, x);
262 QString mess =
"Cholesky Failed:: " + ie.
toString();
263 return (
logError(CholeskyFailed, mess));
268 for (
int i = 0 ; i < 8 ; i++) {
270 for (
int k = 0 ; k < npts ; k++) {
271 temp += a[k][i] * lvec[k];
276 GVector alpha(8, 0.0);
277 for (
int i = 0 ; i < 8 ; i++) {
278 for (
int k = 0 ; k < 8 ; k++) {
279 alpha[i] += atai[i][k] * atl[k];
287 QString mess =
"Affine failed: " + ie.
toString();
288 return (
logError(AffineNotInvertable, mess));
306 const GMatrix &atai) {
309 results.m_npts = npts;
314 for(
int r = 0 ; r < 8 ; r++) {
315 for(
int c = 0 ; c < 8 ; c++) {
316 kmat[r][c] = variance * atai[r][c];
319 results.m_variance = variance;
324 skmat[0][0] = kmat[0][0];
325 skmat[0][1] = kmat[0][3];
326 skmat[1][0] = kmat[3][0];
327 skmat[1][1] = kmat[3][3];
330 Jacobi(skmat, eigen, skmat);
332 for (
int i = 0 ; i < 2 ; i++) {
333 results.m_sevals[i] = eigen[i];
334 results.m_kmat[i] = kmat[i*3][i*3];
338 QString errmsg =
"Eigen Solution Failed:: " + ie.
toString();
339 results.m_status =
logError(EigenSolutionFailed, errmsg);
343 results.m_status = 0;
361 GMatrix aa = a.copy();
364 for(
int i = 0 ; i < nrows ; i++) {
365 for(
int j = i ; j < ncols ; j++) {
366 double sum = aa[i][j];
367 for(
int k = i-1 ; k >= 0 ; k--) {
368 sum -= (aa[i][k] * aa[j][k]);
374 "Choldc failed - matrix not postive definite",
380 aa[j][i] = sum / p[i];
400 const GMatrix &x)
const {
401 assert(b.dim1() == x.dim1());
402 assert(b.dim2() == x.dim2());
403 assert(p.dim1() == b.dim2());
408 GMatrix xout = x.copy();
409 for(
int j = 0 ; j < nrows ; j++) {
411 for(
int i = 0 ; i < ncols ; i++) {
412 double sum = b[j][i];
413 for(
int k = i-1 ; k >= 0 ; k--) {
414 sum -= (a[i][k] * xout[j][k]);
416 xout[j][i] = sum / p[i];
419 for (
int i = ncols-1 ; i >= 0 ; i--) {
420 double sum = xout[j][i];
421 for(
int k = i+1 ; k < ncols ; k++) {
422 sum -= (a[k][i] * xout[j][k]);
424 xout[j][i] = sum / p[i];
444 GMatrix &evecs,
const int &MaxIters)
const {
448 GMatrix v = Identity(nrows);
449 GVector d(nrows),b(nrows), z(nrows);
451 for(
int ip = 0 ; ip < nrows ; ip++) {
457 double n2(
double(nrows) *
double(nrows));
458 GMatrix aa = a.copy();
460 for ( ; nrot < MaxIters ; nrot++) {
462 for(
int ip = 0 ; ip < nrows-1 ; ip++) {
463 for(
int iq = ip+1 ; iq < nrows ; iq++) {
464 sm += fabs(aa[ip][iq]);
475 double thresh = (nrot < 3) ? (0.2 * sm/n2 ): 0.0;
476 for (
int ip = 0 ; ip < nrows-1 ; ip++) {
477 for (
int iq = ip+1 ; iq < nrows ; iq++) {
478 double g = 100.0 * fabs(aa[ip][iq]);
480 ( (fabs(d[ip]+g) == fabs(d[ip])) ) &&
481 ( (fabs(d[iq]+g) == fabs(d[iq])) ) ) {
484 else if ( fabs(aa[ip][iq]) > thresh ) {
485 double h = d[iq] - d[ip];
487 if ( (fabs(h)+g) == fabs(h) ) {
491 double theta = 0.5 * h / aa[ip][iq];
492 t = 1.0 / (fabs(theta) + sqrt(1.0 + theta * theta));
493 if (theta < 0.0) t = -1.0 * t;
495 double c = 1./sqrt(1.0 + t * t);
497 double tau = s / (1.0 + c);
507 for (
int j = 0 ; j < ip-1 ; j++) {
510 aa[j][ip] = g - s * (h + g * tau);
511 aa[j][iq] = h + s * (g - h * tau);
514 for (
int j = ip+1 ; j < iq-1 ; j++) {
517 aa[ip][j] = g - s * (h + g * tau);
518 aa[j][iq] = h + s * (g - h * tau);
521 for (
int j = iq+1 ; j < ncols ; j++) {
524 aa[ip][j] = g - s * (h + g * tau);
525 aa[j][iq] = h + s * (g - h * tau);
528 for (
int j = 0 ; j < ncols ; j++) {
531 v[j][ip] = g - s * (h + g * tau);
532 v[j][iq] = h + s * (g - h * tau);
539 for (
int ip = 0 ; ip < nrows ; ip++) {
540 b[ip] = b[ip] + z[ip];
550 "Too many iterations in Jacobi",
556 GMatrix Gruen::Identity(
const int &ndiag)
const {
557 GMatrix ident(ndiag, ndiag, 0.0);
558 for (
int i = 0 ; i < ndiag ; i++) {
573 assert(evals.dim1() == evecs.dim1());
575 for (
int i = 0 ; i < n-1 ; i++ ) {
578 for (
int j = i+1 ; j < n ; j++) {
587 for (
int j = 0 ; j < n ; j++) {
589 evecs[j][i] = evecs[j][k];
632 npts, resid, atai, affrad);
636 if (analysis.isValid()) {
653 return (fit1 <= fit2);
697 Chip &fChip,
int startSamp,
698 int startLine,
int endSamp,
699 int endLine,
int bestSamp,
705 QString chipOut = m_filePattern;
743 Affine extractor(affine.m_affine);
744 sChip.
Extract(fChip, extractor);
747 if (!chipOut.isEmpty()) {
748 std::ostringstream ss;
749 ss <<
"C" << std::setw(6) << std::setfill(
'0') << m_callCount <<
"I"
750 << std::setw(3) << std::setfill(
'0') << m_nIters;
751 QString sfname = chipOut + ss.str().c_str() +
".cub";
760 int status =
algorithm(pChip, fChip, affine.m_radio, npts, resid,
764 return (
Status(matchpt.setStatus(status)));
768 matchpt.m_nIters = ++m_nIters;
769 if (m_nIters > m_maxIters) {
770 QString errmsg =
"Maximum Iterations exceeded";
771 matchpt.setStatus(
logError(MaxIterationsExceeded, errmsg));
779 matchpt.m_affine = affine;
781 matchpt.setStatus(matchpt.m_analysis.m_status);
782 if (matchpt.isValid()) {
803 QString mess =
"Affine invalid/not invertable";
804 matchpt.setStatus(
logError(AffineNotInvertable, mess));
821 regdef =
Pvl(
"$base/templates/autoreg/coreg.adaptgruen.p1515s3030.def");
846 for (
int e = 0 ; e < m_errors.
size() ; e++) {
847 algo += m_errors.
getNth(e).LogIt();
850 if (m_unclassified > 0) {
910 parms +=
ValidateKey(
"AffineScaleTolerance", m_scaleTol);
911 parms +=
ValidateKey(
"AffineShearTolerance", m_shearTol);
912 parms +=
ValidateKey(
"AffineTranslationTolerance", m_transTol);
917 parms +=
ParameterKey(
"RadioShiftTolerance", m_shiftTol);
919 parms +=
ParameterKey(
"RadioGainMinTolerance", m_rgainMinTol);
920 parms +=
ParameterKey(
"RadioGainMaxTolerance", m_rgainMaxTol);
922 parms +=
ValidateKey(
"DefaultRadioGain", m_defGain);
923 parms +=
ValidateKey(
"DefaultRadioShift", m_defShift);
965 if (!m_errors.
exists(gerrno)) {
969 m_errors.
get(gerrno).BumpIt();
992 if (m_prof.
Name().isEmpty()) m_prof.
setName(
"Gruen");
1016 m_totalIterations = 0;
1035 m_eigenStat.
Reset();
1037 m_shiftStat.
Reset();
1056 return ((BigInt) pts);
1109 if (point.isValid()) {
1110 if (point.m_nIters > m_maxIters) {
1111 QString errmsg =
"Maximum Iterations exceeded";
1112 return (
logError(MaxIterationsExceeded, errmsg));
1114 m_iterStat.
AddData(point.m_nIters);
1117 QString errmsg =
"Maximum Eigenvalue exceeded";
1118 return (
logError(MaxEigenExceeded, errmsg));
1120 m_eigenStat.
AddData(point.getEigen());
1122 double shift = point.m_affine.m_radio.Shift();
1123 if ( shift > m_shiftTol) {
1124 QString errmsg =
"Radiometric shift exceeds tolerance";
1125 return (
logError(RadShiftExceeded, errmsg));
1129 double gain = point.m_affine.m_radio.Gain();
1130 if (((1.0 + gain) > m_rgainMaxTol) ||
1131 ((1.0 + gain) < m_rgainMinTol)) {
1132 QString errmsg =
"Radiometric gain exceeds tolerances";
1133 return (
logError(RadGainExceeded, errmsg));
1140 QString errmsg =
"Affine distance exceeded";
1141 return (
logError(AffineDistExceeded, errmsg));
1144 return (point.getStatus());
void SetChipPosition(const double sample, const double line)
Compute the position of the cube given a chip coordinate.
void setAffineRadio()
Set affine parameters to defaults.
Error occured in Adaptive algorithm.
Success registering to sub-pixel accuracy.
bool IsValid(double percentage)
Return if the pixel is valid at a particular position.
const double Null
Value for an Isis Null pixel.
GMatrix Cholsl(const GMatrix &a, const GVector &p, const GMatrix &b, const GMatrix &x) const
Compute Cholesky solution matrix from correlation.
bool exists(const K &key) const
Checks the existance of a particular key in the list.
AutoReg::RegisterStatus Status(const MatchPoint &result)
Returns the proper status given a Gruen result container.
PvlGroupIterator findGroup(const QString &name, PvlGroupIterator beg, PvlGroupIterator end)
Find a group with the specified name, within these indexes.
T & get(const K &key)
Returns the value associated with the name provided.
virtual AutoReg::RegisterStatus Registration(Chip &sChip, Chip &pChip, Chip &fChip, int startSamp, int startLine, int endSamp, int endLine, int bestSamp, int bestLine)
Applies the adaptive Gruen algorithm to pattern and search chips.
Define a generic Y/X container.
void SetChipSample(double sample)
Sets the search chip subpixel sample that matches the pattern tack sample.
Coordinate getAffinePoint(const Coordinate &coord=Coordinate(0.0, 0.0)) const
Return registration offset of a given chip coordinate from center.
double Tolerance() const
Return match algorithm tolerance.
Store for radiometric gain and shift parameters.
double Minimum() const
Returns the absolute minimum double found in all data passed through the AddData method.
A small chip of data used for pattern matching.
void Translate(const Coordinate &offset)
Apply a translation to the given offset.
void EigenSort(GVector &evals, GMatrix &evecs) const
Sort eigenvectors from highest to lowest.
T & getNth(int nth)
Returns the nth value in the collection.
bool hasConverged(const AffineRadio &affine) const
Determines convergence from an affine/radiometric fit.
QString Name() const
Returns the name of this property.
virtual bool CompareFits(double fit1, double fit2)
This virtual method must return if the 1st fit is equal to or better than the second fit...
Define a point set of left, right and geometry at that location.
void addGroup(const Isis::PvlGroup &group)
Add a group to the object.
int toInt(const QString &string)
Global function to convert from a string to an integer.
GMatrix Choldc(const GMatrix &a, GVector &p) const
Compute Cholesky solution.
double ChipLine() const
Returns chip line after invoking SetCubePosition.
void TackCube(const double cubeSample, const double cubeLine)
This sets which cube position will be located at the chip tack position.
PvlKeyword ValidateKey(const QString keyname, const double &value, const QString &unit="") const
Checks value of key, produces appropriate value.
Analysis errorAnalysis(const BigInt &npts, const double &resid, const GMatrix &atai)
Compute the error analysis of convergent Gruen matrix.
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
PvlGroup ParameterLog() const
Create a PvlGroup with the Gruen specific parameters.
int logError(int gerrno, const QString &gerrmsg)
Logs a Gruen error.
double toDouble(const QString &string)
Global function to convert from a string to a double.
This error is for when a programmer made an API call that was illegal.
PvlKeyword ParameterKey(const QString &keyname, const T &value, const QString &unit="") const
Keyword formatter for Gruen parameters.
virtual QString AlgorithmName() const
Returns the default name of the algorithm as Gruen.
int algorithm(Chip &pattern, Chip &subsearch, const Radiometric &radio, BigInt &ptsUsed, double &resid, GMatrix &atai, AffineRadio &affrad)
Real workhorse of the computational Gruen algorithm.
Chip Extract(int samples, int lines, int samp, int line)
Extract a sub-chip from a chip.
A DbProfile is a container for access parameters to a database.
virtual Pvl AlgorithmStatistics(Pvl &pvl)
Create Gruen error and processing statistics Pvl output.
double StandardDeviation() const
Computes and returns the standard deviation.
int Samples() const
Return the number of samples in the chip.
AffineTolerance getAffineTolerance() const
Return set of tolerances for affine convergence.
double PatternValidPercent() const
Return pattern chip valid percent. The default value is.
const AffineRadio & getAffineRadio() const
Return current state of Affine/Radio state.
Gruen()
Default constructor.
void SetGoodnessOfFit(double fit)
Sets the goodness of fit for adaptive algorithms.
Contains multiple PvlContainers.
double Average() const
Computes and returns the average.
void Write(const QString &filename)
Writes the contents of the Chip to a cube.
void Reset()
Reset all accumulators and counters to zero.
#define _FILEINFO_
Macro for the filename and line number.
void add(const K &key, const T &value)
Adds the element to the list.
A single keyword-value pair.
double Maximum() const
Returns the absolute maximum double found in all data passed through the AddData method.
void WriteSubsearchChips(const QString &pattern="SubChip")
Set up for writing subsearch for a a given registration call.
double getEigen() const
Returns the square of the of sum of the squares of eigenvalues.
void SetChipLine(double line)
Sets the search chip subpixel line that matches the pattern tack line.
double DegreesOfFreedom(const int npts) const
Returns number of degrees of freedom of points.
int TackSample() const
Return the fixed tack sample of the chip.
void SetSize(const int samples, const int lines)
Change the size of the Chip.
virtual double MatchAlgorithm(Chip &pattern, Chip &subsearch)
Minimization of data set using Gruen algorithm.
Container for cube-like labels.
double CubeLine() const
Returns cube line after invoking SetChipPosition.
void setName(const QString &name)
Set the name of this profile.
Container for Affine limits parameters.
Container for affine and radiometric parameters.
int CheckConstraints(MatchPoint &point)
Test user limits/contraints after the algorithm has converged.
void init(Pvl &pvl)
Initialize the object.
Structure containing comprehensive registration info/results.
Gruen pattern matching algorithm.
int Jacobi(const GMatrix &a, GVector &evals, GMatrix &evecs, const int &MaxIters=50) const
Compute the Jacobian of a covariance matrix.
bool hasObject(const QString &name) const
Returns a boolean value based on whether the object exists in the current PvlObject or not...
PvlGroup StatsLog() const
Create a PvlGroup with the Gruen specific statistics.
void resetStats()
Reset Gruen statistics as needed.
RegisterStatus
Enumeration of the Register() method's return status.
int Lines() const
Return the number of lines in the chip.
double getDistance(const Coordinate &pntA=Coordinate(0.0, 0.0)) const
Computes the distance from this point and the point provided.
bool ValidPoints(BigInt totalPoints, BigInt nPoints) const
Determines if number of points is valid percentage of all points.
QString toString() const
Returns a string representation of this exception.
int size() const
Returns the size of the collection.
double getAffineConstraint() const
Returns the Affine tolerance constraint as read from config file.
double GetValue(int sample, int line)
Loads a Chip with a value.
Compute/test the Affine convergence from given parameters/chip.
double CubeSample() const
Returns cube sample after invoking SetChipPosition.
Coordinate getChipUpdate(Chip &sChip, MatchPoint &point) const
Compute the chip coordinate of the registered pixel.
Error analysis of Gruen match point solution.
int TackLine() const
Return the fixed tack line of the chip.
ErrorList initErrorList() const
Creates an error list from know Gruen errors.
void AddData(const double *data, const unsigned int count)
Add an array of doubles to the accumulators and counters.
const AffineRadio & getDefaultAffineRadio() const
Returns default settings for Affine/Radiometric parameters.
static Pvl & getDefaultParameters()
Load default Gruen parameter file in $ISIS3DATA/base/templates.
Struct that maintains error counts.
QString ConfKey(const DbProfile &conf, const QString &keyname, const QString &defval, int index=0) const
Helper method to initialize parameters.
BigInt MinValidPoints(BigInt totalPoints) const
Computes the number of minimum valid points.
double ChipSample() const
Returns chip sample after invoking SetCubePosition.
Radiometric getDefaultRadio() const
Returns the default radiometric gain value.