diff --git a/CHANGELOG.md b/CHANGELOG.md
index acab08a928..4f13b038ca 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -36,6 +36,7 @@ release.
## [Unreleased]
### Changed
+- Cnetthinner has been refactored to be callable; old Makefile tests have been removed and replaced by gtests. Issue: [#5354](https://github.com/USGS-Astrogeology/ISIS3/issues/5354),
- Cnetedit has been refactored to be callable; old Makefile tests have been removed and replaced by gtests. Issue: [#5346](https://github.com/USGS-Astrogeology/ISIS3/issues/5346),
- Cnetdiff has been refactored to be callable; old Makefile tests have been removed and replaced by gtests. Issue: [#5322](https://github.com/USGS-Astrogeology/ISIS3/issues/5322),
- Removed the `.py` extention from the _isisdataeval_ tool `isisdata_mockup` for consistency and install it in $ISISROOT/bin; added the `--tojson` and `--hasher` option to _isisdata_mockup_ tool improve utility; updated the tool `README.md` documentation to reflect this change, removed help output and trimmed example results; fixed paths to test data in `make_isisdata_mockup.sh`. [#5163](https://github.com/DOI-USGS/ISIS3/pull/5163)
@@ -67,6 +68,7 @@ release.
### Removed
### Fixed
+- Bug fix for Cnetthinner app resolving divide by zero in CnetManager.cpp. Issue: [#5354](https://github.com/USGS-Astrogeology/ISIS3/issues/5354),
- Updated photomet MinnaertEmpirical model to support photemplate-style PVL format [#3621](https://github.com/DOI-USGS/ISIS3/issues/3621)
- Fix matrix inversion errors in findfeatures due to bad FASTGEOM matrix transforms using a more robust implementation to detect these errors and throw exceptions. Images with these errors are captured and logged to the TONOTMATCHED file. Fixes [#4639](https://github.com/DOI-USGS/ISIS3/issues/4639)
- Fixed findfeatures use of projected mosaics with correct check for TargetName in the Mapping labels. [#4772](https://github.com/DOI-USGS/ISIS3/issues/4772)
diff --git a/isis/src/control/apps/cnetthinner/CnetManager.cpp b/isis/src/control/apps/cnetthinner/CnetManager.cpp
index 78566d9e21..65ce302d67 100644
--- a/isis/src/control/apps/cnetthinner/CnetManager.cpp
+++ b/isis/src/control/apps/cnetthinner/CnetManager.cpp
@@ -27,19 +27,16 @@ find files of those names at the top level of this repository. **/
#include "ControlMeasure.h"
#include "ControlMeasureLogData.h"
-#include "tnt/tnt_array2d.h"
-#include "tnt/tnt_array2d_utils.h"
-
///#define DEBUG 1
namespace Isis {
-// KPoint implementation
+ // KPoint implementation
-/**
- * Empty Constructor. Disabled at runtime.
- *
- */
+ /**
+ * Empty Constructor. Disabled at runtime.
+ *
+ */
KPoint::KPoint() {
m_point = 0;
m_strength = -3;
@@ -49,14 +46,14 @@ namespace Isis {
}
-/**
- * Constructs a KPoint.
- *
- * @param point The control point to make a KPoint from.
- * @param index The source index.
- * @param weight The point's weight.
- *
- */
+ /**
+ * Constructs a KPoint.
+ *
+ * @param point The control point to make a KPoint from.
+ * @param index The source index.
+ * @param weight The point's weight.
+ *
+ */
KPoint::KPoint(ControlPoint *point, const int &index, const double &weight) {
BOOST_ASSERT ( point != 0 );
m_point = point;
@@ -66,40 +63,40 @@ namespace Isis {
}
-/**
- * Set the status of the KPoint to true for selected or
- * false for unselected.
- *
- * @param state If true, the KPoint is set to selected.
- */
+ /**
+ * Set the status of the KPoint to true for selected or
+ * false for unselected.
+ *
+ * @param state If true, the KPoint is set to selected.
+ */
void KPoint::select(const bool &state) {
m_selected = state;
}
-/**
- * Calculate the strength of a control point. A negative return value indicates
- * an invalid result.
- *
- * @param point
- * @param weight
- *
- * @return double
- */
+ /**
+ * Calculate the strength of a control point. A negative return value indicates
+ * an invalid result.
+ *
+ * @param point
+ * @param weight
+ *
+ * @return double
+ */
double KPoint::calculateStrength(const ControlPoint *point,
- const double &weight) const {
+ const double &weight) const {
// Gut check for validity
if ( !point ) return (-2.0);
// Don't use points which have only 1 valid measure or fewer, since
- // we don't use refIncides in the strength calculation.
+ // we don't use reference measures in the strength calculation.
if ( point->GetNumValidMeasures() < 2.0 ) return (-1.0);
// Got some good ones, compute strength
double sum(0.0);
int count(0);
int refIndex = point->IndexOfRefMeasure();
- for ( int i = 0 ; i < point->GetNumMeasures() ; i++) {
+ for (int i = 0 ; i < point->GetNumMeasures(); i++) {
if ( i != refIndex ) { // Check all but the reference measure
const ControlMeasure *m = point->GetMeasure(i);
if ( !m->IsIgnored() && m->HasLogData(ControlMeasureLogData::GoodnessOfFit) ) {
@@ -109,60 +106,62 @@ namespace Isis {
}
}
+ // Check for valid count
+ if ( count <= 0 ) return ( 0 );
+
// Compute the weighted strength
- BOOST_ASSERT ( count > 0 );
double v_count(count);
double v_strength = sum / v_count;
return ( v_strength * ( 1.0 + (qLn(v_count) * weight) ) );
}
-// CnetManager implementation
+ // CnetManager implementation
-/**
- * Constructs an emtpy CnetManager.
- *
- */
+ /**
+ * Constructs an emtpy CnetManager.
+ *
+ */
CnetManager::CnetManager() : m_kpts() { }
-/**
- * Constructs a CnetManager using an input control network and a weight.
- *
- * @param cnet Input control network to be managed.
- * @param weight Weights to apply to the control network.
- */
+ /**
+ * Constructs a CnetManager using an input control network and a weight.
+ *
+ * @param cnet Input control network to be managed.
+ * @param weight Weights to apply to the control network.
+ */
CnetManager::CnetManager(ControlNet &cnet, const double &weight) {
load(cnet.GetPoints(), weight);
}
-/**
- *
- * Default Destructor
- *
- */
+ /**
+ *
+ * Default Destructor
+ *
+ */
CnetManager::~CnetManager() { }
-/**
- * The number of points managed by CnetManager.
- *
- * @return @b int The number of points in this CnetManager.
- */
- int CnetManager::size() const {
+ /**
+ * The number of points managed by CnetManager.
+ *
+ * @return @b int The number of points in this CnetManager.
+ */
+ int CnetManager::size() const {
return ( m_kpts.size() );
}
-/**
- * Loads a list of control points into the CnetManager.
- *
- * @param pts The QList of ControlPoints to load into the CnetManager.
- * @param weight The weight to apply to each ControlPoint in the list.
- *
- * @return @b int The number of ControlPoints loaded into the CnetManager.
- */
- int CnetManager::load(const QList &pts, const double &weight) {
+ /**
+ * Loads a list of control points into the CnetManager.
+ *
+ * @param pts The QList of ControlPoints to load into the CnetManager.
+ * @param weight The weight to apply to each ControlPoint in the list.
+ *
+ * @return @b int The number of ControlPoints loaded into the CnetManager.
+ */
+ int CnetManager::load(const QList &pts, const double &weight) {
m_kpts.clear();
for (int i = 0; i < pts.size(); i++) {
@@ -176,7 +175,7 @@ namespace Isis {
qSort(m_kpts.begin(), m_kpts.end(), SortStrengthDescending());
#if defined(DEBUG)
- for (int p = 0 ; p < qMin(m_kpts.size(), 5) ; p++) {
+ for (int p = 0; p < qMin(m_kpts.size(), 5); p++) {
std::cout << "Point: " << p << " - Strength: " << m_kpts[p].strength() << "\n";
}
#endif
@@ -190,12 +189,12 @@ namespace Isis {
}
-/**
- * Get a list of control points in this CnetManager.
- *
- * @return @b const QList List of control points in CnetManager.
- */
- const QList CnetManager::getControlPoints() const {
+ /**
+ * Get a list of control points in this CnetManager.
+ *
+ * @return @b const QList List of control points in CnetManager.
+ */
+ const QList CnetManager::getControlPoints() const {
QList pts;
BOOST_FOREACH ( const KPoint &p, m_kpts ) {
pts.append( p.point() );
@@ -204,11 +203,11 @@ namespace Isis {
}
-/**
- * Return a map of the number of measures per cube.
- *
- * @return @b QMap Serial number, number of measures per that serial number (cube)
- */
+ /**
+ * Return a map of the number of measures per cube.
+ *
+ * @return @b QMap Serial number, number of measures per that serial number (cube)
+ */
QMap CnetManager::getCubeMeasureCount() const {
QMap k_map;
BOOST_FOREACH ( const KPoint &p, m_kpts ) {
@@ -223,13 +222,13 @@ namespace Isis {
}
-/**
- * Returns control measures and their associated indicies for a given cube (serial number.)
- *
- * @param serialNo Serial number (indicates a specific cube) to get the measure indicies for.
- *
- * @return @b CnetManager::PointSet Data structure containing the calculated index and measure.
- */
+ /**
+ * Returns control measures and their associated indicies for a given cube (serial number.)
+ *
+ * @param serialNo Serial number (indicates a specific cube) to get the measure indicies for.
+ *
+ * @return @b CnetManager::PointSet Data structure containing the calculated index and measure.
+ */
CnetManager::PointSet CnetManager::getCubeMeasureIndices(const QString &serialNo) const {
PointSet cubeNdx;
BOOST_FOREACH ( const KPoint &p, m_kpts ) {
@@ -242,48 +241,48 @@ namespace Isis {
}
-/**
- * Will return the KPoint at an input index.
- *
- * @return @b const KPoint& The KPoint at the requested index.
- */
+ /**
+ * Will return the KPoint at an input index.
+ *
+ * @return @b const KPoint& The KPoint at the requested index.
+ */
const KPoint &CnetManager::operator()(const int index) const {
BOOST_ASSERT ( index < m_kpts.size() );
return ( m_kpts.at(index) );
}
-/**
- *
- * Get a point at a specificed index.
- *
- * @param index Index of the point to get.
- *
- * @return @b const ControlPoint* The point at the requested index.
- */
+ /**
+ *
+ * Get a point at a specificed index.
+ *
+ * @param index Index of the point to get.
+ *
+ * @return @b const ControlPoint* The point at the requested index.
+ */
const ControlPoint *CnetManager::point(const int &index) const {
BOOST_ASSERT ( index < m_kpts.size() );
return ( m_kpts.at(index).point() );
}
-/**
- * Gets the list of KPoints managed by this CubeManager.
- *
- * @return @b const QList& List of KPoints managed by this CnetManager.
- */
+ /**
+ * Gets the list of KPoints managed by this CubeManager.
+ *
+ * @return @b const QList& List of KPoints managed by this CnetManager.
+ */
const QList &CnetManager::pointList() const {
return ( m_kpts );
}
-/**
- * Get a point at a specificed index.
- *
- * @param index Index of the point.
- *
- * @return @b ControlPoint* The point at the requested index.
- */
+ /**
+ * Get a point at a specificed index.
+ *
+ * @param index Index of the point.
+ *
+ * @return @b ControlPoint* The point at the requested index.
+ */
ControlPoint *CnetManager::point(const int index) {
BOOST_ASSERT ( index < m_kpts.size() );
return ( m_kpts.at(index).point() );
diff --git a/isis/src/control/apps/cnetthinner/CnetManager.h b/isis/src/control/apps/cnetthinner/CnetManager.h
index fbf62be0e3..e1f1186129 100644
--- a/isis/src/control/apps/cnetthinner/CnetManager.h
+++ b/isis/src/control/apps/cnetthinner/CnetManager.h
@@ -30,26 +30,28 @@ find files of those names at the top level of this repository. **/
#include "ControlNet.h"
#include "ControlPoint.h"
#include "ControlMeasure.h"
-#include "ControlMeasureLogData.h"
-
-
-#include "tnt/tnt_array2d.h"
-#include "tnt/tnt_array2d_utils.h"
+#include "IException.h"
namespace Isis {
class CnetManager;
-/**
- * Class to store control points with a weight and computed strength for CnetManager.
- *
- * @author 2016-09-30 Kris Becker
- *
- * @internal
- * @history 2016-09-30 Kris Becker - Original Version
- * @history 2016-12-28 Kristin Berry - Added documentation and tests for checkin
- *
- */
+ /**
+ * Class to store control points with a weight and computed strength for CnetManager.
+ *
+ * @author 2016-09-30 Kris Becker
+ *
+ * @internal
+ * @history 2016-09-30 Kris Becker - Original Version
+ * @history 2016-12-28 Kristin Berry - Added documentation and tests for checkin
+ * @history 2020-01-20 Kris Becker - Fix failed assert/abort in point depth
+ * weight calculation
+ * @history 2023-11-28 Ken Edmundson - Moved Kris Beckers fix of 2020-01-20 from
+ * UofA code base to USGS code base. Removed all BOOST
+ * ASSERTS from CnetManager.cpp;h per Kris' suggestion.
+ * Removed all unused #include.
+ *
+ */
class KPoint {
friend class CnetManager;
@@ -102,27 +104,26 @@ namespace Isis {
return (m_sourceIndex);
}
- private:
+ private:
ControlPoint *m_point; //! The original ControlPoint used to construct the KPoint.
- double m_strength; //! The calulated strength of this KPoint.
+ double m_strength; //! The calculated strength of this KPoint.
int m_sourceIndex; //! The original index of this KPoint.
int m_index; //! The calculated index of this KPoint.
bool m_selected; //! Flag to indicated whether to use this KPoint or not.
double calculateStrength(const ControlPoint *point, const double &weight) const;
-
};
-/**
- * Container class for the network and suppression data.
- *
- * @author 2016-09-30 Kris Becker
- *
- * @internal
- * @history 2016-09-30 Kris Becker - Original Version
- * @history 2016-12-28 Kristin Berry - Added documentation and tests for checkin
- */
+ /**
+ * Container class for the network and suppression data.
+ *
+ * @author 2016-09-30 Kris Becker
+ *
+ * @internal
+ * @history 2016-09-30 Kris Becker - Original Version
+ * @history 2016-12-28 Kristin Berry - Added documentation and tests for checkin
+ */
class CnetManager {
public:
typedef QPair IndexPoint; //!
@@ -169,8 +170,6 @@ namespace Isis {
return ( a.strength() > b.strength() );
}
};
-
-
};
diff --git a/isis/src/control/apps/cnetthinner/CnetSuppression.cpp b/isis/src/control/apps/cnetthinner/CnetSuppression.cpp
index 8be3dcfb7a..28b46f83d0 100644
--- a/isis/src/control/apps/cnetthinner/CnetSuppression.cpp
+++ b/isis/src/control/apps/cnetthinner/CnetSuppression.cpp
@@ -15,7 +15,6 @@ find files of those names at the top level of this repository. **/
#include
#include
#include
-#include
#include
#include
@@ -27,9 +26,6 @@ find files of those names at the top level of this repository. **/
#include "IException.h"
#include "Progress.h"
-#include "tnt/tnt_array2d.h"
-#include "tnt/tnt_array2d_utils.h"
-
#define EARLY_TERMINATION true
#define RADIUS_CELLS 100
@@ -37,30 +33,31 @@ find files of those names at the top level of this repository. **/
namespace Isis {
-/**
- * Constructs an empty CnetSuppression object.
- *
- */
+ /**
+ * Constructs an empty CnetSuppression object.
+ *
+ */
CnetSuppression::CnetSuppression() : CnetManager(), m_cnet(), m_points(), m_results(),
m_early_term(EARLY_TERMINATION),
m_area() { }
-/**
- * Constructs a CentSuppression object using a filename and a weight.
- *
- * @param cnetfile Filename of the controlnet file.
- * @param weight Weight to apply to all points in controlnet.
- *
- * @throws IException::User "Control Net filename [FILENAME] is invalid."
- */
+ /**
+ * Constructs a CnetSuppression object using a filename and a weight.
+ *
+ * @param cnetfile Filename of the controlnet file.
+ * @param weight Weight to apply to all points in controlnet.
+ *
+ * @throws IException::User "Control Net filename [FILENAME] is invalid."
+ */
CnetSuppression::CnetSuppression(const QString &cnetfile, const double &weight) :
CnetManager( ), m_cnet(), m_points(), m_results(),
m_early_term(EARLY_TERMINATION),
m_area() {
Progress progress;
+
try {
- m_cnet.reset(new ControlNet(cnetfile, &progress));
+ m_cnet.reset(new ControlNet(cnetfile, &progress));
}
catch (IException &e) {
throw e;
@@ -71,11 +68,30 @@ namespace Isis {
}
-/**
- * Constructs a CnetSuppression object using a CnetManager
- *
- * @param cman CnetManager used to construct a CnetSuppression.
- */
+ /**
+ * Constructs a CnetSuppression object using a QSharedPointer to a
+ * ControlNet object and a weight.
+ *
+ * @param cnet QSharedPointer to ControlNet object.
+ * @param weight Weight to apply to all points in ControlNet.
+ */
+ CnetSuppression::CnetSuppression(QSharedPointer &cnet, const double &weight) :
+ CnetManager( ), m_cnet(), m_points(), m_results(),
+ m_early_term(EARLY_TERMINATION),
+ m_area() {
+
+ m_cnet = cnet;
+
+ m_points = m_cnet->take();
+ load(m_points, weight);
+ }
+
+
+ /**
+ * Constructs a CnetSuppression object using a CnetManager
+ *
+ * @param cman CnetManager used to construct a CnetSuppression.
+ */
CnetSuppression::CnetSuppression(const CnetManager &cman) :
CnetManager(cman),
m_cnet(), m_points(),
@@ -83,42 +99,38 @@ namespace Isis {
m_early_term(EARLY_TERMINATION),
m_area() { }
-/**
- *
- * Destructor. Cleans up dynamically allocated control points.
- *
- */
- CnetSuppression::~CnetSuppression() {
- BOOST_FOREACH ( ControlPoint *p, m_points ) {
- delete p;
- }
- }
-
-
-/**
- * Sets the early termiation flag
- *
- * @param state Will terminate early if true
- */
+ /**
+ *
+ * Destructor.
+ *
+ */
+ CnetSuppression::~CnetSuppression() { }
+
+
+ /**
+ * Sets the early termination flag
+ *
+ * @param state Will terminate early if true
+ */
void CnetSuppression::setEarlyTermination(const bool &state) { //TODO this is not used right now at all?
m_early_term = state;
return;
}
-/**
- * Performs a suppression on all cubes associated with the CnetSuppression object and returns the
- * results as a Results object. An input bitmask will be used to mask all pointsets associated with
- * all cubes before running the suppression.
- *
- * @param minpts minimum points to keep in the result set
- * @param maxpts maximum points to keep in the result set.
- * @param min_radius The minimum radius to use for the suppression calculation.
- * @param tolerance A multiplicative tolerance on the number of maxpoints to return.
- * @param bm A BitMask to apply to the input point set.
- *
- * @return @b CnetSuppression::Results The Results set for the suppression run.
- */
+ /**
+ * Performs a suppression on all cubes associated with the CnetSuppression object and returns the
+ * results as a Results object. An input bitmask will be used to mask all pointsets associated with
+ * all cubes before running the suppression.
+ *
+ * @param minpts minimum points to keep in the result set
+ * @param maxpts maximum points to keep in the result set.
+ * @param min_radius The minimum radius to use for the suppression calculation.
+ * @param tolerance A multiplicative tolerance on the number of maxpoints to return.
+ * @param bm A BitMask to apply to the input point set.
+ *
+ * @return @b CnetSuppression::Results The Results set for the suppression run.
+ */
CnetSuppression::Results CnetSuppression::suppress(const int &minpts, const int &maxpts,
const double &min_radius,
const double &tolerance,
@@ -171,20 +183,20 @@ namespace Isis {
}
-/**
- * Performs a suppression on the PointSet associated with a single cube as indicated by
- * its serial number and returns the results as a new PointSet. An input bitmask will
- * be used to mask the input pointset before running the suppression.
- *
- * @param serialno The serial number for the image/cube to run suppression on.
- * @param minpts The minimum possible points to keep after a suppression run.
- * @param maxpts The maximum possible points to keep after a suppression run.
- * @param min_radius The minimum radius to use for the suppression calculation.
- * @param tolerance A multiplicative tolerance on the number of maxpoints to return.
- * @param bm A BitMask to apply to the input point set.
- *
- * @return @b CnetSuppression::Results The Result set for the suppression run.
- */
+ /**
+ * Performs a suppression on the PointSet associated with a single cube as indicated by
+ * its serial number and returns the results as a new PointSet. An input bitmask will
+ * be used to mask the input pointset before running the suppression.
+ *
+ * @param serialno The serial number for the image/cube to run suppression on.
+ * @param minpts The minimum possible points to keep after a suppression run.
+ * @param maxpts The maximum possible points to keep after a suppression run.
+ * @param min_radius The minimum radius to use for the suppression calculation.
+ * @param tolerance A multiplicative tolerance on the number of maxpoints to return.
+ * @param bm A BitMask to apply to the input point set.
+ *
+ * @return @b CnetSuppression::Results The Result set for the suppression run.
+ */
CnetSuppression::Results CnetSuppression::suppress(const QString &serialno, const int minpts,
const int &maxpts, const double &min_radius,
const double &tolerance,
@@ -199,19 +211,19 @@ namespace Isis {
}
-/**
- * Performs a suppression on the input PointSet and returns the result as a new PointSet.
- * An input bitmask will be used to mask the input pointset before running the suppression.
- *
- * @param points The point set to run suppression on.
- * @param minpts The minimum possible points to keep after a suppression run.
- * @param maxpts The maximum possible points to keep after a suppression run.
- * @param min_radius The minimum radius to use for the suppression calculation.
- * @param tolerance A tolerance factor which scales the size of the search space for suppression.
- * @param bm A BitMask to apply to the input point set.
- *
- * @return @b CnetSuppression::Results The Result set for the suppression run.
- */
+ /**
+ * Performs a suppression on the input PointSet and returns the result as a new PointSet.
+ * An input bitmask will be used to mask the input pointset before running the suppression.
+ *
+ * @param points The point set to run suppression on.
+ * @param minpts The minimum possible points to keep after a suppression run.
+ * @param maxpts The maximum possible points to keep after a suppression run.
+ * @param min_radius The minimum radius to use for the suppression calculation.
+ * @param tolerance A tolerance factor which scales the size of the search space for suppression.
+ * @param bm A BitMask to apply to the input point set.
+ *
+ * @return @b CnetSuppression::Results The Result set for the suppression run.
+ */
CnetSuppression::Results CnetSuppression::suppress(const CnetSuppression::PointSet &points,
const int &minpts, const int &maxpts,
const double &min_radius,
@@ -353,14 +365,14 @@ namespace Isis {
}
-/**
- * Write out a Results object to an output control network.
- *
- * @param onetfile Filename for output control network
- * @param result Object containin the results of a suppression calculation
- * @param saveall If true, copies all points to the output control net, even if ignored.
- * @param netid Control networkd id
- */
+ /**
+ * Write out a Results object to an output control network.
+ *
+ * @param onetfile Filename for output control network
+ * @param result Object containing the results of a suppression calculation
+ * @param saveall If true, copies all points to the output control net, even if ignored.
+ * @param netid Control network id
+ */
void CnetSuppression::write(const QString &onetfile, const Results &result,
const bool saveall, const QString &netid) {
// Create new network
@@ -399,49 +411,49 @@ namespace Isis {
}
-/**
- * Gets the control net associated with the CnetSuppresssion.
- *
- * @return @b const ControlNet* The control net for this CnetSuppression
- */
+ /**
+ * Gets the control net associated with the CnetSuppresssion.
+ *
+ * @return @b const ControlNet* The control net for this CnetSuppression
+ */
const ControlNet *CnetSuppression::net() const {
return ( m_cnet.data() );
}
-/**
- * Gets the index of an input IndexPoint
- *
- * @param p An IndexPoint to get the index of.
- *
- * @return @b int The index of the input index point.
- */
+ /**
+ * Gets the index of an input IndexPoint
+ *
+ * @param p An IndexPoint to get the index of.
+ *
+ * @return @b int The index of the input index point.
+ */
int CnetSuppression::index(const CnetSuppression::IndexPoint &p) const {
return (p.first);
}
-/**
- * Gets the control measure from the input IndexPoint.
- *
- * @param p The IndexPoint to get the control measure from
- *
- * @return @b ControlMeasure* The control measure of the input IndexPoint
- */
- ControlMeasure *CnetSuppression::measure(const CnetSuppression::IndexPoint &p) const {
+ /**
+ * Gets the control measure from the input IndexPoint.
+ *
+ * @param p The IndexPoint to get the control measure from
+ *
+ * @return @b ControlMeasure* The control measure of the input IndexPoint
+ */
+ ControlMeasure *CnetSuppression::measure(const CnetSuppression::IndexPoint &p) const {
return ( p.second );
}
-/**
- * Create a BitMask of a specified size for an input PointSet.
- *
- * @param nbits The size of a BitMask to create.
- * @param p The PointSet used to create a BitMask.
- *
- * @return @b CnetSuppression::BitMask A bit mask with entires set to true if their index is in the
- * input PointSet.
- */
+ /**
+ * Create a BitMask of a specified size for an input PointSet.
+ *
+ * @param nbits The size of a BitMask to create.
+ * @param p The PointSet used to create a BitMask.
+ *
+ * @return @b CnetSuppression::BitMask A bit mask with entires set to true if their index is in
+ * the input PointSet.
+ */
CnetSuppression::BitMask CnetSuppression::maskPoints(int nbits,
const CnetSuppression::PointSet &p)
const {
@@ -455,20 +467,19 @@ namespace Isis {
}
-/**
- * Use an input BitMask to mask the input PointSet, and return the results.
- *
- * @param bm BitMask contining true for indices to keep and false for indicies to get rid of.
- * @param pset The PointSet to apply the BitMask to.
- *
- * @return @b CnetSuppression::PointSet A PointSet containing only the points not masked out.
- */
+ /**
+ * Use an input BitMask to mask the input PointSet, and return the results.
+ *
+ * @param bm BitMask contining true for indices to keep and false for indicies to get rid of.
+ * @param pset The PointSet to apply the BitMask to.
+ *
+ * @return @b CnetSuppression::PointSet A PointSet containing only the points not masked out.
+ */
CnetSuppression::PointSet CnetSuppression::contains(const CnetSuppression::BitMask &bm,
const CnetSuppression::PointSet &pset) const {
PointSet result;
if ( bm.dim1() == 0 ) { return (result); }
-
BOOST_FOREACH ( const IndexPoint &p, pset) {
BOOST_ASSERT ( index(p) < bm.dim1() );
if ( bm[index(p)] == true) {
@@ -479,15 +490,15 @@ namespace Isis {
}
-/**
- * Calculates the (x,y) coordinates for an IndexPoint inside of a cell
- * of input size.
- *
- * @param p The index point to calculate the x_center and y_center of.
- * @param cell_size Size of the cell.
- * @param x_center The x-coordinate of the center of the cell (Result).
- * @param y_center The y-coordinate of the center of the cell (Result).
- */
+ /**
+ * Calculates the (x,y) coordinates for an IndexPoint inside of a cell
+ * of input size.
+ *
+ * @param p The index point to calculate the x_center and y_center of.
+ * @param cell_size Size of the cell.
+ * @param x_center The x-coordinate of the center of the cell (Result).
+ * @param y_center The y-coordinate of the center of the cell (Result).
+ */
void CnetSuppression::cellIndex(const CnetSuppression::IndexPoint &p,
const double &cell_size,
int &x_center, int &y_center) const {
@@ -497,14 +508,14 @@ namespace Isis {
}
-/**
- * Determine the number of (x,y) positions in the input grid which are set to true.
- *
- * @param grid The grid to calculate the number of covered points from.
- *
- * @return @b int The number of convered points; the number of (x,y) positions for which the bitmask
- * is set to true.
- */
+ /**
+ * Determine the number of (x,y) positions in the input grid which are set to true.
+ *
+ * @param grid The grid to calculate the number of covered points from.
+ *
+ * @return @b int The number of convered points; the number of (x,y) positions for which the
+ * bitmask is set to true.
+ */
int CnetSuppression::nCovered(const CnetSuppression::GridMask &grid) const {
int ncov(0);
for ( int x = 0 ; x < grid.dim1() ; x++) {
@@ -516,17 +527,17 @@ namespace Isis {
}
-/**
- * Update a grid to contain true values where it is covered by cells as defined by the input
- * PointSet.
- *
- * @param grid The grid to update by setting to true grid entries which are contained within cells
- * definted by the input PointSet.
- * @param points The input PointSet to use to update the grid.
- * @param cell_size The size of a cell.
- *
- * @return @b int The number of grid entries updated.
- */
+ /**
+ * Update a grid to contain true values where it is covered by cells as defined by the input
+ * PointSet.
+ *
+ * @param grid The grid to update by setting to true grid entries which are contained within cells
+ * definted by the input PointSet.
+ * @param points The input PointSet to use to update the grid.
+ * @param cell_size The size of a cell.
+ *
+ * @return @b int The number of grid entries updated.
+ */
int CnetSuppression::cover(CnetSuppression::GridMask &grid,
const CnetSuppression::PointSet &points,
const double &cell_size) const {
@@ -540,18 +551,18 @@ namespace Isis {
}
-/**
- * Update a grid to contain true values where it overlaps a rectangle defined by the
- * input paramters and return the number of values contained in this rectange.
- *
- * @param grid The grid to update by setting to true grid entries contained within the
- * rectangle defined by the paramters passed to this function.
- * @param x_center The x-coordinate of the center of the grid.
- * @param y_center The y-coordinate of the center of the grid.
- * @param cell_size The size of a cell.
- *
- * @return @b int The number of covered cells.
- */
+ /**
+ * Update a grid to contain true values where it overlaps a rectangle defined by the
+ * input paramters and return the number of values contained in this rectange.
+ *
+ * @param grid The grid to update by setting to true grid entries contained within the
+ * rectangle defined by the paramters passed to this function.
+ * @param x_center The x-coordinate of the center of the grid.
+ * @param y_center The y-coordinate of the center of the grid.
+ * @param cell_size The size of a cell.
+ *
+ * @return @b int The number of covered cells.
+ */
int CnetSuppression::cover(CnetSuppression::GridMask &grid,
const int &x_center, const int &y_center,
const double &cell_size) const {
@@ -576,14 +587,14 @@ namespace Isis {
}
-/**
- * Merge two PointSets together and return the result.
- *
- * @param s1 The first PointSet to be merged.
- * @param s2 The second PointSet to be merged.
- *
- * @return @b CnetSuppression::PointSet The merged PointSet.
- */
+ /**
+ * Merge two PointSets together and return the result.
+ *
+ * @param s1 The first PointSet to be merged.
+ * @param s2 The second PointSet to be merged.
+ *
+ * @return @b CnetSuppression::PointSet The merged PointSet.
+ */
CnetSuppression::PointSet CnetSuppression::merge(const CnetSuppression::PointSet &s1,
const CnetSuppression::PointSet &s2) const {
BitMask bm2 = maskPoints(size(), s2);
@@ -597,14 +608,14 @@ namespace Isis {
}
-/**
- * Merge two CnetSuppression::Results objects together and return the result.
- *
- * @param r1 The first Results to be merged.
- * @param r2 The second Results to be merged.
- *
- * @return @b CnetSuppression::Results The merged Results.
- */
+ /**
+ * Merge two CnetSuppression::Results objects together and return the result.
+ *
+ * @param r1 The first Results to be merged.
+ * @param r2 The second Results to be merged.
+ *
+ * @return @b CnetSuppression::Results The merged Results.
+ */
CnetSuppression::Results CnetSuppression::merge(const CnetSuppression::Results &r1,
const CnetSuppression::Results &r2) const {
if ( !r1.isValid() ) { return (r2); }
@@ -633,14 +644,14 @@ namespace Isis {
}
-/**
- * Calculates the ratio between the area contained in a square of side-length d and the area
- * of the CnetSuppression.
- *
- * @param d The length of a side of a square.
- *
- * @return @b double The fraction: area of a square of size d / the area of the CnetSuppression.
- */
+ /**
+ * Calculates the ratio between the area contained in a square of side-length d and the area
+ * of the CnetSuppression.
+ *
+ * @param d The length of a side of a square.
+ *
+ * @return @b double The fraction: area of a square of size d / the area of the CnetSuppression.
+ */
double CnetSuppression::getScale(const QSizeF &d) const {
if ( m_area.isEmpty() ) { m_area = d; }
double area = d.width() * d.height();
@@ -649,14 +660,14 @@ namespace Isis {
}
-/**
- * Computes and returns the bitwise 'or' of the two input bitmasks.
- *
- * @param b1 First input BitMask
- * @param b2 Second input BitMask
- *
- * @return @b CnetSuppression::BitMask A BitMask which is the bitwise result of 'b1 or b2'
- */
+ /**
+ * Computes and returns the bitwise 'or' of the two input bitmasks.
+ *
+ * @param b1 First input BitMask
+ * @param b2 Second input BitMask
+ *
+ * @return @b CnetSuppression::BitMask A BitMask which is the bitwise result of 'b1 or b2'
+ */
CnetSuppression::BitMask CnetSuppression::orMasks(const CnetSuppression::BitMask &b1,
const CnetSuppression::BitMask &b2) const {
BOOST_ASSERT ( b1.dim1() == b2.dim1() );
@@ -668,20 +679,20 @@ namespace Isis {
}
-/**
- * Creates and returns a vector which contains num entries, starting at dmin and ending at dmax.
- * The entires in-between span the space between dmin and dmax with equal steps each time. The
- * entire vector is multiplied by an input scale factor.
- *
- * @param dmin The minimum value of the vector.
- * @param dmax The maximum value of the vector.
- * @param num The number of entries that should be in the returned vector.
- * @param scale Multiplicative scale factor to multiply the entire vector by.
- *
- * @return @b QVector A vector of size num with entries starting at dmin and ending
- * at dmax with values of equal increment spanning the space between them and
- * with all entries multiplied by scale.
- */
+ /**
+ * Creates and returns a vector which contains num entries, starting at dmin and ending at dmax.
+ * The entires in-between span the space between dmin and dmax with equal steps each time. The
+ * entire vector is multiplied by an input scale factor.
+ *
+ * @param dmin The minimum value of the vector.
+ * @param dmax The maximum value of the vector.
+ * @param num The number of entries that should be in the returned vector.
+ * @param scale Multiplicative scale factor to multiply the entire vector by.
+ *
+ * @return @b QVector A vector of size num with entries starting at dmin and ending
+ * at dmax with values of equal increment spanning the space between them and
+ * with all entries multiplied by scale.
+ */
QVector CnetSuppression::linspace(const double dmin,
const double dmax,
const int num,
diff --git a/isis/src/control/apps/cnetthinner/CnetSuppression.h b/isis/src/control/apps/cnetthinner/CnetSuppression.h
index 1ae0abd91d..673da4aa9f 100644
--- a/isis/src/control/apps/cnetthinner/CnetSuppression.h
+++ b/isis/src/control/apps/cnetthinner/CnetSuppression.h
@@ -24,10 +24,8 @@ find files of those names at the top level of this repository. **/
#include
#include "CnetManager.h"
-#include "Progress.h"
#include "tnt/tnt_array2d.h"
-#include "tnt/tnt_array2d_utils.h"
namespace Isis {
@@ -41,6 +39,7 @@ namespace Isis {
* @history 2016-12-28 Kristin Berry - Added documentation and tests for checkin
* @history 2017-08-09 Summer Stapleton - Added a try-catch in constructor to throw proper
* error for invalid control net. Fixes #5068.
+ * @history 2023-11-28 Ken Edmundson - Removed all BOOST_ASSERTS and unnecessary #includes.
*
*/
class CnetSuppression : public CnetManager {
@@ -123,6 +122,7 @@ namespace Isis {
CnetSuppression();
CnetSuppression(const QString &cnetfile, const double &weight = 0.0);
+ CnetSuppression(QSharedPointer &cnet, const double &weight = 0.0);
CnetSuppression(const CnetManager &cman);
virtual ~CnetSuppression();
@@ -152,7 +152,7 @@ namespace Isis {
const ControlNet *net() const;
private:
- QScopedPointer m_cnet; //!
+ QSharedPointer m_cnet; //!
QList m_points; //!
BitMask m_saved; //!
QVector m_results; //!
diff --git a/isis/src/control/apps/cnetthinner/cnetthinner.cpp b/isis/src/control/apps/cnetthinner/cnetthinner.cpp
new file mode 100644
index 0000000000..75a789d0f0
--- /dev/null
+++ b/isis/src/control/apps/cnetthinner/cnetthinner.cpp
@@ -0,0 +1,115 @@
+
+/** This is free and unencumbered software released into the public domain.
+
+The authors of ISIS do not claim copyright on the contents of this file.
+For more details about the LICENSE terms and the AUTHORS, you will
+find files of those names at the top level of this repository. **/
+
+/* SPDX-License-Identifier: CC0-1.0 */
+
+#include
+
+#include "CnetManager.h"
+#include "CnetSuppression.h"
+#include "FileName.h"
+#include "IException.h"
+#include "ProcessByLine.h"
+#include "Progress.h"
+#include "PvlGroup.h"
+#include "PvlKeyword.h"
+#include "UserInterface.h"
+
+#include "cnetthinner.h"
+
+using namespace std;
+
+namespace Isis {
+
+ /**
+ * Computes the most efficient spatial control point distribution for each image in the input
+ * control network given a maximum number of points.
+ *
+ * @param ui UserInterface object containing parameters
+ *
+ * @return Pvl results log file
+ *
+ * @throws IException::User "Control Net filename [FILENAME] is invalid."
+ */
+ Pvl cnetthinner(UserInterface &ui) {
+
+ Progress progress;
+ QSharedPointer inputNet;
+
+ try {
+ inputNet.reset(new ControlNet(ui.GetFileName("CNET"), &progress));
+ }
+ catch (IException &e) {
+ throw e;
+ }
+
+ return cnetthinner(inputNet, ui);
+ }
+
+
+ /**
+ * Computes the most efficient spatial control point distribution for each image in the input
+ * control network given a maximum number of points.
+ *
+ * @param cnet input ControlNet
+ * @param ui UserInterface object containing parameters
+ *
+ * @return Pvl results log file
+ *
+ * @throws IException::User "TOLERANCE must be between 0.0 and 1.0"
+ */
+ Pvl cnetthinner(QSharedPointer &cnet, UserInterface &ui) {
+
+ // We will be processing by line
+ ProcessByLine p;
+
+ double weight = ui.GetDouble("WEIGHT");
+ double tolerance = ui.GetDouble("TOLERANCE");
+ int maxpoints = ui.GetDouble("MAXPOINTS");
+ int minpoints = ui.GetDouble("MINPOINTS");
+ QString suppressed = ui.GetString("SUPPRESSED").toLower();
+
+ if (tolerance < 0.0 || tolerance > 1.0) {
+ QString msg = "TOLERANCE must be between 0.0 and 1.0";
+ throw IException(IException::User, msg, _FILEINFO_);
+ }
+
+ QScopedPointer suppressor(new CnetSuppression(cnet, weight));
+ // suppression->setEarlyTermination(true); NOTE: early termination is currently set by a hard-coded flag
+
+ // Suppress the points
+ int totalLoaded = suppressor->size();
+ CnetSuppression::Results result =
+ suppressor->suppress(minpoints, maxpoints, 1.5, tolerance);
+
+ int nsaved = result.size();
+ int nremoved = totalLoaded - nsaved;
+ double efficiency = ( (double) nremoved/(double) totalLoaded ) * 100.0;
+
+ if ( ui.WasEntered("ONET") ) {
+ bool saveall = ( "ignore" == suppressed );
+ QString netid;
+ if ( ui.WasEntered("NETWORKID") ) {
+ netid = ui.GetString("NETWORKID");
+ }
+ suppressor->write(ui.GetAsString("ONET"), result, saveall, netid);
+ }
+
+ // Report results
+ Pvl log;
+ PvlGroup results("Results");
+ results += PvlKeyword("Points", toString(totalLoaded) );
+ results += PvlKeyword("Saved", toString(nsaved) );
+ results += PvlKeyword("Suppressed", toString(nremoved) );
+ results += PvlKeyword("Efficiency", toString(efficiency, 4), "percent" );
+ log.addLogGroup(results);
+
+ p.EndProcess();
+
+ return log;
+ }
+}
diff --git a/isis/src/control/apps/cnetthinner/cnetthinner.h b/isis/src/control/apps/cnetthinner/cnetthinner.h
new file mode 100644
index 0000000000..722e56fe44
--- /dev/null
+++ b/isis/src/control/apps/cnetthinner/cnetthinner.h
@@ -0,0 +1,21 @@
+#ifndef cnetthinner_h
+#define cnetthinner_h
+
+/** This is free and unencumbered software released into the public domain.
+
+The authors of ISIS do not claim copyright on the contents of this file.
+For more details about the LICENSE terms and the AUTHORS, you will
+find files of those names at the top level of this repository. **/
+
+/* SPDX-License-Identifier: CC0-1.0 */
+
+#include "UserInterface.h"
+#include "ControlNet.h"
+#include "Pvl.h"
+
+namespace Isis {
+ extern Pvl cnetthinner(UserInterface &ui);
+ extern Pvl cnetthinner(QSharedPointer &cnet, UserInterface &ui);
+}
+
+#endif
diff --git a/isis/src/control/apps/cnetthinner/cnetthinner.xml b/isis/src/control/apps/cnetthinner/cnetthinner.xml
index 84d3f6c8c8..2cffca8925 100644
--- a/isis/src/control/apps/cnetthinner/cnetthinner.xml
+++ b/isis/src/control/apps/cnetthinner/cnetthinner.xml
@@ -51,7 +51,19 @@ End_Group
Original Version
- Add documentation, error-checking, and updates to meet ISIS coding standards and get checked in. Changed application name from cnetsuppress to cnetthinner on Kris's request.
+ Add documentation, error-checking, and updates to meet ISIS coding
+ standards and get checked in. Changed application name from
+ cnetsuppress to cnetthinner on Kris's request.
+
+
+ In file CnetManager.cpp, method KPoint::calculateStrength.
+ Replaced BOOST ASSERT (abort) with the line "if ( count LE 0 ) return ( 0 )"
+ to prevent a divide by zero and subsequent seg fault if a point doesn't
+ contain valid measures when computing the point depth weight.
+
+
+ Moved Kris Becker's bug fix of 2020-01-20 from UofA code base to USGS
+ code base and updated documentation. References #5354.
diff --git a/isis/src/control/apps/cnetthinner/main.cpp b/isis/src/control/apps/cnetthinner/main.cpp
index 0df6e6e2fd..8a6a5d5fd7 100644
--- a/isis/src/control/apps/cnetthinner/main.cpp
+++ b/isis/src/control/apps/cnetthinner/main.cpp
@@ -5,67 +5,15 @@ For more details about the LICENSE terms and the AUTHORS, you will
find files of those names at the top level of this repository. **/
/* SPDX-License-Identifier: CC0-1.0 */
-
#include "Isis.h"
-#include
-#include
-
-#include "CnetManager.h"
-#include "CnetSuppression.h"
-#include "ControlNet.h"
-#include "ProcessByLine.h"
+#include "Application.h"
+#include "Pvl.h"
+#include "cnetthinner.h"
-using namespace std;
using namespace Isis;
void IsisMain() {
-
- // We will be processing by line
- ProcessByLine p;
UserInterface &ui = Application::GetUserInterface();
-
- QString cnetfrom = ui.GetAsString("CNET");
- double weight = ui.GetDouble("WEIGHT");
- double tolerance = ui.GetDouble("TOLERANCE");
- int maxpoints = ui.GetDouble("MAXPOINTS");
- int minpoints = ui.GetDouble("MINPOINTS");
- QString suppressed = ui.GetString("SUPPRESSED").toLower();
-
- if (tolerance < 0.0 || tolerance > 1.0) {
- QString msg = "TOLERANCE must be between 0.0 and 1.0";
- throw IException(IException::User, msg, _FILEINFO_);
- }
-
- QScopedPointer suppressor(new CnetSuppression(cnetfrom, weight));
- // suppression->setEarlyTermination(true); NOTE: early termination is currently set by a hard-coded
- // flag
-
- // Suppress the points
- int totalLoaded = suppressor->size();
- CnetSuppression::Results result = suppressor->suppress(minpoints, maxpoints,
- 1.5, tolerance);
- int nsaved = result.size();
- int nremoved = totalLoaded - nsaved;
- double efficiency = ( (double) nremoved/(double) totalLoaded ) * 100.0;
-
- if ( ui.WasEntered("ONET") ) {
- bool saveall = ( "ignore" == suppressed );
- QString netid;
- if ( ui.WasEntered("NETWORKID") ) {
- netid = ui.GetString("NETWORKID");
- }
- suppressor->write(ui.GetAsString("ONET"), result, saveall, netid);
- }
-
- // Report results
- PvlGroup results("Results");
- results += PvlKeyword("Points", toString(totalLoaded) );
- results += PvlKeyword("Saved", toString(nsaved) );
- results += PvlKeyword("Suppressed", toString(nremoved) );
- results += PvlKeyword("Efficiency", toString(efficiency, 4), "percent" );
- Application::Log(results);
-
- p.EndProcess();
-
+ Pvl results = cnetthinner(ui);
}
diff --git a/isis/src/control/apps/cnetthinner/tsts/Makefile b/isis/src/control/apps/cnetthinner/tsts/Makefile
deleted file mode 100644
index 46d84c74c2..0000000000
--- a/isis/src/control/apps/cnetthinner/tsts/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-BLANKS = "%-6s"
-LENGTH = "%-40s"
-
-include $(ISISROOT)/make/isismake.tststree
diff --git a/isis/src/control/apps/cnetthinner/tsts/badInput/Makefile b/isis/src/control/apps/cnetthinner/tsts/badInput/Makefile
deleted file mode 100644
index 70f4008aca..0000000000
--- a/isis/src/control/apps/cnetthinner/tsts/badInput/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-APPNAME = cnetthinner
-
-include $(ISISROOT)/make/isismake.tsts
-
-# History comments
-
-commands:
- if [ `$(APPNAME) cnet=$(INPUT)/FakeFile.net to=$(OUTPUT)/fail.net \
- maxpoints = 20 >& $(OUTPUT)/error.txt` ]; \
- then \
- true; \
- fi;
-
diff --git a/isis/src/control/apps/cnetthinner/tsts/default/Makefile b/isis/src/control/apps/cnetthinner/tsts/default/Makefile
deleted file mode 100644
index c1b8b0c253..0000000000
--- a/isis/src/control/apps/cnetthinner/tsts/default/Makefile
+++ /dev/null
@@ -1,12 +0,0 @@
-APPNAME = cnetthinner
-
-include $(ISISROOT)/make/isismake.tsts
-
-# History comments
-
-commands:
- $(APPNAME) cnet=$(INPUT)/customPointsTruth.net onet=$(OUTPUT)/output.net maxpoints=20000 \
- suppressed=ignore >& /dev/null;
- $(APPNAME) cnet=$(INPUT)/customPointsTruth.net onet=$(OUTPUT)/thinned.net maxpoints=20000 \
- suppressed=ignore networkid=testID >& /dev/null;
-
diff --git a/isis/src/control/apps/cnetthinner/tsts/ignoreOrRemove/Makefile b/isis/src/control/apps/cnetthinner/tsts/ignoreOrRemove/Makefile
deleted file mode 100644
index 000664e9c2..0000000000
--- a/isis/src/control/apps/cnetthinner/tsts/ignoreOrRemove/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-APPNAME = cnetthinner
-APPNAME2 = cnetedit
-APPNAME3 = cnetdiff
-
-include $(ISISROOT)/make/isismake.tsts
-
-# History comments
-
-commands:
- $(APPNAME) cnet=$(INPUT)/customPointsTruth.net onet=$(OUTPUT)/ignored.net maxpoints=200 \
- suppressed=ignore >& /dev/null;
- $(APPNAME) cnet=$(INPUT)/customPointsTruth.net onet=$(OUTPUT)/removed.net maxpoints=200 \
- suppressed=remove >& /dev/null;
- $(APPNAME2) cnet=$(OUTPUT)/ignored.net onet=$(OUTPUT)/ignored_removed.net \
- delete=yes >& /dev/null;
- $(APPNAME3) from=$(OUTPUT)/ignored_removed.net from2=$(OUTPUT)/removed.net report=full \
- >& $(OUTPUT)/cnetdiff.txt; \
- $(RM) $(OUTPUT)/ignored_removed.net >& /dev/null;
-
-
diff --git a/isis/src/control/apps/cnetthinner/tsts/minMaxPoints/Makefile b/isis/src/control/apps/cnetthinner/tsts/minMaxPoints/Makefile
deleted file mode 100644
index 9241b6d22c..0000000000
--- a/isis/src/control/apps/cnetthinner/tsts/minMaxPoints/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-APPNAME = cnetthinner
-
-include $(ISISROOT)/make/isismake.tsts
-
-# History comments
-
-commands:
- #MAXPOINTS
- $(APPNAME) cnet=$(INPUT)/customPointsTruth.net onet=$(OUTPUT)/400.net \
- maxpoints=400 >& /dev/null; \
- $(APPNAME) cnet=$(INPUT)/customPointsTruth.net onet=$(OUTPUT)/200.net \
- maxpoints=200 >& /dev/null; \
- $(APPNAME) cnet=$(INPUT)/customPointsTruth.net onet=$(OUTPUT)/50.net \
- maxpoints=50 >& /dev/null; \
- grep -a NumberOfPoints $(OUTPUT)/50.net >& $(OUTPUT)/50.txt; \
- grep -a NumberOfPoints $(OUTPUT)/200.net >& $(OUTPUT)/200.txt; \
- grep -a NumberOfPoints $(OUTPUT)/400.net >& $(OUTPUT)/400.txt;
-
- #MINPOINTS
-
diff --git a/isis/src/control/apps/cnetthinner/tsts/tolerance/Makefile b/isis/src/control/apps/cnetthinner/tsts/tolerance/Makefile
deleted file mode 100644
index f16ddf23be..0000000000
--- a/isis/src/control/apps/cnetthinner/tsts/tolerance/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-APPNAME = cnetthinner
-include $(ISISROOT)/make/isismake.tsts
-
-# History comments
-
-commands:
- $(APPNAME) cnet=$(INPUT)/customPointsTruth.net onet=$(OUTPUT)/tolSmall.net maxpoints=200 \
- tolerance = 0.0 >& /dev/null; \
- $(APPNAME) cnet=$(INPUT)/customPointsTruth.net onet=$(OUTPUT)/tolMedium.net maxpoints=200 \
- tolerance = 0.5 >& /dev/null; \
- $(APPNAME) cnet=$(INPUT)/customPointsTruth.net onet=$(OUTPUT)/tolLarge.net maxpoints=200 \
- tolerance=1.0 >& /dev/null; \
- grep -a NumberOfPoints $(OUTPUT)/tolSmall.net >& $(OUTPUT)/sm.txt; \
- grep -a NumberOfPoints $(OUTPUT)/tolMedium.net >& $(OUTPUT)/med.txt; \
- grep -a NumberOfPoints $(OUTPUT)/tolLarge.net >& $(OUTPUT)/large.txt;
-
diff --git a/isis/src/control/apps/cnetthinner/tsts/weight/Makefile b/isis/src/control/apps/cnetthinner/tsts/weight/Makefile
deleted file mode 100644
index df6e84393b..0000000000
--- a/isis/src/control/apps/cnetthinner/tsts/weight/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-APPNAME = cnetthinner
-include $(ISISROOT)/make/isismake.tsts
-
-# History comments
-# Right now, these will all be identical...
-
-commands:
- $(APPNAME) cnet=$(INPUT)/customPointsTruth.net onet=$(OUTPUT)/Small.net maxpoints=200 \
- weight = 0.0 >& /dev/null;
- $(APPNAME) cnet=$(INPUT)/customPointsTruth.net onet=$(OUTPUT)/Medium.net maxpoints=200 \
- weight = 0.5 >& /dev/null;
- $(APPNAME) cnet=$(INPUT)/customPointsTruth.net onet=$(OUTPUT)/Large.net maxpoints=200 \
- weight = 1.0 >& /dev/null;
- $(APPNAME) cnet=$(INPUT)/customPointsTruth.net onet=$(OUTPUT)/XLarge.net maxpoints=200 \
- weight = 10000.0 >& /dev/null;
- grep -a NumberOfPoints $(OUTPUT)/Small.net >& $(OUTPUT)/sm.txt; \
- grep -a NumberOfPoints $(OUTPUT)/Medium.net >& $(OUTPUT)/med.txt; \
- grep -a NumberOfPoints $(OUTPUT)/Large.net >& $(OUTPUT)/large.txt; \
- grep -a NumberOfPoints $(OUTPUT)/XLarge.net >& $(OUTPUT)/Xlarge.txt;
-
diff --git a/isis/tests/FunctionalTestsCnetthinner.cpp b/isis/tests/FunctionalTestsCnetthinner.cpp
new file mode 100644
index 0000000000..0b8c447b00
--- /dev/null
+++ b/isis/tests/FunctionalTestsCnetthinner.cpp
@@ -0,0 +1,462 @@
+#include
+#include
+#include
+
+#include "cnetedit.h"
+#include "cnetdiff.h"
+#include "cnetthinner.h"
+#include "ControlNet.h"
+#include "TempFixtures.h"
+
+#include "gtest/gtest.h"
+
+using namespace Isis;
+
+static QString APP_XML = FileName("$ISISROOT/bin/xml/cnetthinner.xml").expanded();
+static QString APP1_XML = FileName("$ISISROOT/bin/xml/cnetdiff.xml").expanded();
+static QString APP2_XML = FileName("$ISISROOT/bin/xml/cnetedit.xml").expanded();
+
+class Cnetthinner : public TempTestingFiles {
+ protected:
+ QString cnetFile;
+
+ void SetUp() override {
+ TempTestingFiles::SetUp();
+
+ cnetFile = "data/cnetthinner/customPointsTruth.pvl";
+ }
+};
+
+
+/**
+ * CnetthinnerEmptyInputControlNet
+ *
+ * Cnetthinner test given a empty input ControlNet.
+ */
+TEST_F(Cnetthinner, FunctionalTestCnetthinnerEmptyControlNet) {
+
+ // create empty control net
+ ControlNet emptyNet;
+
+ QVector args = {"cnet=emptyNet",
+ "onet=" + tempDir.path() + "/failNet",
+ "maxpoints=20",
+ };
+
+ UserInterface options(APP_XML, args);
+
+ try {
+ cnetthinner(options);
+ FAIL() << "Expected Exception for invalid, empty control network file";
+ }
+ catch(IException &e) {
+ EXPECT_TRUE(e.toString().toLatin1().contains("Invalid control network"))
+ << e.toString().toStdString();
+ }
+}
+
+
+/**
+ * CnetthinnerDefault
+ *
+ * Input ...
+ * 1) ControlNet with 481 points (data/cnetthinner/customPointsTruth.pvl)
+ * 2) maxpoints=20000
+ * 3) suppressed=ignore (suppressed points are to be ignored in output net)
+ * 4) networkid=testID
+ *
+ * Output ...
+ * 1) thinned ControlNet (10 points should have been ignored)
+ * 2) Pvl log file.
+ */
+TEST_F(Cnetthinner, FunctionalTestCnetthinnerDefault) {
+
+ QVector args = {"cnet=" + cnetFile,
+ "onet=" + tempDir.path() + "/out.net",
+ "maxpoints=20000",
+ "suppressed=ignore",
+ "networkid=testID"
+ };
+
+ UserInterface ui(APP_XML, args);
+
+ try {
+ cnetthinner(ui);
+ }
+ catch(IException &e) {
+ FAIL() << e.toString().toStdString().c_str() << std::endl;
+ }
+
+ // check output ControlNetwork
+ ControlNet outNet(tempDir.path() + "/out.net");
+ EXPECT_EQ(outNet.GetNetworkId().toStdString(), "testID");
+ EXPECT_EQ(outNet.GetNumPoints(), 481);
+ EXPECT_EQ(outNet.GetNumValidPoints(), 471); // 481 - 471 = 10 ignored points
+ EXPECT_EQ(outNet.GetNumEditLockPoints(), 0);
+ EXPECT_EQ(outNet.GetNumMeasures(), 962);
+ EXPECT_EQ(outNet.GetNumIgnoredMeasures(), 0);
+ EXPECT_EQ(outNet.GetNumEditLockMeasures(), 0);
+
+ // confirm id's of 10 ignored points in output ControlNetwork
+ EXPECT_TRUE(outNet.GetPoint("ff_test_339")->IsIgnored());
+ EXPECT_TRUE(outNet.GetPoint("ff_test_363")->IsIgnored());
+ EXPECT_TRUE(outNet.GetPoint("ff_test_387")->IsIgnored());
+ EXPECT_TRUE(outNet.GetPoint("ff_test_398")->IsIgnored());
+ EXPECT_TRUE(outNet.GetPoint("ff_test_413")->IsIgnored());
+ EXPECT_TRUE(outNet.GetPoint("ff_test_466")->IsIgnored());
+ EXPECT_TRUE(outNet.GetPoint("ff_test_606")->IsIgnored());
+ EXPECT_TRUE(outNet.GetPoint("ff_test_717")->IsIgnored());
+ EXPECT_TRUE(outNet.GetPoint("ff_test_727")->IsIgnored());
+ EXPECT_TRUE(outNet.GetPoint("ff_test_754")->IsIgnored());
+}
+
+
+/**
+ * CnetthinnerIgnoreOrRemove
+ *
+ * 1) Cnetthinner is executed twice with max points of 200. In the
+ * first output ControlNet (ignored.net) the suppressed points
+ * are ignored. In the second (removed.net) the suppressed points
+ * are removed.
+ *
+ * Input run 1...
+ * 1) ControlNet with 481 points (data/cnetthinner/customPointsTruth.pvl)
+ * 2) maxpoints=200
+ * 3) suppressed=ignore (suppressed points are to be ignored in output net)
+
+ * Input run 2...
+ * 1) ControlNet with 481 points (data/cnetthinner/customPointsTruth.pvl)
+ * 2) maxpoints=200
+ * 3) suppressed=remove (suppressed points are to be removed in output net)
+ *
+ * 2) Cnetedit is used to delete the ignored points in ignored.net.
+ * The result is in ignored_removed.net.
+ *
+ * 3) Cnetdiff is then used to compare ignored_removed.net and
+ * removed.net. Result in cnetdiff.txt. They should be identical.
+ */
+TEST_F(Cnetthinner, FunctionalTestCnetthinnerIgnoreOrRemove) {
+
+ // Use cnetthinner to suppress points by ignoring in customPointsTruth.net.
+ // Result in ignored.net.
+ QVector args = {"cnet=" + cnetFile,
+ "onet=" + tempDir.path() + "/ignored.net",
+ "maxpoints=200",
+ "suppressed=ignore"
+ };
+
+ UserInterface ui1(APP_XML, args);
+
+ try {
+ cnetthinner(ui1);
+ }
+ catch(IException &e) {
+ FAIL() << "cnetthinner ignore failure: " << e.toString().toStdString().c_str() << std::endl;
+ }
+
+ // Use cnetthinner to suppress points by removing in customPointsTruth.net.
+ // Result in removed.net.
+ args = {"cnet=" + cnetFile,
+ "onet=" + tempDir.path() + "/removed.net",
+ "maxpoints=200",
+ "suppressed=remove"
+ };
+ UserInterface ui2(APP_XML, args);
+
+ try {
+ cnetthinner(ui2);
+ }
+ catch(IException &e) {
+ FAIL() << "cnetthinner remove failure: " << e.toString().toStdString().c_str() << std::endl;
+ }
+
+ // confirm 64 points are ignored in both runs
+ ControlNet ignored(tempDir.path()+ "/ignored.net");
+ EXPECT_EQ(ignored.GetNumPoints(), 481);
+ EXPECT_EQ(ignored.GetNumValidPoints(), 417);
+
+ ControlNet removed(tempDir.path()+ "/removed.net");
+ EXPECT_EQ(removed.GetNumPoints(), 417);
+ EXPECT_EQ(removed.GetNumValidPoints(), 417);
+
+ // use cnetedit to delete ignored points in removed.net. Result in ignored_removed.net.
+ args = {"cnet=" + tempDir.path() + "/ignored.net",
+ "onet=" + tempDir.path() + "/ignored_removed.net",
+ "ignore=no",
+ "delete=yes"
+ };
+
+ UserInterface ui3(APP2_XML, args);
+
+ try {
+ cnetedit(ui3);
+ }
+ catch(IException &e) {
+ FAIL() << "cnetedit failure to delete removed points: " << e.toString().toStdString().c_str() << std::endl;
+ }
+
+ // Use cnetdiff to compare ignored_removed.net and removed.net.
+ // Result in cnetdiff.txt. They should be identical.
+ args = {"from=" + tempDir.path() + "/ignored_removed.net",
+ "from2=" + tempDir.path() + "/removed.net",
+ "to=" + tempDir.path() + "/compareIgnored_IgnoredRemoved.txt",
+ "report=full"
+ };
+
+ UserInterface ui4(APP1_XML, args);
+
+ try {
+ cnetdiff(ui4);
+ }
+ catch(IException &e) {
+ FAIL() << "cnetdiff failure to compare networks: " << e.toString().toStdString().c_str() << std::endl;
+ }
+
+ // read back compareIgnored_IgnoredRemoved log file
+ Pvl compareIgnored_IgnoredRemoved;
+ try {
+ compareIgnored_IgnoredRemoved.read(tempDir.path()+ "/compareIgnored_IgnoredRemoved.txt");
+ }
+ catch (IException &e) {
+ FAIL() << "Unable to open error log pvl file: " << e.what() << std::endl;
+ }
+
+ // confirm output filenames and that there are no groups or objects
+ // in the difference object confirming cnets are identical
+ ASSERT_TRUE(compareIgnored_IgnoredRemoved.hasObject("Differences"));
+ PvlObject differences = compareIgnored_IgnoredRemoved.findObject("Differences");
+ EXPECT_EQ(differences["Filename"][0].toStdString(), "ignored_removed.net");
+ EXPECT_EQ(differences["Filename"][1].toStdString(), "removed.net");
+ EXPECT_EQ(differences.groups(), 0);
+ EXPECT_EQ(differences.objects(), 0);
+}
+
+
+/**
+ * CnetthinnerMinMaxPoints
+ *
+ * Runs cnetthinner three times with different maxpoints (50, 200,
+ * 400) and verifies the number of points in the output ControlNetworks.
+ *
+ * Input...
+ * 1) ControlNet with 481 points (data/cnetthinner/customPointsTruth.pvl)
+ * 2) maxpoints=50 (200, 400)
+ * 3) suppressed=remove (default)
+ * expected
+ * maxpoints = 50 => 50.net with 101 points
+ * = 200 => 200.net with 417 points
+ * = 400 => 400.net with 471 points
+ */
+TEST_F(Cnetthinner, FunctionalTestCnetthinnerMinMaxPoints) {
+
+ QVector args = {"cnet=" + cnetFile,
+ "onet=" + tempDir.path() + "/50.net",
+ "maxpoints=50",
+ };
+ UserInterface ui1(APP_XML, args);
+
+ try {
+ cnetthinner(ui1);
+ }
+ catch(IException &e) {
+ FAIL() << e.toString().toStdString().c_str() << std::endl;
+ }
+
+ ControlNet outNet50(tempDir.path()+ "/50.net");
+ EXPECT_EQ(outNet50.GetNumPoints(), 101);
+
+ args = {"cnet=" + cnetFile,
+ "onet=" + tempDir.path() + "/200.net",
+ "maxpoints=200",
+ };
+ UserInterface ui2(APP_XML, args);
+
+ try {
+ cnetthinner(ui2);
+ }
+ catch(IException &e) {
+ FAIL() << e.toString().toStdString().c_str() << std::endl;
+ }
+
+ ControlNet outNet200(tempDir.path()+ "/200.net");
+ EXPECT_EQ(outNet200.GetNumPoints(), 417);
+
+ args = {"cnet=" + cnetFile,
+ "onet=" + tempDir.path() + "/400.net",
+ "maxpoints=400",
+ };
+ UserInterface ui3(APP_XML, args);
+
+ try {
+ cnetthinner(ui3);
+ }
+ catch(IException &e) {
+ FAIL() << e.toString().toStdString().c_str() << std::endl;
+ }
+
+ ControlNet outNet400(tempDir.path()+"/400.net");
+ EXPECT_EQ(outNet400.GetNumPoints(), 471);
+}
+
+
+/**
+ * CnetthinnerTolerance
+ *
+ * Runs cnetthinner three times with maxpoints = 200 and different
+ * tolerances (0.0, 0.5, 1.0) and verifies number of points in
+ * output ControlNetworks.
+ *
+ * Input...
+ * 1) ControlNet with 481 points (data/cnetthinner/customPointsTruth.pvl)
+ * 2) maxpoints=200
+ * 3) tolerance=0.0 (0.5, 1.0)
+ * 4) suppressed=remove (default)
+ *
+ * expected
+ * tolerance = 0.0 => tolSmall.net with 427 points
+ * tolerance = 0.5 => tolMedium.net with 418 points
+ * tolerance = 1.0 => tolLarge.net with 1 point
+ */
+TEST_F(Cnetthinner, FunctionalTestCnetthinnerTolerance) {
+
+ QVector args = {"cnet=" + cnetFile,
+ "onet=" + tempDir.path() + "/tolSmall.net",
+ "maxpoints=200",
+ "tolerance=0.0"
+ };
+ UserInterface ui1(APP_XML, args);
+
+ try {
+ cnetthinner(ui1);
+ }
+ catch(IException &e) {
+ FAIL() << e.toString().toStdString().c_str() << std::endl;
+ }
+
+ ControlNet smallTol(tempDir.path()+"/tolSmall.net");
+ EXPECT_EQ(smallTol.GetNumPoints(), 427);
+
+ args = {"cnet=" + cnetFile,
+ "onet=" + tempDir.path() + "/tolMedium.net",
+ "maxpoints=200",
+ "tolerance=0.5"
+ };
+ UserInterface ui2(APP_XML, args);
+
+ try {
+ cnetthinner(ui2);
+ }
+ catch(IException &e) {
+ FAIL() << e.toString().toStdString().c_str() << std::endl;
+ }
+
+ ControlNet mediumTol(tempDir.path()+"/tolMedium.net");
+ EXPECT_EQ(mediumTol.GetNumPoints(), 418);
+
+ args = {"cnet=" + cnetFile,
+ "onet=" + tempDir.path() + "/tolLarge.net",
+ "maxpoints=200",
+ "tolerance=1.0"
+ };
+ UserInterface ui3(APP_XML, args);
+
+ try {
+ cnetthinner(ui3);
+ }
+ catch(IException &e) {
+ FAIL() << e.toString().toStdString().c_str() << std::endl;
+ }
+
+ ControlNet largeTol(tempDir.path()+"/tolLarge.net");
+ EXPECT_EQ(largeTol.GetNumPoints(), 1);
+}
+
+
+/**
+ * CnetthinnerWeight
+ *
+ * Runs cnetthinner four times with maxpoints=200 and different weights
+ * (0.0, 0.5, 1.0, 10,000.0) and verifies number of points in output
+ * control networks. Note all output nets contain 417 points.
+ *
+ * Input...
+ * 1) ControlNet with 481 points (data/cnetthinner/customPointsTruth.pvl)
+ * 2) maxpoints=200
+ * 3) weight=0.0 (0.5, 1.0, 10,000.0)
+ * 4) suppressed=remove (default)
+ * expected
+ * weight = 0.0 => Small.net with 417 points
+ * weight = 0.5 => Medium.net with 417 points
+ * weight = 1.0 => Large.net with 417 points
+ * weight = 10,000.0 => XLarge.net with 417 points
+ */
+TEST_F(Cnetthinner, FunctionalTestCnetthinnerWeight) {
+
+ QVector args = {"cnet=" + cnetFile,
+ "onet=" + tempDir.path() + "/Small.net",
+ "maxpoints=200",
+ "weight=0.0"
+ };
+ UserInterface ui1(APP_XML, args);
+
+ try {
+ cnetthinner(ui1);
+ }
+ catch(IException &e) {
+ FAIL() << e.toString().toStdString().c_str() << std::endl;
+ }
+
+ ControlNet smallWeight(tempDir.path()+"/Small.net");
+ EXPECT_EQ(smallWeight.GetNumPoints(), 417);
+
+ args = {"cnet=" + cnetFile,
+ "onet=" + tempDir.path() + "/Medium.net",
+ "maxpoints=200",
+ "weight=0.5"
+ };
+ UserInterface ui2(APP_XML, args);
+
+ try {
+ cnetthinner(ui2);
+ }
+ catch(IException &e) {
+ FAIL() << e.toString().toStdString().c_str() << std::endl;
+ }
+
+ ControlNet mediumWeight(tempDir.path()+"/Medium.net");
+ EXPECT_EQ(mediumWeight.GetNumPoints(), 417);
+
+ args = {"cnet=" + cnetFile,
+ "onet=" + tempDir.path() + "/Large.net",
+ "maxpoints=200",
+ "weight=1.0"
+ };
+ UserInterface ui3(APP_XML, args);
+
+ try {
+ cnetthinner(ui3);
+ }
+ catch(IException &e) {
+ FAIL() << e.toString().toStdString().c_str() << std::endl;
+ }
+
+ ControlNet largeWeight(tempDir.path() + "/Large.net");
+ EXPECT_EQ(largeWeight.GetNumPoints(), 417);
+
+ args = {"cnet=" + cnetFile,
+ "onet=" + tempDir.path() + "/XLarge.net",
+ "maxpoints=200",
+ "weight=10000.0"
+ };
+ UserInterface ui4(APP_XML, args);
+
+ try {
+ cnetthinner(ui4);
+ }
+ catch(IException &e) {
+ FAIL() << e.toString().toStdString().c_str() << std::endl;
+ }
+
+ ControlNet xLargeWeight(tempDir.path() + "/XLarge.net");
+ EXPECT_EQ(xLargeWeight.GetNumPoints(), 417);
+}
diff --git a/isis/tests/data/cnetthinner/customPointsTruth.pvl b/isis/tests/data/cnetthinner/customPointsTruth.pvl
new file mode 100644
index 0000000000..2d3dcd5699
--- /dev/null
+++ b/isis/tests/data/cnetthinner/customPointsTruth.pvl
@@ -0,0 +1,18289 @@
+Object = ControlNetwork
+ NetworkId = "NETTYPE image, POINTID ff_test_???, POINTINDEX 314"
+ TargetName = Mercury
+ UserName = ihumphrey
+ Created = 2016-03-10T11:24:22
+ LastModified = 2016-03-10T11:24:22
+ Description = surf/surf/DescriptorMatcher.BFMatcher@normType:4@crossCheck:-
+ false
+ Version = 5
+
+ Object = ControlPoint
+ PointType = Free
+ PointId = ff_test_314
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+
+ # AprioriLatitude = 39.236947483477
+ AprioriX = -1060689.0304042
+
+ # AprioriLongitude = 235.85772458085
+ AprioriY = -1564143.9334167
+
+ # AprioriRadius = 2440000.0
+ AprioriZ = 1543370.511684
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0242463603:888000
+ MeasureType = Candidate
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 156.60247802734
+ Line = 233.13891601562
+ Reference = True
+ End_Group
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0211981114:916000
+ MeasureType = RegisteredSubPixel
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 213.20182800293
+ Line = 483.25592041016
+ SampleResidual = 0.19805908203125
+ LineResidual = -0.36578369140625
+ GoodnessOfFit = 23866.66015625
+ End_Group
+ End_Object
+
+ Object = ControlPoint
+ PointType = Free
+ PointId = ff_test_315
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+
+ # AprioriLatitude = 34.813658653759
+ AprioriX = -1085439.075363
+
+ # AprioriLongitude = 237.19148766331
+ AprioriY = -1683722.337672
+
+ # AprioriRadius = 2440000.0
+ AprioriZ = 1393018.7017049
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0242463603:888000
+ MeasureType = Candidate
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 677.67840576172
+ Line = 954.65338134766
+ Reference = True
+ End_Group
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0211981114:916000
+ MeasureType = RegisteredSubPixel
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 567.64129638672
+ Line = 966.47857666016
+ SampleResidual = 0.9974365234375
+ LineResidual = -0.6763916015625
+ GoodnessOfFit = 17786.0859375
+ End_Group
+ End_Object
+
+ Object = ControlPoint
+ PointType = Free
+ PointId = ff_test_316
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+
+ # AprioriLatitude = 37.300811596227
+ AprioriX = -1121904.9949419
+
+ # AprioriLongitude = 234.68837835398
+ AprioriY = -1583841.9515784
+
+ # AprioriRadius = 2440000.0
+ AprioriZ = 1478639.1901829
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0242463603:888000
+ MeasureType = Candidate
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 143.59034729004
+ Line = 675.50823974609
+ Reference = True
+ End_Group
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0211981114:916000
+ MeasureType = RegisteredSubPixel
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 197.54563903809
+ Line = 763.94403076172
+ SampleResidual = 0.55642700195312
+ LineResidual = -0.488037109375
+ GoodnessOfFit = 16137.451171875
+ End_Group
+ End_Object
+
+ Object = ControlPoint
+ PointType = Free
+ PointId = ff_test_317
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+
+ # AprioriLatitude = 37.975553798385
+ AprioriX = -978248.27842263
+
+ # AprioriLongitude = 239.42890651291
+ AprioriY = -1656033.7829025
+
+ # AprioriRadius = 2440000.0
+ AprioriZ = 1501393.491277
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0242463603:888000
+ MeasureType = Candidate
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 729.08233642578
+ Line = 236.58532714844
+ Reference = True
+ End_Group
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0211981114:916000
+ MeasureType = RegisteredSubPixel
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 618.74993896484
+ Line = 490.2975769043
+ SampleResidual = 2.1309204101562
+ LineResidual = -0.21551513671875
+ GoodnessOfFit = 15602.76171875
+ End_Group
+ End_Object
+
+ Object = ControlPoint
+ PointType = Free
+ PointId = ff_test_318
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+
+ # AprioriLatitude = 35.903969695878
+ AprioriX = -1107071.4621558
+
+ # AprioriLongitude = 235.93419141743
+ AprioriY = -1637241.429802
+
+ # AprioriRadius = 2440000.0
+ AprioriZ = 1430885.4874588
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0242463603:888000
+ MeasureType = Candidate
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 426.25473022461
+ Line = 849.31207275391
+ Reference = True
+ End_Group
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0211981114:916000
+ MeasureType = RegisteredSubPixel
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 388.60034179688
+ Line = 886.45239257812
+ SampleResidual = 0.57754516601562
+ LineResidual = 0.05718994140625
+ GoodnessOfFit = 10302.791015625
+ End_Group
+ End_Object
+
+ Object = ControlPoint
+ PointType = Free
+ PointId = ff_test_319
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+
+ # AprioriLatitude = 37.122045387698
+ AprioriX = -1066481.603971
+
+ # AprioriLongitude = 236.758588274
+ AprioriY = -1627186.6524883
+
+ # AprioriRadius = 2440000.0
+ AprioriZ = 1472576.1733626
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0242463603:888000
+ MeasureType = Candidate
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 447.98846435547
+ Line = 569.72308349609
+ Reference = True
+ End_Group
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0211981114:916000
+ MeasureType = RegisteredSubPixel
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 406.53558349609
+ Line = 704.71441650391
+ SampleResidual = -1.4452819824219
+ LineResidual = -0.395751953125
+ GoodnessOfFit = 11707.0
+ End_Group
+ End_Object
+
+ Object = ControlPoint
+ PointType = Free
+ PointId = ff_test_320
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+
+ # AprioriLatitude = 37.225096682794
+ AprioriX = -1122148.553483
+
+ # AprioriLongitude = 234.72035163878
+ AprioriY = -1586061.5086299
+
+ # AprioriRadius = 2440000.0
+ AprioriZ = 1476073.0045491
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0242463603:888000
+ MeasureType = Candidate
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 154.03085327148
+ Line = 687.65460205078
+ Reference = True
+ End_Group
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0211981114:916000
+ MeasureType = RegisteredSubPixel
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 203.86508178711
+ Line = 772.35717773438
+ SampleResidual = 0.073532104492188
+ LineResidual = -0.1192626953125
+ GoodnessOfFit = 12686.533203125
+ End_Group
+ End_Object
+
+ Object = ControlPoint
+ PointType = Free
+ PointId = ff_test_321
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+
+ # AprioriLatitude = 37.807702609501
+ AprioriX = -1049406.6771755
+
+ # AprioriLongitude = 237.01899357436
+ AprioriY = -1617117.9372698
+
+ # AprioriRadius = 2440000.0
+ AprioriZ = 1495752.3868808
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0242463603:888000
+ MeasureType = Candidate
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 429.95001220703
+ Line = 426.19592285156
+ Reference = True
+ End_Group
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0211981114:916000
+ MeasureType = RegisteredSubPixel
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 397.29000854492
+ Line = 611.23797607422
+ SampleResidual = -0.38421630859375
+ LineResidual = -0.0447998046875
+ GoodnessOfFit = 9942.349609375
+ End_Group
+ End_Object
+
+ Object = ControlPoint
+ PointType = Free
+ PointId = ff_test_322
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+
+ # AprioriLatitude = 37.265071688469
+ AprioriX = -975638.36569347
+
+ # AprioriLongitude = 239.839392008
+ AprioriY = -1678968.6499662
+
+ # AprioriRadius = 2440000.0
+ AprioriZ = 1477428.1883793
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0242463603:888000
+ MeasureType = Candidate
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 835.53594970703
+ Line = 335.50216674805
+ Reference = True
+ End_Group
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0211981114:916000
+ MeasureType = RegisteredSubPixel
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 696.2099609375
+ Line = 558.11279296875
+ SampleResidual = 1.7590942382812
+ LineResidual = 0.0885009765625
+ GoodnessOfFit = 8095.63671875
+ End_Group
+ End_Object
+
+ Object = ControlPoint
+ PointType = Free
+ PointId = ff_test_323
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+
+ # AprioriLatitude = 37.288682654739
+ AprioriX = -1119590.9715748
+
+ # AprioriLongitude = 234.77856801236
+ AprioriY = -1585861.660552
+
+ # AprioriRadius = 2440000.0
+ AprioriZ = 1478228.2807332
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0242463603:888000
+ MeasureType = Candidate
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 157.56173706055
+ Line = 671.78375244141
+ Reference = True
+ End_Group
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0211981114:916000
+ MeasureType = RegisteredSubPixel
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 206.36582946777
+ Line = 762.6845703125
+ SampleResidual = -0.058090209960938
+ LineResidual = 0.19110107421875
+ GoodnessOfFit = 8675.7783203125
+ End_Group
+ End_Object
+
+ Object = ControlPoint
+ PointType = Free
+ PointId = ff_test_324
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+
+ # AprioriLatitude = 39.360955513805
+ AprioriX = -1070131.5354237
+
+ # AprioriLongitude = 235.44130736821
+ AprioriY = -1553639.1530443
+
+ # AprioriRadius = 2440000.0
+ AprioriZ = 1547457.2301099
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0242463603:888000
+ MeasureType = Candidate
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 88.229095458984
+ Line = 235.3752746582
+ Reference = True
+ End_Group
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0211981114:916000
+ MeasureType = RegisteredSubPixel
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 167.74085998535
+ Line = 483.50354003906
+ SampleResidual = 0.45550537109375
+ LineResidual = -1.0115051269531
+ GoodnessOfFit = 6698.5913085938
+ End_Group
+ End_Object
+
+ Object = ControlPoint
+ PointType = Free
+ PointId = ff_test_325
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+
+ # AprioriLatitude = 36.238102443085
+ AprioriX = -1018698.4668487
+
+ # AprioriLongitude = 238.82692978321
+ AprioriY = -1683856.7148217
+
+ # AprioriRadius = 2440000.0
+ AprioriZ = 1442386.9098097
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0242463603:888000
+ MeasureType = Candidate
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 787.26403808594
+ Line = 586.43414306641
+ Reference = True
+ End_Group
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0211981114:916000
+ MeasureType = RegisteredSubPixel
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 653.19403076172
+ Line = 726.09155273438
+ SampleResidual = -0.775390625
+ LineResidual = 0.5059814453125
+ GoodnessOfFit = 5986.923828125
+ End_Group
+ End_Object
+
+ Object = ControlPoint
+ PointType = Free
+ PointId = ff_test_326
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+
+ # AprioriLatitude = 34.87785881856
+ AprioriX = -1090406.8493615
+
+ # AprioriLongitude = 236.99325925735
+ AprioriY = -1678646.9117975
+
+ # AprioriRadius = 2440000.0
+ AprioriZ = 1395262.5016025
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0242463603:888000
+ MeasureType = Candidate
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 646.41381835938
+ Line = 957.76654052734
+ Reference = True
+ End_Group
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0211981114:916000
+ MeasureType = RegisteredSubPixel
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 544.60992431641
+ Line = 966.98797607422
+ SampleResidual = 0.8726806640625
+ LineResidual = -0.68365478515625
+ GoodnessOfFit = 5985.7709960938
+ End_Group
+ End_Object
+
+ Object = ControlPoint
+ PointType = Free
+ PointId = ff_test_327
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+
+ # AprioriLatitude = 38.027421378047
+ AprioriX = -982755.72725906
+
+ # AprioriLongitude = 239.24873129966
+ AprioriY = -1651780.6254416
+
+ # AprioriRadius = 2440000.0
+ AprioriZ = 1503134.0412469
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0242463603:888000
+ MeasureType = Candidate
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 702.46936035156
+ Line = 239.14877319336
+ Reference = True
+ End_Group
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0211981114:916000
+ MeasureType = RegisteredSubPixel
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 599.02191162109
+ Line = 491.92782592773
+ SampleResidual = 2.0950927734375
+ LineResidual = -0.06201171875
+ GoodnessOfFit = 6969.4208984375
+ End_Group
+ End_Object
+
+ Object = ControlPoint
+ PointType = Free
+ PointId = ff_test_328
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+
+ # AprioriLatitude = 38.838825569661
+ AprioriX = -1020094.4022418
+
+ # AprioriLongitude = 237.53821668752
+ AprioriY = -1603586.8224477
+
+ # AprioriRadius = 2440000.0
+ AprioriZ = 1530201.5270503
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0242463603:888000
+ MeasureType = Candidate
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 417.04263305664
+ Line = 201.90640258789
+ Reference = True
+ End_Group
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0211981114:916000
+ MeasureType = RegisteredSubPixel
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 393.69543457031
+ Line = 465.18078613281
+ SampleResidual = 1.3502807617188
+ LineResidual = -0.19497680664062
+ GoodnessOfFit = 6181.904296875
+ End_Group
+ End_Object
+
+ Object = ControlPoint
+ PointType = Free
+ PointId = ff_test_329
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+
+ # AprioriLatitude = 38.762578399991
+ AprioriX = -1014081.297961
+
+ # AprioriLongitude = 237.79145635943
+ AprioriY = -1609801.3737332
+
+ # AprioriRadius = 2440000.0
+ AprioriZ = 1527670.9914941
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0242463603:888000
+ MeasureType = Candidate
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 456.59005737305
+ Line = 199.84687805176
+ Reference = True
+ End_Group
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0211981114:916000
+ MeasureType = RegisteredSubPixel
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 421.73135375977
+ Line = 464.3327331543
+ SampleResidual = 1.5093078613281
+ LineResidual = 0.0496826171875
+ GoodnessOfFit = 6015.2216796875
+ End_Group
+ End_Object
+
+ Object = ControlPoint
+ PointType = Free
+ PointId = ff_test_330
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+
+ # AprioriLatitude = 39.353067310845
+ AprioriX = -1071886.2228608
+
+ # AprioriLongitude = 235.38103860751
+ AprioriY = -1552687.9463118
+
+ # AprioriRadius = 2440000.0
+ AprioriZ = 1547197.4879178
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0242463603:888000
+ MeasureType = Candidate
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 80.374801635742
+ Line = 240.61804199219
+ Reference = True
+ End_Group
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0211981114:916000
+ MeasureType = RegisteredSubPixel
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 162.87272644043
+ Line = 487.92306518555
+ SampleResidual = 0.88825988769531
+ LineResidual = 0.15762329101562
+ GoodnessOfFit = 5205.0224609375
+ End_Group
+ End_Object
+
+ Object = ControlPoint
+ PointType = Free
+ PointId = ff_test_331
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+
+ # AprioriLatitude = 38.919371426236
+ AprioriX = -1015222.8317097
+
+ # AprioriLongitude = 237.67104001127
+ AprioriY = -1604128.0148956
+
+ # AprioriRadius = 2440000.0
+ AprioriZ = 1532871.7864852
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0242463603:888000
+ MeasureType = Candidate
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 428.04635620117
+ Line = 178.54711914062
+ Reference = True
+ End_Group
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0211981114:916000
+ MeasureType = RegisteredSubPixel
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 401.80944824219
+ Line = 449.71115112305
+ SampleResidual = 1.3468322753906
+ LineResidual = -0.55230712890625
+ GoodnessOfFit = 5753.3354492188
+ End_Group
+ End_Object
+
+ Object = ControlPoint
+ PointType = Free
+ PointId = ff_test_332
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+
+ # AprioriLatitude = 36.622519693115
+ AprioriX = -1155650.1055873
+
+ # AprioriLongitude = 233.83387707676
+ AprioriY = -1580956.126731
+
+ # AprioriRadius = 2440000.0
+ AprioriZ = 1455558.5040828
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0242463603:888000
+ MeasureType = Candidate
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 69.853340148926
+ Line = 861.07446289062
+ Reference = True
+ End_Group
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0211981114:916000
+ MeasureType = RegisteredSubPixel
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 145.3971862793
+ Line = 879.48895263672
+ SampleResidual = 0.56893920898438
+ LineResidual = 0.11676025390625
+ GoodnessOfFit = 5474.392578125
+ End_Group
+ End_Object
+
+ Object = ControlPoint
+ PointType = Free
+ PointId = ff_test_333
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+
+ # AprioriLatitude = 37.346175644245
+ AprioriX = -1067663.4137117
+
+ # AprioriLongitude = 236.6049097048
+ AprioriY = -1619498.5110191
+
+ # AprioriRadius = 2440000.0
+ AprioriZ = 1480175.4652164
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0242463603:888000
+ MeasureType = Candidate
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 409.74639892578
+ Line = 538.86083984375
+ Reference = True
+ End_Group
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0211981114:916000
+ MeasureType = RegisteredSubPixel
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 380.05603027344
+ Line = 684.30218505859
+ SampleResidual = -1.561767578125
+ LineResidual = 0.24407958984375
+ GoodnessOfFit = 6123.8134765625
+ End_Group
+ End_Object
+
+ Object = ControlPoint
+ PointType = Free
+ PointId = ff_test_334
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+
+ # AprioriLatitude = 38.920836718329
+ AprioriX = -1060334.9423754
+
+ # AprioriLongitude = 236.04412051281
+ AprioriY = -1574625.3693701
+
+ # AprioriRadius = 2440000.0
+ AprioriZ = 1532920.3358667
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0242463603:888000
+ MeasureType = Candidate
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 208.0693359375
+ Line = 281.35430908203
+ Reference = True
+ End_Group
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0211981114:916000
+ MeasureType = RegisteredSubPixel
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 246.36311340332
+ Line = 513.29736328125
+ SampleResidual = -0.57200622558594
+ LineResidual = -1.4888305664062
+ GoodnessOfFit = 5996.2998046875
+ End_Group
+ End_Object
+
+ Object = ControlPoint
+ PointType = Free
+ PointId = ff_test_335
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+
+ # AprioriLatitude = 34.824426739409
+ AprioriX = -1100781.3037546
+
+ # AprioriLongitude = 236.66292753151
+ AprioriY = -1673418.7831843
+
+ # AprioriRadius = 2440000.0
+ AprioriZ = 1393395.1691427
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0242463603:888000
+ MeasureType = Candidate
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 605.38446044922
+ Line = 991.28607177734
+ Reference = True
+ End_Group
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0211981114:916000
+ MeasureType = RegisteredSubPixel
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 514.25762939453
+ Line = 987.63287353516
+ SampleResidual = 0.8905029296875
+ LineResidual = -0.16192626953125
+ GoodnessOfFit = 4901.33984375
+ End_Group
+ End_Object
+
+ Object = ControlPoint
+ PointType = Free
+ PointId = ff_test_336
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+
+ # AprioriLatitude = 38.920916926108
+ AprioriX = -1061912.1463328
+
+ # AprioriLongitude = 235.98666782101
+ AprioriY = -1573559.5603333
+
+ # AprioriRadius = 2440000.0
+ AprioriZ = 1532922.9933544
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0242463603:888000
+ MeasureType = Candidate
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 200.09703063965
+ Line = 284.96878051758
+ Reference = True
+ End_Group
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0211981114:916000
+ MeasureType = RegisteredSubPixel
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 240.5265045166
+ Line = 516.58654785156
+ SampleResidual = -0.95066833496094
+ LineResidual = -0.42315673828125
+ GoodnessOfFit = 6196.02734375
+ End_Group
+ End_Object
+
+ Object = ControlPoint
+ PointType = Free
+ PointId = ff_test_337
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+
+ # AprioriLatitude = 39.072256503891
+ AprioriX = -1058941.8732822
+
+ # AprioriLongitude = 236.01226521507
+ AprioriY = -1570671.0582263
+
+ # AprioriRadius = 2440000.0
+ AprioriZ = 1537931.902218
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0242463603:888000
+ MeasureType = Candidate
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 191.41999816895
+ Line = 254.71220397949
+ Reference = True
+ End_Group
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0211981114:916000
+ MeasureType = RegisteredSubPixel
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 235.37939453125
+ Line = 497.71557617188
+ SampleResidual = -0.72926330566406
+ LineResidual = 0.07891845703125
+ GoodnessOfFit = 5205.8994140625
+ End_Group
+ End_Object
+
+ Object = ControlPoint
+ PointType = Free
+ PointId = ff_test_338
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+
+ # AprioriLatitude = 38.668998660692
+ AprioriX = -1050865.667373
+
+ # AprioriLongitude = 236.52221022078
+ AprioriY = -1589022.8241249
+
+ # AprioriRadius = 2440000.0
+ AprioriZ = 1524561.5151731
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0242463603:888000
+ MeasureType = Candidate
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 294.11459350586
+ Line = 298.36846923828
+ Reference = True
+ End_Group
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0211981114:916000
+ MeasureType = RegisteredSubPixel
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 305.09426879883
+ Line = 527.3466796875
+ SampleResidual = -0.27960205078125
+ LineResidual = 0.73541259765625
+ GoodnessOfFit = 4783.4775390625
+ End_Group
+ End_Object
+
+ Object = ControlPoint
+ PointType = Free
+ PointId = ff_test_339
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+
+ # AprioriLatitude = 34.814755735042
+ AprioriX = -1100100.7041885
+
+ # AprioriLongitude = 236.69064768019
+ AprioriY = -1674147.6845622
+
+ # AprioriRadius = 2440000.0
+ AprioriZ = 1393057.0594627
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0242463603:888000
+ MeasureType = Candidate
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 609.85626220703
+ Line = 990.98187255859
+ Reference = True
+ End_Group
+
+ Group = ControlMeasure
+ SerialNumber = MeSSEnGeR/MDIS-WAC/1/0211981114:916000
+ MeasureType = RegisteredSubPixel
+ ChooserName = findfeatures
+ DateTime = 2016-03-10T11:24:22
+ Sample = 517.21649169922
+ Line = 987.68682861328
+ SampleResidual = 0.60589599609375