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();
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());
bool ValidPoints(BigInt totalPoints, BigInt nPoints) const
Determines if number of points is valid percentage of all points.
long long int BigInt
Big int.
void SetChipPosition(const double sample, const double line)
Compute the position of the cube given a chip coordinate.
int Jacobi(const GMatrix &a, GVector &evals, GMatrix &evecs, const int &MaxIters=50) const
Compute the Jacobian of a covariance matrix.
void setAffineRadio()
Set affine parameters to defaults.
Error occured in Adaptive algorithm.
Success registering to sub-pixel accuracy.
double getEigen() const
Returns the square of the of sum of the squares of eigenvalues.
const double Null
Value for an Isis Null pixel.
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.
double StandardDeviation() const
Computes and returns the standard deviation.
double Minimum() const
Returns the absolute minimum double found in all data passed through the AddData method.
Store for radiometric gain and shift parameters.
double getDistance(const Coordinate &pntA=Coordinate(0.0, 0.0)) const
Computes the distance from this point and the point provided.
A small chip of data used for pattern matching.
void Translate(const Coordinate &offset)
Apply a translation to the given offset.
T & getNth(int nth)
Returns the nth value in the collection.
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.
GMatrix Cholsl(const GMatrix &a, const GVector &p, const GMatrix &b, const GMatrix &x) const
Compute Cholesky solution matrix from correlation.
int toInt(const QString &string)
Global function to convert from a string to an integer.
Namespace for the standard library.
PvlGroup StatsLog() const
Create a PvlGroup with the Gruen specific statistics.
void TackCube(const double cubeSample, const double cubeLine)
This sets which cube position will be located at the chip tack position.
virtual QString AlgorithmName() const
Returns the default name of the algorithm as Gruen.
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.
int size() const
Returns the size of the collection.
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.
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.
bool hasObject(const QString &name) const
Returns a boolean value based on whether the object exists in the current PvlObject or not...
Coordinate getChipUpdate(Chip &sChip, MatchPoint &point) const
Compute the chip coordinate of the registered pixel.
const AffineRadio & getAffineRadio() const
Return current state of Affine/Radio state.
double Maximum() const
Returns the absolute maximum double found in all data passed through the AddData method.
double DegreesOfFreedom(const int npts) const
Returns number of degrees of freedom of points.
BigInt MinValidPoints(BigInt totalPoints) const
Computes the number of minimum valid points.
Gruen()
Default constructor.
void SetGoodnessOfFit(double fit)
Sets the goodness of fit for adaptive algorithms.
ErrorList initErrorList() const
Creates an error list from know Gruen errors.
double Tolerance() const
Return match algorithm tolerance.
bool IsValid(int sample, int line)
QString ConfKey(const DbProfile &conf, const QString &keyname, const QString &defval, int index=0) const
Helper method to initialize parameters.
void EigenSort(GVector &evals, GMatrix &evecs) const
Sort eigenvectors from highest to lowest.
PvlKeyword ParameterKey(const QString &keyname, const T &value, const QString &unit="") const
Keyword formatter for Gruen parameters.
Contains multiple PvlContainers.
bool exists(const K &key) const
Checks the existance of a particular key in the list.
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 CubeSample() const
double PatternValidPercent() const
Return pattern chip valid percent. The default value is.
void WriteSubsearchChips(const QString &pattern="SubChip")
Set up for writing subsearch for a a given registration call.
AffineTolerance getAffineTolerance() const
Return set of tolerances for affine convergence.
int TackSample() const
This method returns a chip's fixed tack sample; the middle of the chip.
void SetChipLine(double line)
Sets the search chip subpixel line that matches the pattern tack line.
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.
PvlGroup ParameterLog() const
Create a PvlGroup with the Gruen specific parameters.
Container for cube-like labels.
void setName(const QString &name)
Set the name of this profile.
Container for Affine limits parameters.
Radiometric getDefaultRadio() const
Returns the default radiometric gain value.
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.
QString toString() const
Returns a string representation of this exception.
PvlKeyword ValidateKey(const QString keyname, const double &value, const QString &unit="") const
Checks value of key, produces appropriate value.
void resetStats()
Reset Gruen statistics as needed.
bool hasConverged(const AffineRadio &affine) const
Determines convergence from an affine/radiometric fit.
RegisterStatus
Enumeration of the Register() method's return status.
const AffineRadio & getDefaultAffineRadio() const
Returns default settings for Affine/Radiometric parameters.
Namespace for ISIS/Bullet specific routines.
double ChipSample() const
double GetValue(int sample, int line)
Loads a Chip with a value.
QString Name() const
Returns the name of this property.
Compute/test the Affine convergence from given parameters/chip.
Coordinate getAffinePoint(const Coordinate &coord=Coordinate(0.0, 0.0)) const
Return registration offset of a given chip coordinate from center.
Error analysis of Gruen match point solution.
void AddData(const double *data, const unsigned int count)
Add an array of doubles to the accumulators and counters.
static Pvl & getDefaultParameters()
Load default Gruen parameter file in $ISIS3DATA/base/templates.
double Average() const
Computes and returns the average.
GMatrix Choldc(const GMatrix &a, GVector &p) const
Compute Cholesky solution.
double getAffineConstraint() const
Returns the Affine tolerance constraint as read from config file.
Struct that maintains error counts.
int TackLine() const
This method returns a chip's fixed tack line; the middle of the chip.