USGS

Isis 3.0 Application Source Code Reference

Home

ControlByRow.h

Go to the documentation of this file.
00001 #ifndef ControlByRow_h
00002 #define ControlByRow_h
00003 /**
00004  * @file
00005  * $Revision: 1.2 $
00006  * $Date: 2007/01/30 22:12:21 $
00007  *
00008  *   Unless noted otherwise, the portions of Isis written by the USGS are
00009  *   public domain. See individual third-party library and package descriptions
00010  *   for intellectual property information, user agreements, and related
00011  *   information.
00012  *
00013  *   Although Isis has been used by the USGS, no warranty, expressed or
00014  *   implied, is made by the USGS as to the accuracy and functioning of such
00015  *   software and related material nor shall the fact of distribution
00016  *   constitute any such warranty, and no responsibility is assumed by the
00017  *   USGS in connection therewith.
00018  *
00019  *   For additional information, launch
00020  *   $ISISROOT/doc//documents/Disclaimers/Disclaimers.html
00021  *   in a browser or see the Privacy & Disclaimers page on the Isis website,
00022  *   http://isis.astrogeology.usgs.gov, and the USGS privacy and disclaimers on
00023  *   http://www.usgs.gov/privacy.html.
00024  */
00025 
00026 #include <vector>
00027 #include "ControlMeasure.h"
00028 #include "ControlMeasureLogData.h"
00029 #include "Statistics.h"
00030 #include "CollectorMap.h"
00031 #include "iString.h"
00032 #include <gsl/gsl_math.h>
00033 
00034 namespace Isis {
00035 
00036   /**
00037    * @brief Container for point collection
00038    */
00039   struct PointData {
00040     ControlMeasure refPoint;
00041     ControlMeasure chpPoint;
00042   };
00043 
00044   /**
00045    * @brief Less than test for Control point group
00046    *
00047    * This function tests the reference line numbers and returns true if the first
00048    * point reference line is less than the second.
00049    *
00050    * @param p1  First PointData set to compare
00051    * @param p2  Second PointData set to compare
00052    *
00053    * @return bool If first point reference line is less than the second
00054    */
00055   inline bool PointLess(const PointData &p1, const PointData &p2) {
00056     return (p1.refPoint.GetLine() < p2.refPoint.GetLine());
00057   }
00058 
00059   /**
00060    * @brief Equality test for Control point group
00061    *
00062    * This function tests the reference line numbers for equality and returns true
00063    * if the line references are equivalent, according to an approximation using an
00064    * epsilon of 1.0e-6.
00065    *
00066    * @param p1  First PointData set to compare
00067    * @param p2  Second PointData set to compare
00068    *
00069    * @return bool If the reference point lines are (approximately) equivalent
00070    */
00071   inline bool PointEqual(const PointData &p1, const PointData &p2) {
00072     return (gsl_fcmp(p1.refPoint.GetLine(), p2.refPoint.GetLine(), 1.0E-6) == 0);
00073   }
00074 
00075   /**
00076    * @brief Collector for Control points within the same row for analysis
00077    *
00078    * This class is designed to be used as a Functor object collecting control net
00079    * file and collapsing all column measures into on row.  This is primarily used
00080    * for analysis of coregistration results with one or more columns specified
00081    * in the search/pattern chip strategy.
00082    *
00083    * @author ????-??-?? Unknown
00084    *
00085    * @internal
00086    */
00087   class ControlByRow {
00088     public:
00089       /**
00090        * @brief Structure to return control point statistics for row
00091        *
00092        * This structure contains the row statistics of merged control points.
00093        * This will eventually be used to compute the spline interpolations for
00094        * line and sample offsets.
00095        *
00096        */
00097       struct RowPoint {
00098         RowPoint() : refLine(0.0), refSamp(0.0), chpLine(0.0), chpSamp(0.0),
00099           total(0), count(0) { }
00100         double refLine;    //!<  Reference line (row)
00101         double refSamp;    //!<  Reference sample
00102         double chpLine;    //!<  Registered line
00103         double chpSamp;    //!<  Registered sample
00104         int total;         //!<  Total points in row
00105         int count;         //!<  Valid points found
00106 
00107         Statistics rSStats;
00108         Statistics cLStats;
00109         Statistics cSStats;
00110         Statistics cLOffset;
00111         Statistics cSOffset;
00112         Statistics GOFStats;
00113       };
00114 
00115     public:
00116       /**
00117        * @brief Default constructor
00118        */
00119       ControlByRow()  {
00120         _minGOF = DBL_MIN;
00121         _maxGOF = DBL_MAX;
00122       }
00123 
00124       /**
00125        * @brief Constructor that sets the maximum goodness of fit tolerance
00126        * @param maxGOF Value that specifies the maximum goodness of fit which is
00127        *               typically never expected to exceed 1.0 for a good fit.
00128        */
00129       ControlByRow(double maxGOF)  {
00130         _minGOF = DBL_MIN;
00131         _maxGOF = maxGOF;
00132       }
00133 
00134       /**
00135        * @brief Constructor that sets the maximum goodness of fit tolerance
00136        * @param minGOF Value of minimum goodness of fit.  Allows user selectable
00137        *               adjustment to coregistration minimum tolerance
00138        * @param maxGOF Value that specifies the maximum goodness of fit which is
00139        *               typically never expected to exceed 1.0 for a good fit.
00140        */
00141       ControlByRow(double minGOF, double maxGOF)  {
00142         _minGOF = minGOF;
00143         _maxGOF = maxGOF;
00144       }
00145 
00146       /**
00147        * @brief Destructor
00148        */
00149       ~ControlByRow() { }
00150 
00151       /**
00152        * @brief Determines the number of points (rows) found valid
00153        *
00154        * The number returned is really the number of unique rows of coregistration
00155        * chips gleened from the control net.
00156        *
00157        * @return unsigned int Row/line count
00158        */
00159       inline unsigned int size() const {
00160         return (_rowList.size());
00161       }
00162 
00163       /**
00164        * @brief Set the minimum acceptable goodness of fit value
00165        *
00166        * This sets the minimum (absolute) value used to gleen valid points from
00167        * the control net data.
00168        *
00169        * @param minGOF Minimum goodness of fit tolerance
00170        */
00171       void setMinGOF(double minGOF) {
00172         _minGOF = minGOF;
00173       }
00174 
00175       /**
00176        * @brief Set the maximum acceptable goodness of fit value
00177        *
00178        * This sets the maximum (absolute) value used to gleen valid points from
00179        * the control net data.  This is intended to use to exclude wild points
00180        * that exceed the level of reasonable tolerance.  This is typically 1.0 for
00181        * most coregistration algorithms.
00182        *
00183        * @param maxGOF Maximum goodness of fit tolerance
00184        */
00185       void setMaxGOF(double maxGOF) {
00186         _maxGOF = maxGOF;
00187       }
00188 
00189       /**
00190        * @brief Operator used to add a point to the data set
00191        *
00192        * This method provides support for the STL for_each algorithm.  This allows
00193        * this class to be used as a functor object.
00194        *
00195        * @param p Point to tested for acceptance in the list
00196        */
00197       void operator()(const PointData &p) {
00198         addPoint(p);
00199         return;
00200       }
00201 
00202       /**
00203        * @brief Formal method of adding a control point to the data set
00204        *
00205        * This method will add the provided point to the collection of rows (or
00206        * lines of points).
00207        *
00208        * @param p  Point to add to the list
00209        */
00210       void addPoint(const PointData &p) {
00211         if(_rowList.exists(p.refPoint.GetLine())) {
00212           PointList &r = _rowList.get(p.refPoint.GetLine());
00213           r.push_back(p);
00214         }
00215         else {
00216           PointList pl;
00217           pl.push_back(p);
00218           _rowList.add(p.refPoint.GetLine(), pl);
00219         }
00220         return;
00221       }
00222 
00223       /**
00224        * @brief Returns a point at the ith location
00225        *
00226        * Traverses the list of points after computing the merge statistics for the
00227        * ith row.
00228        *
00229        * @param i Index of point to return
00230        *
00231        * @return RowPoint  Structure containing the (statistically) merged row
00232        */
00233       RowPoint operator[](int i) const {
00234         try {
00235           return (computeStats(_rowList.getNth(i)));
00236         }
00237         catch(iException &oor) {
00238           std::string msg = "Requested value (" + iString(i) +  ") not found";
00239           throw iException::Message(Isis::iException::User, msg, _FILEINFO_);
00240         }
00241       }
00242 
00243     private:
00244       typedef std::vector<PointData> PointList;    //!< Composite list
00245       typedef CollectorMap<double, PointList, RobustFloatCompare> CNetRow;  /**
00246                                   * Nifty templated collector class works just
00247                                   * nicely for merging rows of correlations
00248                                                                          */
00249       double            _minGOF;  //!<  Minimum acceptable goodness of fit
00250       double            _maxGOF;  //!<  Maximum acceptable goodness of fit
00251       CNetRow           _rowList; //!<  Collection of merged rows/lines
00252 
00253       /**
00254        * @brief Convenience method for adding point to Statistics class
00255        *
00256        * The interface to the Isis Statistics class requires the value to be added
00257        * by address.  This method expedites the addition of values from say a
00258        * function or method.
00259        *
00260        * @param value  Value to add to Statistics class
00261        * @param stats  Statistics class to add the data point to
00262        */
00263       inline void addToStats(double value, Statistics &stats) const {
00264         stats.AddData(&value, 1);
00265         return;
00266       }
00267 
00268       /**
00269        * @brief  All important method that computes statistics for a row
00270        *
00271        * This method computes the statistics for a potentially merged row of
00272        * coregistration chips.  It applies the minimum and maximum goodness of fit
00273        * tolerance checks and add valid points to each statistical component of
00274        * the merge.
00275        *
00276        * @param cols  List of column chip registrations
00277        *
00278        * @return RowPoint Structure containing the statistics for row/line of
00279        *         merged registration columns
00280        */
00281       RowPoint computeStats(const std::vector<PointData> &cols) const {
00282         RowPoint rp;
00283         rp.refLine = cols[0].refPoint.GetLine();
00284         for(unsigned int i = 0; i < cols.size() ; i++) {
00285           double regGOF =
00286             cols[i].chpPoint.GetLogData(ControlMeasureLogData::GoodnessOfFit)
00287               .GetNumericalValue();
00288           if(fabs(regGOF) > _maxGOF) continue;
00289           if(fabs(regGOF) < _minGOF) continue;
00290           (rp.count)++;
00291           addToStats(cols[i].refPoint.GetSample(), rp.rSStats);
00292           addToStats(cols[i].chpPoint.GetLine(), rp.cLStats);
00293           addToStats(cols[i].chpPoint.GetSample(), rp.cSStats);
00294           addToStats(cols[i].chpPoint.GetLineResidual(), rp.cLOffset);
00295           addToStats(cols[i].chpPoint.GetSampleResidual(), rp.cSOffset);
00296           addToStats(regGOF, rp.GOFStats);
00297         }
00298 
00299         rp.total = cols.size();
00300         rp.refSamp = rp.rSStats.Average();
00301         rp.chpLine = rp.cLStats.Average();
00302         rp.chpSamp = rp.cSStats.Average();
00303         return (rp);
00304       }
00305 
00306   };
00307 
00308 
00309 }  // namespace Isis
00310 
00311 #endif