Isis 3.0 Application Source Code Reference |
Home |
00001 #include "Isis.h" 00002 00003 #include <cmath> 00004 00005 #include "ProcessByLine.h" 00006 #include "Pixel.h" 00007 #include "Camera.h" 00008 #include "iException.h" 00009 #include "Table.h" 00010 00011 using namespace std; 00012 using namespace Isis; 00013 00014 bool conv; 00015 double dcconst; 00016 bool useDcconst; 00017 double focalPlaneTemp; 00018 double exposureDuration; 00019 int offsetModeID; 00020 double gain; 00021 double avgFF; 00022 double cr; 00023 double dist; 00024 double C2; 00025 double correctedExposureDuration; 00026 00027 const double ACO = 1.062; 00028 const double BCO = -0.1153E-02; 00029 const double CCO = 0.6245E-05; 00030 const double DCO = -0.1216E-07; 00031 const double C3 = 7.13; 00032 const double C4 = -8.177; // Post-readout offset 00033 const double C5 = 15.56; 00034 const double DT = .00068; 00035 00036 void UvVisCal(std::vector< Isis::Buffer * > &in, std::vector< Isis::Buffer * > &out); 00037 void FixTemp(int); 00038 00039 void IsisMain() { 00040 // We will be processing by line 00041 ProcessByBrick p; 00042 UserInterface &ui = Application::GetUserInterface(); 00043 00044 // Use the def file for filter constants 00045 Pvl uvvisDef("$clementine1/calibration/uvvis/uvvis.def"); 00046 00047 // Setup the input and output cubes 00048 Cube *icube = p.SetInputCube("FROM"); 00049 00050 Cube *dccube; 00051 if(ui.WasEntered("DCFILE")) { 00052 dccube = p.SetInputCube("DCFILE"); 00053 } 00054 else { 00055 string dcfileloc = "$clementine1/calibration/uvvis/"; 00056 dcfileloc += "dark_5_15_96.cub"; 00057 CubeAttributeInput cubeAtt; 00058 dccube = p.SetInputCube(dcfileloc, cubeAtt); 00059 } 00060 00061 iString filter = (string)(icube->getGroup("BandBin"))["FilterName"]; 00062 filter = filter.DownCase(); 00063 00064 Cube *ffcube; 00065 if(ui.WasEntered("FFFILE")) { 00066 ffcube = p.SetInputCube("FFFILE"); 00067 } 00068 else { 00069 // compute default fffile 00070 double compressRatio = (icube->getGroup("Instrument"))["EncodingCompressionRatio"]; 00071 00072 // check to see if cube is compressed or uncompressed 00073 if(compressRatio == 1.0) { 00074 string fffileLoc = "$clementine1/calibration/uvvis/"; 00075 fffileLoc += "lu" + filter + "_uncomp_flat_long.cub"; 00076 CubeAttributeInput cubeAtt; 00077 ffcube = p.SetInputCube(fffileLoc, cubeAtt); 00078 } 00079 else { 00080 string fffileLoc = "$clementine1/calibration/uvvis/"; 00081 fffileLoc += "lu" + filter + "_comp_flat_long.cub"; 00082 CubeAttributeInput cubeAtt; 00083 ffcube = p.SetInputCube(fffileLoc, cubeAtt); 00084 } 00085 } 00086 00087 Cube *ocube = p.SetOutputCube("TO"); 00088 00089 avgFF = uvvisDef.FindGroup("Filter" + filter.UpCase())["AVGFF"]; 00090 cr = uvvisDef.FindGroup("Filter" + filter.UpCase())["CO"]; 00091 gain = uvvisDef.FindGroup(iString("GainModeID") + iString(icube->getGroup("Instrument")["GainModeID"][0]))["GAIN"]; 00092 00093 useDcconst = ui.WasEntered("DCCONST"); 00094 if(useDcconst) { 00095 dcconst = ui.GetDouble("DCCONST"); 00096 } 00097 else { 00098 dcconst = 0.0; 00099 } 00100 00101 conv = ui.GetBoolean("CONV"); 00102 exposureDuration = icube->getGroup("Instrument")["ExposureDuration"]; 00103 offsetModeID = icube->getGroup("Instrument")["OffsetModeID"]; 00104 00105 if(((string)icube->getGroup("Instrument")["FocalPlaneTemperature"]).compare("UNK") == 0) { 00106 //if FocalPlaneTemp is unknown set it to zero 00107 focalPlaneTemp = 0.0; 00108 } 00109 else { 00110 focalPlaneTemp = icube->getGroup("Instrument")["FocalPlaneTemperature"]; 00111 } 00112 00113 Camera *cam = icube->getCamera(); 00114 bool camSuccess = cam->SetImage(icube->getSampleCount() / 2, icube->getLineCount() / 2); 00115 00116 if(!camSuccess) { 00117 throw iException::Message(iException::Camera, "Unable to calculate the Solar Distance for this cube.", _FILEINFO_); 00118 } 00119 00120 dist = cam->SolarDistance(); 00121 00122 // If temp. correction set to true, or focal plane temp is zero then use temperature correction 00123 if(ui.GetBoolean("TCOR") || abs(focalPlaneTemp) <= DBL_EPSILON) { 00124 // Temperature correction requires the use of the mission phase 00125 // (PRELAUNCH, EARTH, LUNAR) and the product ID. 00126 string productID = (string)(icube->getGroup("Archive")["ProductID"]); 00127 char missionPhase = ((string)((icube->getGroup("Archive"))["MissionPhase"])).at(0); 00128 string n1substring(productID.substr(productID.find('.') + 1, productID.length() - 1)); 00129 string n2substring(productID.substr(4, productID.find('.') - 1)); 00130 int n1 = atoi(n1substring.c_str()); 00131 int n2 = atoi(n2substring.c_str()); 00132 int phase = 0; 00133 00134 if(missionPhase == 'L') { 00135 phase = 0; 00136 } 00137 else if(missionPhase == 'E') { 00138 phase = 1; 00139 } 00140 else if(missionPhase == 'P') { 00141 phase = 2; 00142 } 00143 else { 00144 throw iException::Message(iException::Pvl, "Invalid Mission Phase", _FILEINFO_); 00145 } 00146 00147 // This formula makes the primary search critera the original product ID's extension, 00148 // the secondary search criteria the mission phase and finally the numerical part of the 00149 // original product ID. 00150 int imageID = (100000 * n1) + (10000 * phase) + n2; 00151 FixTemp(imageID); 00152 } 00153 00154 if(focalPlaneTemp <= 0.0) { 00155 focalPlaneTemp = 272.5; 00156 } 00157 00158 // Start the processing 00159 p.SetBrickSize(icube->getSampleCount(), icube->getLineCount(), 1); 00160 p.StartProcess(UvVisCal); 00161 00162 // Add the radiometry group 00163 PvlGroup calgrp("Radiometry"); 00164 calgrp += PvlKeyword("FlatFieldFile", ffcube->getFilename()); 00165 00166 if(ui.GetString("DARKCURRENT").compare("DCFILE") == 0) { 00167 calgrp += PvlKeyword("DarkCurrentFile", dccube->getFilename()); 00168 } 00169 else { 00170 calgrp += PvlKeyword("DarkCurrentConstant", dcconst); 00171 } 00172 00173 calgrp += PvlKeyword("CorrectedFocalPlaneTemp", focalPlaneTemp); 00174 calgrp += PvlKeyword("C1", avgFF); 00175 calgrp += PvlKeyword("C2", C2); 00176 calgrp += PvlKeyword("C3", C3); 00177 calgrp += PvlKeyword("C4", C4); 00178 calgrp += PvlKeyword("C5", C5); 00179 calgrp += PvlKeyword("CR", cr); 00180 calgrp += PvlKeyword("FrameTransferTimePerRow", cr); 00181 calgrp += PvlKeyword("Gain", gain); 00182 calgrp += PvlKeyword("CorrectedExposureDuration", correctedExposureDuration); 00183 calgrp += PvlKeyword("ConvertToRadiance", conv); 00184 00185 calgrp += PvlKeyword("ACO", ACO); 00186 calgrp += PvlKeyword("BCO", BCO); 00187 calgrp += PvlKeyword("CCO", CCO); 00188 calgrp += PvlKeyword("DCO", DCO); 00189 00190 ocube->putGroup(calgrp); 00191 p.EndProcess(); 00192 } 00193 00194 void UvVisCal(std::vector< Isis::Buffer * > &in, std::vector< Isis::Buffer * > &out) { 00195 #define INPUT_CUBE (*in[0]) 00196 #define DC_CUBE (*in[1]) 00197 #define FF_CUBE (*in[2]) 00198 #define OUTPUT_CUBE (*out[0]) 00199 00200 C2 = 0.003737 * exp(0.0908 * (focalPlaneTemp - 273.15)); 00201 correctedExposureDuration = exposureDuration + 0.0494; 00202 00203 double dc = 0.0; 00204 bool valid = false; 00205 double *sum, *ro; 00206 00207 sum = new double[INPUT_CUBE.SampleDimension()]; 00208 ro = new double[INPUT_CUBE.SampleDimension()]; 00209 00210 for(int iSample = 0; iSample < INPUT_CUBE.SampleDimension(); iSample++) { 00211 ro[iSample] = 0.0; 00212 sum[iSample] = 0.0; 00213 00214 for(int iLine = 0; iLine < INPUT_CUBE.LineDimension(); iLine ++) { 00215 valid = false; 00216 int index = INPUT_CUBE.SampleDimension() * iLine + iSample; 00217 00218 if(Pixel::IsSpecial(INPUT_CUBE[index])) { 00219 OUTPUT_CUBE[index] = INPUT_CUBE[index]; 00220 00221 if(Pixel::IsHigh(INPUT_CUBE[index])) { 00222 sum[iSample] += 255; 00223 } 00224 } 00225 else { 00226 if(Pixel::IsSpecial(FF_CUBE[index])) { //check DCFILE 00227 OUTPUT_CUBE[index] = Isis::Null; 00228 sum[iSample] += INPUT_CUBE[index]; 00229 } 00230 else { 00231 valid = true; 00232 if(!useDcconst) { 00233 dc = DC_CUBE[index]; 00234 } 00235 else { 00236 dc = dcconst; 00237 } 00238 } 00239 } 00240 00241 if(valid) { 00242 //Global Offset Corrections 00243 double step1_dn = INPUT_CUBE[index] - (C4 * offsetModeID) - C5; 00244 //Gain Correction 00245 double step2_dn = step1_dn / gain; 00246 //Pixel dependent dark current correction 00247 double step3_dn = step2_dn - (dc + C3); 00248 //Non-linearity correction 00249 double xmul = ACO + (BCO * step3_dn) + (CCO * pow(step3_dn, 2)) + (DCO * pow(step3_dn, 3)); 00250 double corstep3_dn = step3_dn * xmul; 00251 //Tempurature-dependent offset correction 00252 double rotim = 60.05 + 0.05 * iLine; 00253 double u = correctedExposureDuration + rotim; 00254 double step4_dn = corstep3_dn - (C2 * u); 00255 OUTPUT_CUBE[index] = step4_dn; 00256 sum[iSample] += step4_dn; 00257 } 00258 } 00259 00260 ro[iSample] = sum[iSample] * DT / (correctedExposureDuration + (288.0 * DT)); 00261 } 00262 00263 for(int iLine = 0; iLine < INPUT_CUBE.LineDimension(); iLine ++) { 00264 for(int iSample = 0; iSample < INPUT_CUBE.SampleDimension(); iSample++) { 00265 valid = false; 00266 int index = INPUT_CUBE.SampleDimension() * iLine + iSample; 00267 if(!Pixel::IsSpecial(INPUT_CUBE[index])) { 00268 if(Pixel::IsSpecial(FF_CUBE[index])) { //check FFFILE 00269 OUTPUT_CUBE[index] = Isis::Null; 00270 } 00271 else { 00272 valid = true; 00273 } 00274 00275 if(valid) { 00276 // Frame transfer correction 00277 double step5_dn = OUTPUT_CUBE[index] - ro[iSample]; 00278 // Flat-field and exposure time normalization (Units=counts/ms) 00279 double step6_dn = step5_dn / (FF_CUBE[index] * correctedExposureDuration); 00280 // Normalize to sun-moon distance of 1AU 00281 double step7_dn = step6_dn * pow(dist, 2); 00282 // Conversion to radience (L=mW/sr-cm*cm) 00283 double L = step7_dn / avgFF; 00284 // Conversion to reflectance 00285 if(conv) { 00286 OUTPUT_CUBE[index] = step7_dn * cr; 00287 } 00288 else { 00289 OUTPUT_CUBE[index] = L; 00290 } 00291 } 00292 } 00293 } 00294 } 00295 00296 delete sum; 00297 delete ro; 00298 } 00299 00300 /* 00301 * In the ISIS2 Fortran we noticed FIXTEMP uses a REAL*4 to store the RIMGID. 00302 * This results in the last digit being lost precision. The table that 00303 * it looks in for data is also store as a REAL*4 again resulting 00304 * in a loss in precision. We believe this makes the lookup table inaccurate. 00305 */ 00306 void FixTemp(int imgID) { 00307 string table = "$clementine1/calibration/uvvis/uvvisTemperature.tbl"; 00308 Table t("FocalPlaneTemperatures", table); 00309 float currID = t[0]["ImageID"]; 00310 int currIndex = 0; 00311 00312 do { 00313 currID = t[currIndex]["ImageID"]; 00314 currIndex ++; 00315 } 00316 while((imgID > currID) && (currIndex < t.Records())); 00317 currIndex --; // Fixes an out-of-bounds segmentation fault 00318 00319 // Make sure currIndex makes sense 00320 if(currIndex < 0 || currIndex >= t.Records()) { 00321 focalPlaneTemp = 0; 00322 return; 00323 } 00324 00325 // Value too small - look up in the table and see if we're closer 00326 if(currID < imgID) { 00327 double diff = imgID - currID; 00328 if((currIndex + 1 < t.Records()) && abs((float)t[currIndex + 1]["ImageID"] - imgID) < diff) { 00329 currIndex ++; 00330 } 00331 } 00332 // Value too big - look down in the table and see if we're closer 00333 else if(currID > imgID) { 00334 double diff = currID - imgID; 00335 if(currIndex - 1 >= 0 && abs((float)t[currIndex - 1]["ImageID"] - imgID) < diff) { 00336 currIndex --; 00337 } 00338 } 00339 00340 focalPlaneTemp = (float)t[currIndex]["Temp"]; 00341 }