USGS

Isis 3.0 Application Source Code Reference

Home

lrowaccal.cpp

Go to the documentation of this file.
00001 #include "Isis.h"
00002 
00003 #include <vector>
00004 
00005 #include <QDir>
00006 
00007 #include "Brick.h"
00008 #include "Camera.h"
00009 #include "Constants.h"
00010 #include "Cube.h"
00011 #include "CubeAttribute.h"
00012 #include "ProcessByBrick.h"
00013 #include "SpecialPixel.h"
00014 #include "Statistics.h"
00015 #include "iTime.h"
00016 
00017 using namespace Isis;
00018 using namespace std;
00019 
00020 #define POLAR_MODE_SAMPLES 1024
00021 #define NO_POLAR_MODE_SAMPLES 704
00022 #define BW_BANDS 1
00023 #define VIS_LINES 14
00024 #define COLOR_BANDS 5
00025 #define UV_SAMPLES 128
00026 #define UV_LINES 4
00027 #define UV_BANDS 2
00028 #define KM_PER_AU 149597871
00029 
00030 void ResetGlobals ();
00031 void Calibrate ( Buffer &in, Buffer &out );
00032 void CopyCubeIntoBuffer ( string &fileString, Buffer* &data);
00033 double min ( double a, double b );
00034 
00035 void GetDark(string fileString, double temp, double time, Buffer* &data1, Buffer* &data2, double & temp1, double & temp2, string & file1, string & file2);
00036 void GetMask(string &fileString, double temp, Buffer* &data);
00037 
00038 vector<double> g_iofResponsivity;
00039 vector<double> g_radianceResponsivity;
00040 
00041 bool g_dark = true, g_flatfield = true, g_radiometric = true, g_iof = true, g_specpix = true;
00042 
00043 double g_exposure; // Exposure duration
00044 double g_solarDistance = 1.01; // average distance in [AU]
00045 double g_startTemperature, g_endTemperature;
00046 double g_temp1, g_temp2;
00047 
00048 int g_numFrames;
00049 
00050 vector<int> g_bands;
00051 
00052 Buffer *g_darkCube1, *g_darkCube2, *g_flatCube, *g_specpixCube;
00053 
00054 void IsisMain () {
00055   ResetGlobals();
00056   UserInterface &ui = Application::GetUserInterface();
00057 
00058   ProcessByBrick p;
00059   Cube *icube = p.SetInputCube("FROM");
00060 
00061   // Make sure it is a WAC cube
00062   Isis::PvlGroup &inst = icube->getLabel()->FindGroup("Instrument", Pvl::Traverse);
00063   iString instId = (string) inst["InstrumentId"];
00064   instId.UpCase();
00065   if (instId != "WAC-VIS" && instId != "WAC-UV") {
00066     string msg = "This program is intended for use on LROC WAC images only. [";
00067     msg += icube->getFilename() + "] does not appear to be a WAC image.";
00068     throw iException::Message(iException::User, msg, _FILEINFO_);
00069   }
00070 
00071   // And check if it has already run through calibration
00072   if (icube->getLabel()->FindObject("IsisCube").HasGroup("Radiometry")) {
00073     string msg = "This image has already been calibrated";
00074     throw iException::Message(iException::User, msg, _FILEINFO_);
00075   }
00076 
00077   if (icube->getLabel()->FindObject("IsisCube").HasGroup("AlphaCube")) {
00078     string msg = "This application can not be run on any image that has been geometrically transformed (i.e. scaled, rotated, sheared, or reflected) or cropped.";
00079     throw iException::Message(iException::User, msg, _FILEINFO_);
00080   }
00081 
00082   g_dark = ui.GetBoolean("DARK");
00083   g_flatfield = ui.GetBoolean("FLATFIELD");
00084   g_radiometric = ui.GetBoolean("RADIOMETRIC");
00085   g_iof = (ui.GetString("RADIOMETRICTYPE") == "IOF");
00086   g_specpix = ui.GetBoolean("SPECIALPIXELS");
00087 
00088   // Determine the dark/flat files to use
00089   iString offset = (string) inst["BackgroundOffset"];
00090   iString mode = (string) inst["Mode"];
00091   iString instModeId = (string) inst["InstrumentModeId"];
00092   instModeId.UpCase();
00093 
00094   if (instModeId == "COLOR" && (string) inst["InstrumentId"] == "WAC-UV")
00095     instModeId = "UV";
00096   else if (instModeId == "VIS")
00097     instModeId = "COLOR";
00098 
00099   g_startTemperature = (double) inst["BeginTemperatureFpa"];
00100   g_endTemperature = (double) inst["EndTemperatureFpa"];
00101 
00102   g_numFrames = (int) inst["NumFramelets"];
00103 
00104   vector<string> darkFiles;
00105   ui.GetAsString("DARKFILE", darkFiles);
00106   iString flatFile = ui.GetAsString("FLATFIELDFILE");
00107   iString radFile = ui.GetAsString("RADIOMETRICFILE");
00108   iString specpixFile = ui.GetAsString("SPECIALPIXELSFILE");
00109 
00110   // Figure out which bands are input
00111   for (int i = 1; i <= icube->getBandCount(); i++) {
00112     g_bands.push_back(icube->getPhysicalBand(i));
00113   }
00114 
00115   Isis::PvlGroup &bandBin = icube->getLabel()->FindGroup("BandBin", Pvl::Traverse);
00116   iString filter = (string) bandBin["Center"][0];
00117 
00118   if (g_dark) {
00119     if (darkFiles.size() == 0 || darkFiles[0] =="Default" || darkFiles[0].length() == 0) {
00120       darkFiles.resize(2);
00121       double temp = (double) inst["MiddleTemperatureFpa"];
00122       double time = iTime(inst["StartTime"][0]).Et();
00123       string darkFile = "$lro/calibration/wac_darks/WAC_" + instModeId;
00124       if (instModeId == "BW")
00125         darkFile += "_" + filter + "_Mode" + mode;
00126       darkFile += "_Offset" + offset + "_*C_*T_Dark.????.cub";
00127       GetDark (darkFile, temp, time, g_darkCube1, g_darkCube2, g_temp1, g_temp2, darkFiles[0], darkFiles[1]);
00128     }
00129     else if (darkFiles.size() == 1) {
00130       CopyCubeIntoBuffer(darkFiles[0], g_darkCube1);
00131       g_temp1 = 0.0;
00132       g_darkCube2 = new Buffer(*g_darkCube1);
00133       g_temp2 = g_temp1;
00134     }
00135     else {
00136       CopyCubeIntoBuffer(darkFiles[0], g_darkCube1);
00137       int index = darkFiles[0].find_last_of("_");
00138       g_temp1 = iString(darkFiles[0].substr( darkFiles[0].find_last_of("_", index-1), index)).ToDouble();
00139       CopyCubeIntoBuffer(darkFiles[1], g_darkCube2);
00140       index = darkFiles[1].find_last_of("_");
00141       g_temp2 = iString(darkFiles[1].substr( darkFiles[1].find_last_of("_", index-1), index)).ToDouble();
00142     }
00143   }
00144 
00145   if (g_flatfield) {
00146     if (flatFile.Equal("Default") || flatFile.length() == 0) {
00147       flatFile = "$lro/calibration/wac_flats/WAC_" + instModeId;
00148       if (instModeId == "BW")
00149         flatFile += "_" + filter + "_Mode" + mode;
00150       flatFile += "_Flatfield.????.cub";
00151     }
00152     CopyCubeIntoBuffer(flatFile, g_flatCube);
00153   }
00154 
00155   PvlKeyword responsivity;
00156 
00157   if (g_radiometric) {
00158 
00159     Isis::PvlKeyword &bands = icube->getLabel()->FindGroup("BandBin", Pvl::Traverse).FindKeyword("FilterNumber");
00160 
00161     if (radFile.Equal("Default") || radFile.length() == 0)
00162       radFile = "$lro/calibration/WAC_RadiometricResponsivity.????.pvl";
00163 
00164     Filename radFilename(radFile);
00165     if ((radFilename.Expanded()).find("?") != string::npos)
00166       radFilename.HighestVersion();
00167     if (!radFilename.Exists()) {
00168       string msg = radFile + " does not exist.";
00169       throw iException::Message(iException::User, msg, _FILEINFO_);
00170     }
00171 
00172     Pvl radPvl(radFilename.Expanded());
00173 
00174     if (g_iof) {
00175       responsivity = radPvl["IOF"];
00176 
00177       for (int i = 0; i < bands.Size(); i++)
00178         g_iofResponsivity.push_back(responsivity[(int)bands[i] - 1]);
00179 
00180       try {
00181         iTime startTime((string) inst["StartTime"]);
00182         double etStart = startTime.Et();
00183         // Get the distance between the Moon and the Sun at the given time in
00184         // Astronomical Units (AU)
00185         string bspKernel1 = p.MissionData("lro", "/kernels/tspk/moon_pa_de421_1900-2050.bpc", false);
00186         string bspKernel2 = p.MissionData("lro", "/kernels/tspk/de421.bsp", false);
00187         furnsh_c(bspKernel1.c_str());
00188         furnsh_c(bspKernel2.c_str());
00189         string pckKernel1 = p.MissionData("base", "/kernels/pck/pck?????.tpc", true);
00190         string pckKernel2 = p.MissionData("lro", "/kernels/pck/moon_080317.tf", false);
00191         string pckKernel3 = p.MissionData("lro", "/kernels/pck/moon_assoc_me.tf", false);
00192         furnsh_c(pckKernel1.c_str());
00193         furnsh_c(pckKernel2.c_str());
00194         furnsh_c(pckKernel3.c_str());
00195         double sunpos[6], lt;
00196         spkezr_c("sun", etStart, "MOON_ME", "LT+S", "MOON", sunpos, &lt);
00197         g_solarDistance = vnorm_c(sunpos) / KM_PER_AU;
00198         unload_c(bspKernel1.c_str());
00199         unload_c(bspKernel2.c_str());
00200         unload_c(pckKernel1.c_str());
00201         unload_c(pckKernel2.c_str());
00202         unload_c(pckKernel3.c_str());
00203       }
00204       catch (iException &e) {
00205         string msg = "Can not find necessary SPICE kernels for converting to IOF";
00206         throw iException::Message(iException::User, msg, _FILEINFO_);
00207       }
00208     }
00209     else {
00210       responsivity = radPvl["Radiance"];
00211       for (int i = 0; i < bands.Size(); i++)
00212         g_radianceResponsivity.push_back(responsivity[(int)bands[i] - 1]);
00213     }
00214   }
00215 
00216   if (g_specpix) {
00217     if (specpixFile.Equal("Default") || specpixFile.length() == 0) {
00218       specpixFile = "$lro/calibration/wac_masks/WAC_" + instModeId;
00219       double temp = (double) inst["MiddleTemperatureFpa"];
00220       if (instModeId == "BW")
00221         specpixFile += "_" + filter + "_Mode" + mode;
00222       specpixFile += "_*C_SpecialPixels.????.cub";
00223       GetMask(specpixFile, temp, g_specpixCube);
00224     }
00225     else
00226       CopyCubeIntoBuffer(specpixFile, g_specpixCube);
00227   }
00228 
00229   if (instModeId == "BW") {
00230     if (mode == "1" || mode == "0")
00231       p.SetBrickSize(NO_POLAR_MODE_SAMPLES, VIS_LINES, (int)min(BW_BANDS, g_bands.size()));
00232     else
00233       p.SetBrickSize(POLAR_MODE_SAMPLES, VIS_LINES, (int)min(BW_BANDS, g_bands.size()));
00234   }
00235   else if (instModeId == "COLOR") {
00236     p.SetBrickSize(NO_POLAR_MODE_SAMPLES, VIS_LINES, (int)min(COLOR_BANDS, g_bands.size()));
00237   }
00238   else if (instModeId == "UV") {
00239     p.SetBrickSize(UV_SAMPLES, UV_LINES, (int)min(UV_BANDS, g_bands.size()));
00240   }
00241 
00242   g_exposure = inst["ExposureDuration"];
00243 
00244   Cube *ocube = p.SetOutputCube("TO");
00245   p.StartProcess(Calibrate);
00246 
00247   // Add an output group with the appropriate information
00248   PvlGroup calgrp("Radiometry");
00249   if (g_dark) {
00250     PvlKeyword darks("DarkFiles");
00251     darks.AddValue(darkFiles[0]);
00252     if (darkFiles.size() > 1)
00253       darks.AddValue(darkFiles[1]);
00254     calgrp += darks;
00255   }
00256   if (g_flatfield)
00257     calgrp += PvlKeyword("FlatFile", flatFile);
00258   if (g_radiometric) {
00259     PvlKeyword vals("ResponsivityValues");
00260     if (g_iof) {
00261       calgrp += PvlKeyword("RadiometricType", "IOF");
00262       for (unsigned int i=0; i< g_iofResponsivity.size(); i++)
00263         vals.AddValue(g_iofResponsivity[i]);
00264     }
00265     else {
00266       calgrp += PvlKeyword("RadiometricType", "AbsoluteRadiance");
00267       for (unsigned int i=0; i< g_radianceResponsivity.size(); i++)
00268         vals.AddValue(g_radianceResponsivity[i]);
00269     }
00270     calgrp += vals;
00271     calgrp += PvlKeyword("SolarDistance", g_solarDistance);
00272   }
00273   if (g_specpix)
00274     calgrp += PvlKeyword("SpecialPixelsFile", specpixFile);
00275   ocube->putGroup(calgrp);
00276 
00277   p.EndProcess();
00278 }
00279 
00280 void ResetGlobals () {
00281   g_iofResponsivity.clear();
00282   g_radianceResponsivity.clear();
00283 
00284   g_dark = true;
00285   g_flatfield = true;
00286   g_radiometric = true;
00287   g_iof = true;
00288   g_specpix = true;
00289 
00290   g_bands.clear();
00291 
00292   g_exposure = 1.0; // Exposure duration
00293   g_solarDistance = 1.01; // average distance in [AU]
00294 
00295   g_temp1 = 0.0;
00296   g_temp2 = 0.0;
00297 
00298   g_numFrames = 0;
00299 
00300   delete g_darkCube1;
00301   delete g_darkCube2;
00302   delete g_flatCube;
00303   delete g_specpixCube;
00304 }
00305 
00306 // Calibrate each framelet
00307 void Calibrate ( Buffer &inCube, Buffer &outCube ) {
00308   int frameHeight = inCube.LineDimension();
00309   int frameSize = inCube.SampleDimension()*inCube.LineDimension();
00310   int frame = inCube.Line() / frameHeight;
00311 
00312   for (int i = 0; i < outCube.size(); i++)
00313     outCube[i] = inCube[i];
00314 
00315   if (g_dark) {
00316     for ( int b=0; b<inCube.BandDimension(); b++) {
00317       // We find the index of the corresponding dark frame band as the offset
00318       int offset = g_darkCube1->Index(1, frameHeight * (int) min(frame, g_darkCube1->LineDimension()/frameHeight - 1) + 1, b+1);
00319 
00320       for (int i = 0; i < frameSize; i++) {
00321         // Calculate the temperature for the current frame
00322         double temp = (g_endTemperature - g_startTemperature)/g_numFrames * frame + g_startTemperature;
00323 
00324         // Interpolate between the two darks with the current temperaturube1
00325         if (IsSpecial(g_darkCube1->at(offset + i)) || IsSpecial(g_darkCube2->at(offset + i)) || IsSpecial(outCube[i + b*frameSize]))
00326           outCube[i + b*frameSize] = Isis::Null;
00327         else {
00328           if (g_temp1 != g_temp2)
00329             outCube[i + b*frameSize] -= (g_darkCube1->at(offset + i) - g_darkCube2->at(offset + i))/(g_temp1-g_temp2) * (temp - g_temp2) + g_darkCube2->at(offset + i);
00330           else
00331             outCube[i+b*frameSize] -= g_darkCube1->at(offset + i);
00332         }
00333       }
00334     }
00335   }
00336 
00337   if (g_flatfield) {
00338     for ( int b=0; b<inCube.BandDimension(); b++) {
00339       // We find the index of the corresponding flat frame band as the offset
00340       int offset = g_flatCube->Index(1, frameHeight * (int) min(frame, (g_flatCube->LineDimension()-1) / frameHeight)+1, b+1);
00341 
00342       for (int i = 0; i < frameSize; i++) {
00343         if (g_flatCube->at(offset + i) <= 0 || IsSpecial(g_flatCube->at(offset + i)) || IsSpecial(outCube[i + b*frameSize]))
00344           outCube[i+b*frameSize] = Isis::Null;
00345         else
00346           outCube[i+b*frameSize] /= g_flatCube->at(offset + i);
00347       }
00348     }
00349   }
00350 
00351   if (g_radiometric) {
00352     for (int i = 0; i < outCube.size(); i++) {
00353       if (IsSpecial(outCube[i]))
00354         outCube[i] = Isis::Null;
00355       else {
00356         outCube[i] /= g_exposure;
00357         if (g_iof)
00358           outCube[i] *= pow(g_solarDistance, 2) / g_iofResponsivity[outCube.Band(i) - 1];
00359         else
00360           outCube[i] /= g_radianceResponsivity[outCube.Band(i) - 1];
00361       }
00362     }
00363   }
00364 
00365   if (g_specpix) {
00366     for ( int b=0; b<inCube.BandDimension(); b++) {
00367       // We find the index of the corresponding flat frame band as the offset
00368       int offset = g_specpixCube->Index(1, frameHeight * (int) min(frame, (g_specpixCube->LineDimension()-1) / frameHeight)+1, b+1);
00369 
00370       for (int i = 0; i < frameSize; i++) {
00371         if (IsSpecial(g_specpixCube->at(offset + i)))
00372           outCube[i+b*frameSize] = g_specpixCube->at(offset + i);
00373       }
00374     }
00375   }
00376 }
00377 
00378 void CopyCubeIntoBuffer ( string &fileString, Buffer* &data) {
00379   Cube cube;
00380   Filename filename(fileString);
00381   if ((filename.Expanded()).find("?") != string::npos)
00382     filename.HighestVersion();
00383   if (!filename.Exists()) {
00384     string msg = fileString + " does not exist.";
00385     throw iException::Message(iException::User, msg, _FILEINFO_);
00386   }
00387   cube.open(filename.Expanded());
00388   Brick brick(cube.getSampleCount(), cube.getLineCount(), cube.getBandCount(), cube.getPixelType());
00389   brick.SetBasePosition(1, 1, 1);
00390   cube.read(brick);
00391 
00392   data = new Buffer(brick);
00393 
00394   fileString = filename.Expanded();
00395 }
00396 
00397 double min ( double a, double b ) {
00398   if (a < b)
00399     return a;
00400   return b;
00401 }
00402 
00403 void GetDark(string fileString, double temp, double time, Buffer* &data1, Buffer* &data2, double & temp1, double & temp2, string & file1, string & file2) {
00404   // Find the beginning and end of the "?"s in the versioned filename
00405   Filename filename(fileString);
00406   string absolutePath = filename.Expanded();
00407   string basename = Filename(filename.Basename()).Basename(); // We do it twice to remove the ".????.cub"
00408 
00409   unsigned int tempIndex = basename.find("*C");
00410   vector<double> temperatures;
00411 
00412   unsigned int timeIndex = basename.find("*T");
00413   vector<int> times;
00414 
00415   QDir dir( (QString)(iString)(absolutePath.substr(0, absolutePath.find_last_of("/"))) );
00416 
00417   // Loop through all files in the dir and see if they match our name
00418   for (unsigned int indx=0; indx < dir.count(); indx++) {
00419     string file = Filename( Filename(dir[indx].toStdString()).Basename()).Basename(); // We do it twice to remove ".????.cub
00420 
00421     size_t fileTempEndIndex = file.find("C", tempIndex);
00422     size_t fileTimeEndIndex = file.find("T", fileTempEndIndex+1);
00423     size_t fileTimeIndex = file.find_last_not_of("0123456789", fileTimeEndIndex-1) + 1;
00424     if (fileTempEndIndex == string::npos || fileTimeEndIndex == string::npos || fileTimeIndex == string::npos)
00425       continue;
00426 
00427     bool matches = file.substr(0, tempIndex) == basename.substr(0,tempIndex);
00428     matches = matches && ( file.substr(fileTempEndIndex, fileTimeIndex-fileTempEndIndex) == basename.substr(tempIndex+1, timeIndex-tempIndex-1) );
00429     matches = matches && ( file.substr(fileTimeEndIndex) == basename.substr(timeIndex+1) );
00430 
00431     if (matches) {
00432       // Extract all available temperatures
00433       Isis::iString tempStr = file.substr(tempIndex, fileTempEndIndex - tempIndex);
00434 
00435       if ((tempStr.length() > 0) &&
00436           (tempStr.find_first_not_of("0123456789.-") == string::npos)) {
00437         // Make sure it isn't already included, otherwise add it
00438         bool add = true;
00439         for (unsigned int j=0; j<temperatures.size(); j++)
00440           if (temperatures[j] == tempStr.ToDouble())
00441             add = false;
00442         if (add)
00443           temperatures.push_back( tempStr.ToDouble());
00444       }
00445 
00446       // Extract all available times
00447       Isis::iString timeStr = file.substr(fileTimeIndex, fileTimeEndIndex - fileTimeIndex);
00448       if ((timeStr.length() > 0) &&
00449           (timeStr.find_first_not_of("0123456789.-") == string::npos)) {
00450         // Make sure it isn't already included, otherwise add it
00451         bool add = true;
00452         for (unsigned int j=0; j<times.size(); j++)
00453           if (times[j] == timeStr.ToDouble())
00454             add = false;
00455         if (add)
00456           times.push_back( timeStr.ToInteger());
00457       }
00458     }
00459 
00460   }
00461 
00462   // Now that we have all the available temperatures, we need to find the nearest two temperatures and interpolate (or extrapolate) between them
00463   if (temperatures.size() == 0) {
00464     string msg = "No Dark files exist for these image options [" + basename + "]";
00465     throw iException::Message(iException::User, msg, _FILEINFO_);
00466   }
00467   else if ( temperatures.size() > 2) {
00468     if (abs(temp - temperatures[0]) < abs(temp - temperatures[1])){
00469       temp1 = temperatures[0];
00470       temp2 = temperatures[1];
00471     }
00472     else {
00473       temp1 = temperatures[1];
00474       temp2 = temperatures[0];
00475     }
00476     for (unsigned int i=2; i<temperatures.size(); i++){
00477       if (abs(temp - temperatures[i]) < abs(temp - temp1)) {
00478         temp2 = temp1;
00479         temp1 = temperatures[i];
00480       }
00481       else if (abs(temp - temperatures[i]) < abs(temp - temp2)) {
00482         temp2 = temperatures[i];
00483       }
00484     }
00485   }
00486   else {
00487     temp1=temperatures[0];
00488     temp2=temp1;
00489   }
00490 
00491   tempIndex = fileString.find("*C");
00492   timeIndex = fileString.find("*T");
00493   // And then find the latest available time
00494   int bestTime = -1;
00495   for (unsigned int i=0; i<times.size(); i++) {
00496     try {
00497       Filename f1(fileString.substr(0, tempIndex) + iString((int)temp1) + fileString.substr(tempIndex+1, timeIndex-tempIndex-1) + iString(times[i]) + fileString.substr(timeIndex+1));
00498       Filename f2(fileString.substr(0, tempIndex) + iString((int)temp2) + fileString.substr(tempIndex+1, timeIndex-tempIndex-1) + iString(times[i]) + fileString.substr(timeIndex+1));
00499 
00500 
00501       f1.HighestVersion();
00502       f2.HighestVersion();
00503 
00504       if ( f1.Exists() && f2.Exists() && abs(times[i] - time) < abs(bestTime - time))
00505         bestTime = times[i];
00506     }
00507     catch ( Isis::iException e) {
00508       // We ignore exceptions as we expect them every time there is not a file with the given temperature and time
00509       e.Clear(); 
00510     }
00511   }
00512 
00513   if (bestTime == -1) {
00514     string msg = "No Dark files exist for these image options [" + basename + "]\n no matching times";
00515     throw iException::Message(iException::User, msg, _FILEINFO_);
00516   }
00517 
00518   file1 = fileString.substr(0, tempIndex) + iString((int)temp1) + fileString.substr(tempIndex+1, timeIndex-tempIndex-1) + iString(bestTime) + fileString.substr(timeIndex+1);
00519   file2 = fileString.substr(0, tempIndex) + iString((int)temp2) + fileString.substr(tempIndex+1, timeIndex-tempIndex-1) + iString(bestTime) + fileString.substr(timeIndex+1);
00520 
00521   CopyCubeIntoBuffer ( file1, data1 );
00522   CopyCubeIntoBuffer ( file2, data2 );
00523 }
00524 
00525 void GetMask(string &fileString, double temp, Buffer* &data) {
00526   // Find the beginning and end of the "?"s in the versioned filename
00527   Filename filename(fileString);
00528   string absolutePath = filename.Expanded();
00529   string basename = Filename(filename.Basename()).Basename(); // We do it twice to remove the ".????.cub"
00530 
00531   unsigned int index = basename.find_first_of("*");
00532   unsigned int charsAfterVersion = basename.length() - index - 1;
00533 
00534   vector<double> temperatures;
00535 
00536   QDir dir( (QString)(iString)(absolutePath.substr(0, absolutePath.find_last_of("/"))) );
00537 
00538   // Loop through all files in the dir and see if they match our name
00539   for (unsigned int indx=0; indx < dir.count(); indx++) {
00540 
00541     string file = Filename( Filename(dir[indx].toStdString()).Basename()).Basename(); // We do it twice to remove ".????.cub"
00542     bool leftSide = file.substr(0, index) == basename.substr(0, index);
00543     bool rightSide = ((int)file.length()-(int)charsAfterVersion) >= 0;
00544     if (rightSide) {
00545       rightSide = rightSide &&
00546         (file.substr(file.length()-charsAfterVersion) == basename.substr(index+1));
00547     }
00548 
00549     if (leftSide && rightSide) {
00550 
00551       Isis::iString version = file.substr(index, file.length()-charsAfterVersion-index);
00552 
00553       if ((version.length() > 0) &&
00554           (version.find_first_not_of("0123456789.-") == string::npos)) {
00555         // Make sure it isn't already included, otherwise add it
00556         bool add = true;
00557         for (unsigned int j=0; j<temperatures.size(); j++)
00558           if (temperatures[j] == version.ToDouble())
00559             add = false;
00560         if (add)
00561           temperatures.push_back( version.ToDouble());
00562       }
00563     }
00564   }
00565 
00566   // Now that we have all the available temperatures, we need to find the nearest temperature
00567   if (temperatures.size() == 0) {
00568     string msg = "No Dark files exist for these image options [" + basename + "]";
00569     throw iException::Message(iException::User, msg, _FILEINFO_);
00570   }
00571 
00572   double bestTemp = temperatures[0];
00573   for (unsigned int i=1; i< temperatures.size(); i++) {
00574     if (abs(temp - temperatures[i]) < abs(temp - bestTemp)) 
00575       bestTemp = temperatures[i];
00576   }
00577   index = fileString.find_first_of("*");
00578 
00579   string file = fileString.substr(0, index) + iString((int)bestTemp) + fileString.substr(index+1);
00580   CopyCubeIntoBuffer ( file, data );
00581   fileString = file;
00582 }
00583