|
Isis 3.0 Object Programmers' Reference |
Home |
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