|
Isis 3.0 Application Source Code Reference |
Home |
00001 #include "Isis.h" 00002 00003 #include <sstream> 00004 #include <string> 00005 #include <float.h> 00006 #include <fstream> 00007 00008 #include "ProcessByLine.h" 00009 00010 #include "Statistics.h" 00011 #include "Pvl.h" 00012 #include "iException.h" 00013 #include "WriteTabular.h" 00014 #include "iString.h" 00015 #include "Pixel.h" 00016 00017 using namespace std; 00018 using namespace Isis; 00019 00020 void compare (vector<Buffer *> &in, 00021 vector<Buffer *> &out); 00022 00023 void diffTable (ofstream &target, int precision); 00024 00025 // This is only used for the difference table 00026 struct Difference { 00027 int lineNum; 00028 int sampNum; 00029 double cube1Val; 00030 double cube2Val; 00031 }; 00032 00033 double tolerance; 00034 bool filesEqual = true; 00035 bool firstDifferenceFound = false; // Set to true when first DN value difference is found 00036 int sample,line,band,spCount,diffCount,colWidth; 00037 Statistics stats; 00038 bool doTable; 00039 unsigned int sigFigAccuracy = DBL_DIG; // DBL_DIG is maximum accuracy for a double 00040 vector<Difference> diffset; 00041 int sigFigLine = 0; 00042 int sigFigSample = 0; 00043 int sigFigBand = 0; 00044 00045 void IsisMain() { 00046 // Set up the two input cubes 00047 ProcessByLine p; 00048 p.SetInputCube("FROM"); 00049 p.SetInputCube("FROM2", SizeMatch); 00050 00051 // Read tolerance value 00052 UserInterface &ui = Application::GetUserInterface(); 00053 if (ui.WasEntered ("TOLERANCE")) { 00054 tolerance = ui.GetDouble("TOLERANCE"); 00055 } 00056 else { 00057 tolerance = DBL_EPSILON; 00058 } 00059 00060 // See if we should output the difference table 00061 if (ui.GetBoolean("OUTPUTDIFFS")){ 00062 doTable = true; 00063 diffCount = ui.GetInteger("COUNT"); 00064 if (!ui.WasEntered("TO")) { 00065 string message = "A target file is required for difference output"; 00066 throw iException::Message(iException::User,message,_FILEINFO_); 00067 } 00068 00069 } 00070 00071 // Compare the cubes 00072 filesEqual = true; 00073 spCount = 0; 00074 stats.Reset(); 00075 colWidth = 0; 00076 p.StartProcess(compare); 00077 00078 // Write to log indicating if two files are filesEqual. 00079 PvlGroup results("Results"); 00080 if (filesEqual) { 00081 results += PvlKeyword ("Compare","Identical"); 00082 } 00083 else { 00084 results += PvlKeyword ("Compare","Different"); 00085 results += PvlKeyword ("Sample",sample); 00086 results += PvlKeyword ("Line",line); 00087 results += PvlKeyword ("Band",band); 00088 if(stats.TotalPixels() < 1) { 00089 results += PvlKeyword ("AverageDifference",0); 00090 results += PvlKeyword ("StandardDeviation",0); 00091 results += PvlKeyword ("Variance",0); 00092 results += PvlKeyword ("MinimumDifference",0); 00093 results += PvlKeyword ("MaximumDifference",0); 00094 } else { 00095 results += PvlKeyword ("AverageDifference",(double)stats.Average()); 00096 results += PvlKeyword ("StandardDeviation",(double)stats.StandardDeviation()); 00097 results += PvlKeyword ("Variance",(double)stats.Variance()); 00098 results += PvlKeyword ("MinimumDifference",(double)stats.Minimum()); 00099 results += PvlKeyword ("MaximumDifference",(double)stats.Maximum()); 00100 } 00101 results += PvlKeyword ("ValidPixelDifferences",stats.TotalPixels()); 00102 results += PvlKeyword ("SpecialPixelDifferences",spCount); 00103 results += PvlKeyword ("SigFigAccuracy", (int)sigFigAccuracy); 00104 results += PvlKeyword ("SigFigMaxDifferenceSample", (int)sigFigSample); 00105 results += PvlKeyword ("SigFigMaxDifferenceLine", (int)sigFigLine); 00106 results += PvlKeyword ("SigFigMaxDifferenceBand", (int)sigFigBand); 00107 } 00108 Application::Log(results); 00109 00110 // Output a file if the user request it 00111 if (ui.WasEntered ("TO")) { 00112 Pvl lab; 00113 lab.AddGroup(results); 00114 lab.Write (ui.GetFilename("TO","txt")); 00115 } 00116 if (doTable) { 00117 string filename = Filename(ui.GetFilename("TO","txt")).Expanded(); 00118 ofstream ofile(filename.c_str(),ios_base::app); 00119 diffTable(ofile, ui.GetInteger("PRECISION")); 00120 } 00121 00122 p.EndProcess(); 00123 filesEqual = true; 00124 } 00125 00126 void compare (vector<Buffer *> &in,vector<Buffer *> &out) { 00127 Buffer &input1 = *in[0]; 00128 Buffer &input2 = *in[1]; 00129 int inputSize = input1.size(); 00130 00131 for (int index = 0; index < inputSize; index ++) { 00132 bool pixelDifferent = false; 00133 bool pixelSpecial = false; 00134 00135 // First check if there is a special pixel in either cube 00136 if(Pixel::IsSpecial(input1[index]) || Pixel::IsSpecial(input2[index])) { 00137 pixelSpecial = true; 00138 00139 // We have special pixels, if they are both special compare them. 00140 if(Pixel::IsSpecial(input1[index]) && Pixel::IsSpecial(input2[index])) { 00141 if(input1[index] != input2[index]) { 00142 spCount ++; 00143 pixelDifferent = true; 00144 } 00145 } 00146 // At least one is special, but not both, so they must be different 00147 else { 00148 spCount ++; 00149 pixelDifferent = true; 00150 } 00151 } 00152 // We don't have any special pixels, run against tolerance 00153 else if(abs(input1[index] - input2[index]) > tolerance) { 00154 // This pixel is different. 00155 pixelDifferent = true; 00156 00157 // Add the difference in dn to the stats object 00158 stats.AddData(abs(input1[index] - input2[index])); 00159 } 00160 00161 // If pixels different & neither are special, calculate the significant figure difference 00162 if(pixelDifferent && !pixelSpecial) { 00163 unsigned int accuracy = 0; 00164 00165 // Check positive/negative and ensure both positive 00166 if((input1[index] < 0 && input2[index] > 0) || 00167 (input1[index] > 0 && input2[index] < 0)) { 00168 accuracy = 1; 00169 } 00170 else { 00171 double in1 = abs(input1[index]); 00172 double in2 = abs(input2[index]); 00173 int in1log = (int)floor(log10(in1)); 00174 int in2log = (int)floor(log10(in2)); 00175 00176 // Check for zeros 00177 if(input1[index] == 0 || input2[index] == 0) { 00178 accuracy = 0; 00179 } 00180 // Check for different decimal places 00181 else if(in1log != in2log) { 00182 accuracy = 0; 00183 } 00184 else { 00185 // int values of log of original - log of difference = # sig fig accuracy 00186 // *The difference can not equal zero because pixelDifferent flag is set to true 00187 accuracy = in1log - (int)floor(log10(abs(in1 - in2))); 00188 } 00189 } 00190 00191 if(accuracy < sigFigAccuracy) { 00192 sigFigSample = input1.Sample(index); 00193 sigFigLine = input1.Line(index); 00194 sigFigBand = input1.Band(index); 00195 sigFigAccuracy = accuracy; 00196 } 00197 } 00198 00199 if(pixelDifferent) { 00200 filesEqual = false; 00201 00202 if (!firstDifferenceFound) { 00203 firstDifferenceFound = true; 00204 sample = input1.Sample(index); 00205 line = input1.Line(index); 00206 band = input1.Band(index); 00207 } 00208 } 00209 00210 // If the user indicated that we should make the table, add this entry 00211 if (pixelDifferent && doTable) { 00212 if ((int)diffset.size() < diffCount) { 00213 Difference currDiff; 00214 currDiff.lineNum = input1.Line(index); 00215 currDiff.sampNum = input1.Sample(index); 00216 currDiff.cube1Val = input1[index]; 00217 currDiff.cube2Val = input2[index]; 00218 diffset.push_back(currDiff); 00219 00220 // Check the character lengths of the values 00221 int val1Length = iString((int)currDiff.cube1Val).length(); 00222 int val2Length = iString((int)currDiff.cube2Val).length(); 00223 if (val1Length < colWidth) { 00224 colWidth = val1Length; 00225 } 00226 if (val2Length < colWidth) { 00227 colWidth = val2Length; 00228 } 00229 } 00230 } 00231 } 00232 } 00233 00234 //Function to prepare the table to append to the 00235 void diffTable(ofstream &target, int precision) { 00236 vector<int> temp; 00237 00238 //Make a list of all samples present 00239 for (unsigned int i=0; i<diffset.size(); i++) { 00240 temp.push_back(diffset[i].sampNum); 00241 } 00242 00243 //Sort the list 00244 sort(temp.begin(),temp.end()); 00245 00246 //Remove duplicates 00247 vector<int> samps; 00248 samps.push_back(temp[0]); 00249 for (unsigned int i=1; i<temp.size(); i++) { 00250 if ( temp[i] != samps.back()) { 00251 samps.push_back(temp[i]); 00252 } 00253 } 00254 vector<Column> cols; 00255 //Add the first Column 00256 Column first("Line#", 7, Column::Integer); 00257 cols.push_back(first); 00258 00259 for (unsigned int i=0; i<samps.size(); i++) { 00260 Column currCol; 00261 //Prepare and add the first file's column 00262 currCol.SetName(iString("File1_") + iString(samps[i])); 00263 if ((unsigned int)(colWidth + precision + 1) < currCol.Name().length()) { 00264 currCol.SetWidth(currCol.Name().length() + 1); 00265 } 00266 else currCol.SetWidth(colWidth + precision + 1); 00267 00268 currCol.SetType(Column::Pixel); 00269 currCol.SetAlignment(Column::Decimal); 00270 currCol.SetPrecision(precision); 00271 cols.push_back(currCol); 00272 00273 //Prepare and add the second file's column 00274 currCol.SetName(iString("File2_") + iString(samps[i])); 00275 cols.push_back(currCol); 00276 } 00277 00278 WriteTabular diffs(target, cols); 00279 00280 //Go through the entire list of differences and make the table 00281 for (unsigned int i=0; i<diffset.size(); i++) { 00282 diffs.Write(diffset[i].lineNum); 00283 for (unsigned int j=0; j<samps.size(); j++) { 00284 if (diffset[i].sampNum == samps[j]) { 00285 diffs.Write(diffset[i].cube1Val); 00286 diffs.Write(diffset[i].cube2Val); 00287 } 00288 else { 00289 diffs.Write(); 00290 diffs.Write(); 00291 } 00292 } 00293 } 00294 }