USGS

Isis 3.0 Object Programmers' Reference

Home

OverlapStatistics.cpp

Go to the documentation of this file.
00001 
00023 #include "OverlapStatistics.h"
00024 
00025 #include <cfloat>
00026 #include <iomanip>
00027 
00028 #include "Brick.h"
00029 #include "Cube.h"
00030 #include "FileName.h"
00031 #include "IException.h"
00032 #include "MultivariateStatistics.h"
00033 #include "Progress.h"
00034 #include "Projection.h"
00035 #include "ProjectionFactory.h"
00036 #include "PvlObject.h"
00037 
00038 using namespace std;
00039 namespace Isis {
00040 
00055   OverlapStatistics::OverlapStatistics(Isis::Cube &x, Isis::Cube &y,
00056                                        QString progressMsg, double sampPercent) {
00057     // Test to ensure sampling percent in bound
00058     if (sampPercent <= 0.0 || sampPercent > 100.0) {
00059       string msg = "The sampling percent must be a decimal (0.0, 100.0]";
00060       throw IException(IException::Programmer, msg, _FILEINFO_);
00061     }
00062 
00063     p_sampPercent = sampPercent;
00064 
00065     // Extract filenames and band number from cubes
00066     p_xFile = x.fileName();
00067     p_yFile = y.fileName();
00068 
00069     // Make sure number of bands match
00070     if (x.bandCount() != y.bandCount()) {
00071       QString msg = "Number of bands do not match between cubes [" +
00072                    p_xFile.name() + "] and [" + p_yFile.name() + "]";
00073       throw IException(IException::User, msg, _FILEINFO_);
00074     }
00075     p_bands = x.bandCount();
00076     p_stats.resize(p_bands);
00077 
00078     //Create projection from each cube
00079     Projection *projX = x.projection();
00080     Projection *projY = y.projection();
00081 
00082     // Test to make sure projection parameters match
00083     if (*projX != *projY) {
00084       QString msg = "Mapping groups do not match between cubes [" +
00085                    p_xFile.name() + "] and [" + p_yFile.name() + "]";
00086       throw IException(IException::Programmer, msg, _FILEINFO_);
00087     }
00088 
00089     // Figure out the x/y range for both images to find the overlap
00090     double Xmin1 = projX->ToProjectionX(0.5);
00091     double Ymax1 = projX->ToProjectionY(0.5);
00092     double Xmax1 = projX->ToProjectionX(x.sampleCount() + 0.5);
00093     double Ymin1 = projX->ToProjectionY(x.lineCount() + 0.5);
00094 
00095     double Xmin2 = projY->ToProjectionX(0.5);
00096     double Ymax2 = projY->ToProjectionY(0.5);
00097     double Xmax2 = projY->ToProjectionX(y.sampleCount() + 0.5);
00098     double Ymin2 = projY->ToProjectionY(y.lineCount() + 0.5);
00099 
00100     // Find overlap
00101     if ((Xmin1 < Xmax2) && (Xmax1 > Xmin2) && (Ymin1 < Ymax2) && (Ymax1 > Ymin2)) {
00102       double minX = Xmin1 > Xmin2 ? Xmin1 : Xmin2;
00103       double minY = Ymin1 > Ymin2 ? Ymin1 : Ymin2;
00104       double maxX = Xmax1 < Xmax2 ? Xmax1 : Xmax2;
00105       double maxY = Ymax1 < Ymax2 ? Ymax1 : Ymax2;
00106 
00107       // Find Sample range of the overlap
00108       p_minSampX = (int)(projX->ToWorldX(minX) + 0.5);
00109       p_maxSampX = (int)(projX->ToWorldX(maxX) + 0.5);
00110       p_minSampY = (int)(projY->ToWorldX(minX) + 0.5);
00111       p_maxSampY = (int)(projY->ToWorldX(maxX) + 0.5);
00112       p_sampRange = p_maxSampX - p_minSampX + 1;
00113 
00114       // Test to see if there was only sub-pixel overlap
00115       if (p_sampRange <= 0) return;
00116 
00117       // Find Line range of overlap
00118       p_minLineX = (int)(projX->ToWorldY(maxY) + 0.5);
00119       p_maxLineX = (int)(projX->ToWorldY(minY) + 0.5);
00120       p_minLineY = (int)(projY->ToWorldY(maxY) + 0.5);
00121       p_maxLineY = (int)(projY->ToWorldY(minY) + 0.5);
00122       p_lineRange = p_maxLineX - p_minLineX + 1;
00123 
00124       // Print percent processed
00125       Progress progress;
00126       progress.SetText(progressMsg);
00127 
00128       int linc = (int)(100.0 / sampPercent + 0.5); // Calculate our line increment
00129 
00130       // Define the maximum number of steps to be our line range divided by the
00131       // line increment, but if they do not divide evenly, then because of
00132       // rounding, we need to do an additional step for each band
00133       int maxSteps = (int)(p_lineRange / linc + 0.5);
00134 
00135       if (p_lineRange % linc != 0) maxSteps += 1;
00136       maxSteps *= p_bands;
00137 
00138 
00139       progress.SetMaximumSteps(maxSteps);
00140       progress.CheckStatus();
00141 
00142       // Collect and store off the overlap statistics
00143       for (int band = 1; band <= p_bands; band++) {
00144         Brick b1(p_sampRange, 1, 1, x.pixelType());
00145         Brick b2(p_sampRange, 1, 1, y.pixelType());
00146 
00147         int i = 0;
00148         while(i < p_lineRange) {
00149           b1.SetBasePosition(p_minSampX, (i + p_minLineX), band);
00150           b2.SetBasePosition(p_minSampY, (i + p_minLineY), band);
00151           x.read(b1);
00152           y.read(b2);
00153           p_stats[band-1].AddData(b1.DoubleBuffer(), b2.DoubleBuffer(), p_sampRange);
00154 
00155           // Make sure we consider the last line
00156           if (i + linc > p_lineRange - 1 && i != p_lineRange - 1) {
00157             i = p_lineRange - 1;
00158             progress.AddSteps(1);
00159           }
00160           else i += linc; // Increment the current line by our incrementer
00161 
00162           progress.CheckStatus();
00163         }
00164       }
00165     }
00166   }
00167 
00175   bool OverlapStatistics::HasOverlap() const {
00176     for (int b = 0; b < p_bands; b++) {
00177       if (p_stats[b].ValidPixels() > 0) return true;
00178     }
00179     return false;
00180   }
00181 
00182 
00183   PvlObject OverlapStatistics::toPvl() const {
00184     // Output the private variables
00185     try {
00186       PvlObject o("OverlapStatistics");
00187       PvlGroup gX("File1");
00188       PvlKeyword stsX("StartSample", toString(StartSampleX()));
00189       PvlKeyword ensX("EndSample", toString(EndSampleX()));
00190       PvlKeyword stlX("StartLine", toString(StartLineX()));
00191       PvlKeyword enlX("EndLine", toString(EndLineX()));
00192       PvlKeyword avgX("Average");
00193       PvlKeyword stdX("StandardDeviation");
00194       PvlKeyword varX("Variance");
00195       for (int band = 1; band <= Bands(); band++) {
00196         if (HasOverlap(band)) {
00197           avgX += toString(GetMStats(band).X().Average());
00198           stdX += toString(GetMStats(band).X().StandardDeviation());
00199           varX += toString(GetMStats(band).X().Variance());
00200         }
00201       }
00202       gX += stsX;
00203       gX += ensX;
00204       gX += stlX;
00205       gX += enlX;
00206       gX += avgX;
00207       gX += stdX;
00208       gX += varX;
00209 
00210       PvlGroup gY("File2");
00211       PvlKeyword stsY("StartSample", toString(StartSampleY()));
00212       PvlKeyword ensY("EndSample", toString(EndSampleY()));
00213       PvlKeyword stlY("StartLine", toString(StartLineY()));
00214       PvlKeyword enlY("EndLine", toString(EndLineY()));
00215       PvlKeyword avgY("Average");
00216       PvlKeyword stdY("StandardDeviation");
00217       PvlKeyword varY("Variance");
00218       for (int band = 1; band <= Bands(); band++) {
00219         if (HasOverlap(band)) {
00220           avgY += toString(GetMStats(band).Y().Average());
00221           stdY += toString(GetMStats(band).Y().StandardDeviation());
00222           varY += toString(GetMStats(band).Y().Variance());
00223         }
00224       }
00225       gY += stsY;
00226       gY += ensY;
00227       gY += stlY;
00228       gY += enlY;
00229       gY += avgY;
00230       gY += stdY;
00231       gY += varY;
00232 
00233       o += PvlKeyword("File1", FileNameX().name());
00234       o += PvlKeyword("File2", FileNameY().name());
00235       o += PvlKeyword("Width", toString(Samples()));
00236       o += PvlKeyword("Height", toString(Lines()));
00237       o += PvlKeyword("SamplingPercent", toString(SampPercent()));
00238       o.AddGroup(gX);
00239       o.AddGroup(gY);
00240 
00241       PvlKeyword cov("Covariance");
00242       PvlKeyword cor("Correlation");
00243 
00244       PvlKeyword valid("ValidOverlap");
00245       PvlKeyword val("ValidPixels");
00246       PvlKeyword inv("InvalidPixels");
00247       PvlKeyword tot("TotalPixels");
00248       for (int band = 1; band <= Bands(); band++) {
00249         if (HasOverlap(band)) {
00250           QString validStr = "false";
00251           if (IsValid(band)) validStr = "true";
00252           valid += validStr;
00253           cov += toString(GetMStats(band).Covariance());
00254           cor += toString(GetMStats(band).Correlation());
00255           val += toString(GetMStats(band).ValidPixels());
00256           inv += toString(GetMStats(band).InvalidPixels());
00257           tot += toString(GetMStats(band).TotalPixels());
00258         }
00259       }
00260       o += valid;
00261       o += cov;
00262       o += cor;
00263       o += val;
00264       o += inv;
00265       o += tot;
00266 
00267       for (int band = 1; band <= Bands(); band++) {
00268         if (HasOverlap(band)) {
00269           QString bandStr = "LinearRegression" + toString(band);
00270           PvlKeyword LinReg(bandStr);
00271           double a, b;
00272           try {
00273             GetMStats(band).LinearRegression(a, b);
00274             LinReg += toString(a);
00275             LinReg += toString(b);
00276           }
00277           catch (IException &e) {
00278             // It is possible one of the overlaps was constant and therefore
00279             // the regression would be a vertical line (x=c instead of y=ax+b)
00280           }
00281           o += LinReg;
00282         }
00283       }
00284 
00285       return o;
00286     }
00287     catch (IException &e) {
00288       QString msg = "Trivial overlap between [" + FileNameX().name();
00289       msg += "] and [" + FileNameY().name() + "]";
00290       throw IException(IException::User, msg, _FILEINFO_);
00291     }
00292   }
00293 
00294 
00303   std::ostream &operator<<(std::ostream &os, Isis::OverlapStatistics &stats) {
00304     PvlObject p = stats.toPvl();
00305     os << p << endl;
00306     return os;
00307   }
00308 
00309 
00310 }
00311