/** * @brief Initializes the object by computing all calibration statistics * * This method validates the input file, reads labels for needed values * and computes calibration statistics for data reduction. * * @param [in] (CubeInfo &) cube Opened cube where label and ancillary data * is read from */ void HiImageClean::init(Cube &cube) { _lines = cube.Lines(); _samples = cube.Samples(); _lastGoodLine = _lines - 1; _totalMaskNulled = _totalDarkNulled = 0; PvlGroup &instrument = cube.GetGroup("Instrument"); // It may be too late and a non-issue by this time, but should check to ensure // this is a valid HiRISE image iString instId = (std::string) instrument["InstrumentId"]; if (instId.UpCase() != "HIRISE") { string message = "Image must be a HiRISE image (InstrumentId != HIRISE)"; iException::Message(iException::User, message, _FILEINFO_); } // Extract what is needed _binning = instrument["Summing"]; _tdi = instrument["Tdi"]; _cpmm = instrument["CpmmNumber"]; _channelNo = instrument["ChannelNumber"]; // Initialize all HiRISE calibration blobs _calimg = blobvert(HiCalibrationImage(cube)); _calbuf = blobvert(HiCalibrationBuffer(cube)); _caldark = blobvert(HiCalibrationDark(cube)); _ancbuf = blobvert(HiAncillaryBuffer(cube)); _ancdark = blobvert(HiAncillaryDark(cube)); // Compute statistics from blobs computeStats(); return; }
void IsisMain() { // We will be processing by line ProcessByLine p; // Setup the input and output cubes Cube *icube = p.SetInputCube("FROM"); p.SetOutputCube ("TO"); // Get exposure duration and tranfer time // Override the lable values if the user entered a value double expTime,xferTime; UserInterface &ui = Application::GetUserInterface(); if (ui.WasEntered ("DURATION")) { expTime = ui.GetDouble ("DURATION"); } else { PvlGroup grp = icube->GetGroup("ISIS_INSTRUMENT"); expTime = grp["EXPOSURE_DURATION"]; } if (ui.WasEntered ("TRANSFER")) { xferTime = ui.GetDouble ("TRANSFER"); } else { PvlGroup grp = icube->GetGroup("ISIS_INSTRUMENT"); xferTime = grp["TRANSFER_TIME"]; } // Calculate the smear scale smearScale = xferTime / expTime / icube->Lines(); // Start the processing p.StartProcess(desmear); p.EndProcess(); }
void IsisMain() { // We will be processing by brick ProcessByBrick p; Isis::Cube *amatrixCube=NULL; Isis::Cube *bmatrixCube=NULL; // Setup the user input for the input/output files and the option UserInterface &ui = Application::GetUserInterface(); // Setup the input HiRise cube Isis::Cube *icube = p.SetInputCube("FROM"); if (icube->Bands() != 1) { std::string msg = "Only single-band HiRise cubes can be calibrated"; throw Isis::iException::Message(Isis::iException::Io,msg,_FILEINFO_); } //Get pertinent label information to determine which band of matrix cube to use HiLab hilab(icube); int ccd = hilab.getCcd(); int channel = hilab.getChannel(); if (channel != 0 && channel != 1) { std::string msg = "Only unstitched cubes can be calibrated"; throw Isis::iException::Message(Isis::iException::Io,msg,_FILEINFO_); } int band = 1 + ccd*2 + channel; string option = ui.GetString("OPTION"); // Set attributes (input band number) for the matrix cube(s); CubeAttributeInput att("+" + iString(band)); // Determine the file specification to the matrix file(s) if defaulted // and open if (ui.WasEntered ("MATRIX") ) { if (option == "GAIN") { string matrixFile = ui.GetFilename("MATRIX"); amatrixCube = p.SetInputCube(matrixFile, att); } else if (option == "OFFSET") { string matrixFile = ui.GetFilename("MATRIX"); bmatrixCube = p.SetInputCube(matrixFile, att); } else { //(option == "BOTH") std::string msg = "The BOTH option cannot be used if a MATRIX is entered"; throw Isis::iException::Message(Isis::iException::Io,msg,_FILEINFO_); } } else { int tdi = hilab.getTdi(); int bin = hilab.getBin(); if (option == "OFFSET" || option == "BOTH") { std::string bmatrixFile = "$mro/calibration"; bmatrixFile += "/B_matrix_tdi"; bmatrixFile += iString(tdi) + "_bin" + iString(bin); bmatrixCube = p.SetInputCube(bmatrixFile, att); } if (option == "GAIN" || option == "BOTH") { std::string amatrixFile = "$mro/calibration"; amatrixFile += "/A_matrix_tdi"; amatrixFile += iString(tdi) + "_bin" + iString(bin); amatrixCube = p.SetInputCube(amatrixFile, att); } } // Open the output file and set processing parameters Cube *ocube = p.SetOutputCube ("TO"); p.SetWrap (true); p.SetBrickSize ( icube->Samples(), 1, 1); // Add the radiometry group if it is not there yet. Otherwise // read the current value of the keyword CalibrationParameters. // Then delete the keyword and rewrite it after appending the // new value to it. Do it this way to avoid multiple Calibration // Parameter keywords. PvlGroup calgrp; PvlKeyword calKey; if (ocube->HasGroup("Radiometry")) { calgrp = ocube->GetGroup ("Radiometry"); if (calgrp.HasKeyword("CalibrationParameters")) { calKey = calgrp.FindKeyword("CalibrationParameters"); calgrp.DeleteKeyword( "CalibrationParameters" ); } else { calKey.SetName ("CalibrationParameters"); } } else { calgrp.SetName("Radiometry"); calKey.SetName ("CalibrationParameters"); } string keyValue = option; if (option == "GAIN") { keyValue += ":" + amatrixCube->Filename(); } else if (option == "OFFSET") { keyValue += ":" + bmatrixCube->Filename(); } else { // "BOTH" keyValue += ":"+bmatrixCube->Filename()+":"+amatrixCube->Filename(); } calKey += keyValue; calgrp += calKey; ocube->PutGroup(calgrp); // Start the processing based on the option if (option == "GAIN") { p.StartProcess(mult); } else if (option == "OFFSET") { p.StartProcess(sub); } else { //(option == "BOTH") p.StartProcess(multSub); } // Cleanup p.EndProcess(); }
// Main program void IsisMain(){ // Create an object for exporting Isis data ProcessExport p; // Open the input cube Cube *icube = p.SetInputCube("FROM"); // Conform to the Big-Endian format for FITS if(IsLsb()) p.SetOutputEndian(Isis::Msb); // Generate the name of the fits file and open it UserInterface &ui = Application::GetUserInterface(); // specify the bits per pixel string bitpix; if (ui.GetString ("BITTYPE") == "8BIT") bitpix = "8"; else if (ui.GetString ("BITTYPE") == "16BIT") bitpix = "16"; else if (ui.GetString ("BITTYPE") == "32BIT") bitpix = "-32"; else { string msg = "Pixel type of [" + ui.GetString("BITTYPE") + "] is unsupported"; throw iException::Message(iException::User, msg, _FILEINFO_); } // Determine bit size and calculate number of bytes to write // for each line. if (bitpix == "8") p.SetOutputType(Isis::UnsignedByte); if (bitpix == "16") p.SetOutputType(Isis::SignedWord); if (bitpix == "-32") p.SetOutputType(Isis::Real); // determine core base and multiplier, set up the stretch PvlGroup pix = icube->Label()->FindObject("IsisCube").FindObject("Core").FindGroup("Pixels"); double scale = pix["Multiplier"][0].ToDouble(); double base = pix["Base"][0].ToDouble(); if (ui.GetString("STRETCH") != "NONE" && bitpix != "-32") { if (ui.GetString("STRETCH") == "LINEAR") { p.SetInputRange(); } else if (ui.GetString("STRETCH") == "MANUAL") { p.SetInputRange(ui.GetDouble("MINIMUM"), ui.GetDouble("MAXIMUM")); } // create a proper scale so pixels look like 32bit data. scale = ((p.GetInputMaximum() - p.GetInputMinimum()) * (p.GetOutputMaximum() - p.GetOutputMinimum())); // round off after 14 decimals to avoid system architecture differences scale = ((floor(scale * 1e14)) / 1e14); // create a proper zero point so pixels look like 32bit data. base = -1.0 * (scale * p.GetOutputMinimum()) + p.GetInputMinimum(); // round off after 14 decimals to avoid system architecture differences base = ((floor(base * 1e14)) / 1e14); } ////////////////////////////////////////// // Write the minimal fits header // ////////////////////////////////////////// string header; // specify that this file conforms to simple fits standard header += FitsKeyword("SIMPLE", true, "T"); // specify the bits per pixel header += FitsKeyword("BITPIX", true, bitpix); // specify the number of data axes (2: samples by lines) int axes = 2; if (icube->Bands() > 1) { axes = 3; } header += FitsKeyword("NAXIS", true, iString(axes)); // specify the limit on data axis 1 (number of samples) header += FitsKeyword("NAXIS1", true, iString(icube->Samples())); // specify the limit on data axis 2 (number of lines) header += FitsKeyword("NAXIS2", true, iString(icube->Lines())); if (axes == 3){ header += FitsKeyword("NAXIS3", true, iString(icube->Bands())); } header += FitsKeyword("BZERO", true, base); header += FitsKeyword("BSCALE", true, scale); // Sky and All cases if (ui.GetString("INFO") == "SKY" || ui.GetString("INFO") == "ALL") { iString msg = "cube has not been skymapped"; PvlGroup map; if (icube->HasGroup("mapping")) { map = icube->GetGroup("mapping"); msg = (string)map["targetname"]; } // If we have sky we want it if (msg == "Sky") { double midRa = 0, midDec = 0; midRa = ((double)map["MaximumLongitude"] + (double)map["MinimumLongitude"])/2; midDec = ((double)map["MaximumLatitude"] + (double)map["MinimumLatitude"])/2; header += FitsKeyword("OBJCTRA", true, iString(midRa)); // Specify the Declination header += FitsKeyword("OBJCTDEC", true, iString(midDec)); } if (ui.GetString("INFO") == "ALL") { header += WritePvl("INSTRUME","Instrument","InstrumentId", icube, true); header += WritePvl("OBSERVER","Instrument","SpacecraftName", icube, true); header += WritePvl("OBJECT ","Instrument","TargetName", icube, true); // StartTime is sometimes middle of the exposure and somtimes beginning, // so StopTime can't be calculated off of exposure reliably. header += WritePvl("DATE-OBS","Instrument","StartTime", icube, true); // Some cameras don't have StopTime if (icube->HasGroup("Instrument")) { PvlGroup inst = icube->GetGroup("Instrument"); if (inst.HasKeyword("StopTime")) { header += WritePvl("TIME_END","Instrument","StopTime", icube, true); } if (inst.HasKeyword("ExposureDuration")) { header += WritePvl("EXPTIME","Instrument","ExposureDuration", icube, false); } } } // If we were set on SKY and Sky doesn't exist else if (msg != "Sky") { throw iException::Message(iException::User,msg,_FILEINFO_); } } // signal the end of the header header += FitsKeyword("END", false, ""); // fill the rest of the fits header with space so to conform with the fits header // size of 2880 bytes for (int i = header.length() % 2880 ; i < 2880 ; i++) header += " "; // open the cube for writing string to = ui.GetFilename("TO","fits"); ofstream fout; fout.open (to.c_str (), ios::out|ios::binary); if (!fout.is_open ()) { string msg = "Cannot open fits output file"; throw iException::Message(iException::Programmer,msg,_FILEINFO_); } fout.seekp(0); fout.write(header.c_str(),header.length()); // write the raw cube data p.StartProcess (fout); // Finish off data area to a number n % 2880 == 0 is true // 2880 is the size of the data blocks int count = 2880 - (fout.tellp() % 2880); for (int i = 0; i < count; i++) { // Write nul characters as needed. ascii 0, hex 00... fout.write("\0", 1); } fout.close(); p.EndProcess(); }
void IsisMain(){ const std::string hical_program = "hicalbeta"; const std::string hical_version = "3.5"; const std::string hical_revision = "$Revision: 1.14 $"; const std::string hical_runtime = Application::DateTime(); UserInterface &ui = Application::GetUserInterface(); string procStep("prepping phase"); try { // The output from the last processing is the input into subsequent processing ProcessByLine p; Cube *hifrom = p.SetInputCube("FROM"); int nsamps = hifrom->Samples(); int nlines = hifrom->Lines(); // Initialize the configuration file string conf(ui.GetAsString("CONF")); HiCalConf hiconf(*(hifrom->Label()), conf); DbProfile hiprof = hiconf.getMatrixProfile(); // Check for label propagation and set the output cube Cube *ocube = p.SetOutputCube("TO"); if ( !IsTrueValue(hiprof,"PropagateTables", "TRUE") ) { RemoveHiBlobs(*(ocube->Label())); } // Set specified profile if entered by user if (ui.WasEntered("PROFILE")) { hiconf.selectProfile(ui.GetAsString("PROFILE")); } // Add OPATH parameter to profiles if (ui.WasEntered("OPATH")) { hiconf.add("OPATH",ui.GetAsString("OPATH")); } else { // Set default to output directory hiconf.add("OPATH", Filename(ocube->Filename()).Path()); } // Do I/F output DN conversions string units = ui.GetString("UNITS"); // Allocate the calibration list calVars = new MatrixList; // Set up access to HiRISE ancillary data (tables, blobs) here. Note it they // are gone, this will error out. See PropagateTables in conf file. HiCalData caldata(*hifrom); //////////////////////////////////////////////////////////////////////////// // FixGaps (Z_f) Get buffer pixels and compute coefficients for equation // y = a[0] + a[1]*x + a[2] * exp(a[3] * x) // where y is the average of the buffer pixel region, // and x is the time at each line in electrons/sec/pixel procStep = "Zf module"; hiconf.selectProfile("Zf"); hiprof = hiconf.getMatrixProfile(); HiHistory ZfHist; ZfHist.add("Profile["+ hiprof.Name()+"]"); if ( !SkipModule(hiprof) ) { DriftBuffer driftB(caldata, hiconf); calVars->add("Zf", driftB.ref()); ZfHist = driftB.History(); if ( hiprof.exists("DumpModuleFile") ) { driftB.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof)); } } else { // NOT RECOMMENDED! This is required for the next step! // SURELY must be skipped with Z_d step as well! calVars->add("Zf", HiVector(nlines, 0.0)); ZfHist.add("Debug::SkipModule invoked!"); } ///////////////////////////////////////////////////////////////////// // DriftCorrect (Z_d) // Now compute the equation of fit // procStep = "Zd module"; HiHistory ZdHist; hiconf.selectProfile("Zd"); hiprof = hiconf.getMatrixProfile(); ZdHist.add("Profile["+ hiprof.Name()+"]"); if (!SkipModule(hiconf.getMatrixProfile("Zd")) ) { DriftCorrect driftC(hiconf); calVars->add("Zd", driftC.Normalize(driftC.Solve(calVars->get("Zf")))); ZdHist = driftC.History(); if ( hiprof.exists("DumpModuleFile") ) { driftC.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof)); } } else { calVars->add("Zd", HiVector(nlines, 0.0)); ZdHist.add("Debug::SkipModule invoked!"); } //////////////////////////////////////////////////////////////////// // ZeroCorrect (Z_z) Get reverse clock procStep = "Zz module"; hiconf.selectProfile("Zz"); hiprof = hiconf.getMatrixProfile(); HiHistory ZzHist; ZzHist.add("Profile["+ hiprof.Name()+"]"); if ( !SkipModule(hiprof) ) { OffsetCorrect zoff(caldata, hiconf); calVars->add("Zz", zoff.ref()); ZzHist = zoff.History(); if ( hiprof.exists("DumpModuleFile") ) { zoff.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof)); } } else { calVars->add("Zz", HiVector(nsamps, 0.0)); ZzHist.add("Debug::SkipModule invoked!"); } ///////////////////////////////////////////////////////////////// // DarkSubtract (Z_b) Remove dark current // procStep = "Zb module"; hiconf.selectProfile("Zb"); hiprof = hiconf.getMatrixProfile(); HiHistory ZbHist; ZbHist.add("Profile["+ hiprof.Name()+"]"); if ( !SkipModule(hiprof) ) { DarkSubtractComp dark(hiconf); calVars->add("Zb", dark.ref()); ZbHist = dark.History(); if ( hiprof.exists("DumpModuleFile") ) { dark.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof)); } } else { calVars->add("Zb", HiVector(nsamps, 0.0)); ZbHist.add("Debug::SkipModule invoked!"); } //////////////////////////////////////////////////////////////////// // GainVLineCorrect (Z_g) Correct for gain-based drift // procStep = "Zg module"; hiconf.selectProfile("Zg"); hiprof = hiconf.getMatrixProfile(); HiHistory ZgHist; ZgHist.add("Profile["+ hiprof.Name()+"]"); if ( !SkipModule(hiprof) ) { GainVLineComp gainV(hiconf); calVars->add("Zg", gainV.ref()); ZgHist = gainV.History(); if ( hiprof.exists("DumpModuleFile") ) { gainV.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof)); } } else { calVars->add("Zg", HiVector(nlines, 1.0)); ZgHist.add("Debug::SkipModule invoked!"); } //////////////////////////////////////////////////////////////////// // GainCorrect (Z_gg) Correct for gain with the G matrix procStep = "Zgg module"; hiconf.selectProfile("Zgg"); hiprof = hiconf.getMatrixProfile(); HiHistory ZggHist; ZggHist.add("Profile["+ hiprof.Name()+"]"); if ( !SkipModule(hiprof) ) { double bin = ToDouble(hiprof("Summing")); double tdi = ToDouble(hiprof("Tdi")); double factor = 128.0 / tdi / (bin*bin); HiVector zgg = hiconf.getMatrix("G", hiprof); for ( int i = 0 ; i < zgg.dim() ; i++ ) { zgg[i] *= factor; } calVars->add("Zgg", zgg);; ZggHist.add("LoadMatrix(G[" + hiconf.getMatrixSource("G",hiprof) + "],Band[" + ToString(hiconf.getMatrixBand(hiprof)) + "],Factor[" + ToString(factor) + "])"); if ( hiprof.exists("DumpModuleFile") ) { Component zg("GMatrix", ZggHist); zg.Process(zgg); zg.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof)); } } else { calVars->add("Zgg", HiVector(nsamps, 1.0)); ZggHist.add("Debug::SkipModule invoked!"); } //////////////////////////////////////////////////////////////////// // FlatField (Z_a) Flat field correction with A matrix procStep = "Za module"; hiconf.selectProfile("Za"); hiprof = hiconf.getMatrixProfile(); HiHistory ZaHist; ZaHist.add("Profile["+ hiprof.Name()+"]"); if ( !SkipModule(hiprof) ) { FlatFieldComp flat(hiconf); calVars->add("Za", flat.ref()); ZaHist = flat.History(); if ( hiprof.exists("DumpModuleFile") ) { flat.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof)); } } else { calVars->add("Za", HiVector(nsamps, 1.0)); ZaHist.add("Debug::SkipModule invoked!"); } //////////////////////////////////////////////////////////////////// // FlatField (Z_t) Temperature-dependant gain correction procStep = "Zt module"; hiconf.selectProfile("Zt"); hiprof = hiconf.getMatrixProfile(); HiHistory ZtHist; ZtHist.add("Profile["+ hiprof.Name()+"]"); if ( !SkipModule(hiprof) ) { TempGainCorrect tcorr(hiconf); calVars->add("Zt", tcorr.ref()); ZtHist = tcorr.History(); if ( hiprof.exists("DumpModuleFile") ) { tcorr.Dump(hiconf.getMatrixSource("DumpModuleFile",hiprof)); } } else { calVars->add("Zt", HiVector(nsamps, 1.0)); ZtHist.add("Debug::SkipModule invoked!"); } //////////////////////////////////////////////////////////////////// // I/FCorrect (Z_iof) Conversion to I/F // procStep = "Ziof module"; hiconf.selectProfile("Ziof"); hiprof = hiconf.getMatrixProfile(); HiHistory ZiofHist; ZiofHist.add("Profile["+ hiprof.Name()+"]"); if ( !SkipModule(hiprof) ) { double sed = ToDouble(hiprof("ScanExposureDuration")); // units = us if ( IsEqual(units, "IOF") ) { // Add solar I/F correction parameters double au = hiconf.sunDistanceAU(); ZiofHist.add("SunDist[" + ToString(au) + " (AU)]"); double suncorr = 1.5 / au; suncorr *= suncorr; double zbin = ToDouble(hiprof("ZiofBinFactor")); ZiofHist.add("ZiofBinFactor[" + ToString(zbin) + "]"); double zgain = ToDouble(hiprof("FilterGainCorrection")); ZiofHist.add("FilterGainCorrection[" + ToString(zgain) + "]"); ZiofHist.add("ScanExposureDuration[" + ToString(sed) + "]"); double ziof = (zbin * zgain) * (sed * 1.0e-6) * suncorr; calVars->add("Ziof", HiVector(1, ziof)); ZiofHist.add("I/F_Factor[" + ToString(ziof) + "]"); ZiofHist.add("Units[I/F Reflectance]"); } else if ( IsEqual(units, "DN/US") ) { // Ziof is a divisor in calibration equation double ziof = sed; calVars->add("Ziof", HiVector(1, ziof)); ZiofHist.add("ScanExposureDuration[" + ToString(sed) + "]"); ZiofHist.add("DN/US_Factor[" + ToString(ziof) + "]"); ZiofHist.add("Units[DNs/microsecond]"); } else { // Units are already in DN double ziof = 1.0; calVars->add("Ziof", HiVector(1, ziof)); ZiofHist.add("DN_Factor[" + ToString(ziof) + "]"); ZiofHist.add("Units[DN]"); } } else { calVars->add("Ziof", HiVector(1,1.0)); ZiofHist.add("Debug::SkipModule invoked!"); ZiofHist.add("Units[Unknown]"); } // Reset the profile selection to default hiconf.selectProfile(); //---------------------------------------------------------------------- // ///////////////////////////////////////////////////////////////////////// // Call the processing function procStep = "calibration phase"; p.StartProcess(calibrate); // Get the default profile for logging purposes hiprof = hiconf.getMatrixProfile(); const std::string conf_file = hiconf.filepath(conf); // Quitely dumps parameter history to alternative format file. This // is completely controlled by the configuration file if ( hiprof.exists("DumpHistoryFile") ) { procStep = "logging/reporting phase"; Filename hdump(hiconf.getMatrixSource("DumpHistoryFile",hiprof)); string hdumpFile = hdump.Expanded(); ofstream ofile(hdumpFile.c_str(), ios::out); if (!ofile) { string mess = "Unable to open/create history dump file " + hdump.Expanded(); iException::Message(iException::User, mess, _FILEINFO_).Report(); } else { ofile << "Program: " << hical_program << endl; ofile << "RunTime: " << hical_runtime << endl; ofile << "Version: " << hical_version << endl; ofile << "Revision: " << hical_revision << endl << endl; ofile << "FROM: " << hifrom->Filename() << endl; ofile << "TO: " << ocube->Filename() << endl; ofile << "CONF: " << conf_file << endl << endl; ofile << "/* " << hical_program << " application equation */" << endl << "/* hdn = (idn - Zd(Zf) - Zz - Zb) */" << endl << "/* odn = hdn / Zg * Zgg * Za * Zt / Ziof */" << endl << endl; ofile << "****** PARAMETER GENERATION HISTORY *******" << endl; ofile << "\nZf = " << ZfHist << endl; ofile << "\nZd = " << ZdHist << endl; ofile << "\nZz = " << ZzHist << endl; ofile << "\nZb = " << ZbHist << endl; ofile << "\nZg = " << ZgHist << endl; ofile << "\nZgg = " << ZggHist << endl; ofile << "\nZa = " << ZaHist << endl; ofile << "\nZt = " << ZtHist << endl; ofile << "\nZiof = " << ZiofHist << endl; ofile.close(); } } // Ensure the RadiometricCalibration group is out there const std::string rcalGroup("RadiometricCalibration"); if (!ocube->HasGroup(rcalGroup)) { PvlGroup temp(rcalGroup); ocube->PutGroup(temp); } PvlGroup &rcal = ocube->GetGroup(rcalGroup); rcal += PvlKeyword("Program", hical_program); rcal += PvlKeyword("RunTime", hical_runtime); rcal += PvlKeyword("Version",hical_version); rcal += PvlKeyword("Revision",hical_revision); PvlKeyword key("Conf", conf_file); key.AddCommentWrapped("/* " + hical_program + " application equation */"); key.AddComment("/* hdn = (idn - Zd(Zf) - Zz - Zb) */"); key.AddComment("/* odn = hdn / Zg * Zgg * Za * Zt / Ziof */"); rcal += key; // Record parameter generation history. Controllable in configuration // file. Note this is optional because of a BUG!! in the ISIS label // writer as this application was initially developed if ( IsEqual(ConfKey(hiprof,"LogParameterHistory",string("TRUE")),"TRUE")) { rcal += ZfHist.makekey("Zf"); rcal += ZdHist.makekey("Zd"); rcal += ZzHist.makekey("Zz"); rcal += ZbHist.makekey("Zb"); rcal += ZgHist.makekey("Zg"); rcal += ZggHist.makekey("Zgg"); rcal += ZaHist.makekey("Za"); rcal += ZiofHist.makekey("Ziof"); } p.EndProcess(); } catch (iException &ie) { delete calVars; calVars = 0; string mess = "Failed in " + procStep; ie.Message(iException::User, mess.c_str(), _FILEINFO_); throw; } // Clean up parameters delete calVars; calVars = 0; }
void IsisMain () { stretch.ClearPairs(); for (int i=0; i<6; i++) { gapCount[i] = 0; suspectGapCount[i] = 0; invalidCount[i] = 0; lisCount[i] = 0; hisCount[i] = 0; validCount[i] = 0; } void TranslateHiriseEdrLabels (Filename &labelFile, Cube *); void SaveHiriseCalibrationData (ProcessImportPds &process, Cube *, Pvl &pdsLabel); void SaveHiriseAncillaryData (ProcessImportPds &process, Cube *); void FixDns8 (Buffer &buf); void FixDns16 (Buffer &buf); ProcessImportPds p; Pvl pdsLabel; UserInterface &ui = Application::GetUserInterface(); // Get the input filename and make sure it is a HiRISE EDR Filename inFile = ui.GetFilename("FROM"); iString id; bool projected; try { Pvl lab(inFile.Expanded()); id = (string) lab.FindKeyword ("DATA_SET_ID"); projected = lab.HasObject("IMAGE_MAP_PROJECTION"); } catch (iException &e) { string msg = "Unable to read [DATA_SET_ID] from input file [" + inFile.Expanded() + "]"; throw iException::Message(iException::Io,msg, _FILEINFO_); } //Checks if in file is rdr if( projected ) { string msg = "[" + inFile.Name() + "] appears to be an rdr file."; msg += " Use pds2isis."; throw iException::Message(iException::User,msg, _FILEINFO_); } id.ConvertWhiteSpace(); id.Compress(); id.Trim(" "); if (id != "MRO-M-HIRISE-2-EDR-V1.0") { string msg = "Input file [" + inFile.Expanded() + "] does not appear to be " + "in HiRISE EDR format. DATA_SET_ID is [" + id + "]"; throw iException::Message(iException::Io,msg, _FILEINFO_); } p.SetPdsFile (inFile.Expanded(), "", pdsLabel); // Make sure the data we need for the BLOBs is saved by the Process p.SaveFileHeader(); p.SaveDataPrefix(); p.SaveDataSuffix(); // Let the Process create the output file but override any commandline // output bit type and min/max. It has to be 16bit for the rest of hi2isis // to run. // Setting the min/max to the 16 bit min/max keeps all the dns (including // the 8 bit special pixels from changing their value when they are mapped // to the 16 bit output. CubeAttributeOutput &outAtt = ui.GetOutputAttribute("TO"); outAtt.PixelType (Isis::SignedWord); outAtt.Minimum((double)VALID_MIN2); outAtt.Maximum((double)VALID_MAX2); Cube *ocube = p.SetOutputCube(ui.GetFilename("TO"), outAtt); p.StartProcess (); TranslateHiriseEdrLabels (inFile, ocube); // Pull out the lookup table so we can apply it in the second pass // and remove it from the labels. // Add the UNLUTTED keyword to the instrument group so we know // if the lut has been used to convert back to 14 bit data PvlGroup &instgrp = ocube->GetGroup("Instrument"); PvlKeyword lutKey = instgrp["LookupTable"]; PvlSequence lutSeq; lutSeq = lutKey; // Set up the Stretch object with the info from the lookup table // If the first entry is (0,0) then no lut was applied. if ((lutKey.IsNull()) || (lutSeq.Size()==1 && lutSeq[0][0]=="0" && lutSeq[0][1]=="0")) { stretch.AddPair(0.0, 0.0); stretch.AddPair(65536.0, 65536.0); instgrp.AddKeyword(PvlKeyword("Unlutted","TRUE")); instgrp.DeleteKeyword ("LookupTable"); } // The user wants it unlutted else if (ui.GetBoolean("UNLUT")) { for (int i=0; i<lutSeq.Size(); i++) { stretch.AddPair(i, (((double)lutSeq[i][0] + (double)lutSeq[i][1]) / 2.0)); } instgrp.AddKeyword(PvlKeyword("Unlutted","TRUE")); instgrp.DeleteKeyword ("LookupTable"); } // The user does not want the data unlutted else { stretch.AddPair(0.0, 0.0); stretch.AddPair(65536.0, 65536.0); instgrp.AddKeyword(PvlKeyword("Unlutted","FALSE")); } ocube->PutGroup(instgrp); // Save the calibration and ancillary data as BLOBs. Both get run thru the // lookup table just like the image data. SaveHiriseCalibrationData (p, ocube, pdsLabel); SaveHiriseAncillaryData (p, ocube); // Save off the input bit type so we know how to process it on the // second pass below. Isis::PixelType inType = p.PixelType(); // All finished with the ImportPds object p.EndProcess (); // Make another pass thru the data using the output file in read/write mode // This allows us to correct gaps, remap special pixels and accumulate some // counts lsbGap = ui.GetBoolean("LSBGAP"); ProcessByLine p2; string ioFile = ui.GetFilename("TO"); CubeAttributeInput att; p2.SetInputCube(ioFile, att, ReadWrite); p2.Progress()->SetText("Converting special pixels"); section = 4; p2.StartProcess((inType == Isis::UnsignedByte) ? FixDns8 : FixDns16); p2.EndProcess(); // Log the results of the image conversion PvlGroup results("Results"); results += PvlKeyword ("From", inFile.Expanded()); results += PvlKeyword ("CalibrationBufferGaps", gapCount[0]); results += PvlKeyword ("CalibrationBufferLIS", lisCount[0]); results += PvlKeyword ("CalibrationBufferHIS", hisCount[0]); results += PvlKeyword ("CalibrationBufferPossibleGaps", suspectGapCount[0]); results += PvlKeyword ("CalibrationBufferInvalid", invalidCount[0]); results += PvlKeyword ("CalibrationBufferValid", validCount[0]); results += PvlKeyword ("CalibrationImageGaps", gapCount[1]); results += PvlKeyword ("CalibrationImageLIS", lisCount[1]); results += PvlKeyword ("CalibrationImageHIS", hisCount[1]); results += PvlKeyword ("CalibrationImagePossibleGaps", suspectGapCount[1]); results += PvlKeyword ("CalibrationImageInvalid", invalidCount[1]); results += PvlKeyword ("CalibrationImageValid", validCount[1]); results += PvlKeyword ("CalibrationDarkGaps", gapCount[2]); results += PvlKeyword ("CalibrationDarkLIS", lisCount[2]); results += PvlKeyword ("CalibrationDarkHIS", hisCount[2]); results += PvlKeyword ("CalibrationDarkPossibleGaps", suspectGapCount[2]); results += PvlKeyword ("CalibrationDarkInvalid", invalidCount[2]); results += PvlKeyword ("CalibrationDarkValid", validCount[2]); results += PvlKeyword ("ObservationBufferGaps", gapCount[3]); results += PvlKeyword ("ObservationBufferLIS", lisCount[3]); results += PvlKeyword ("ObservationBufferHIS", hisCount[3]); results += PvlKeyword ("ObservationBufferPossibleGaps", suspectGapCount[3]); results += PvlKeyword ("ObservationBufferInvalid", invalidCount[3]); results += PvlKeyword ("ObservationBufferValid", validCount[3]); results += PvlKeyword ("ObservationImageGaps", gapCount[4]); results += PvlKeyword ("ObservationImageLIS", lisCount[4]); results += PvlKeyword ("ObservationImageHIS", hisCount[4]); results += PvlKeyword ("ObservationImagePossibleGaps", suspectGapCount[4]); results += PvlKeyword ("ObservationImageInvalid", invalidCount[4]); results += PvlKeyword ("ObservationImageValid", validCount[4]); results += PvlKeyword ("ObservationDarkGaps", gapCount[5]); results += PvlKeyword ("ObservationDarkLIS", lisCount[5]); results += PvlKeyword ("ObservationDarkHIS", hisCount[5]); results += PvlKeyword ("ObservationDarkPossibleGaps", suspectGapCount[5]); results += PvlKeyword ("ObservationDarkInvalid", invalidCount[5]); results += PvlKeyword ("ObservationDarkValid", validCount[5]); // Write the results to the log Application::Log(results); return; }
void IsisMain(){ UserInterface &ui = Application::GetUserInterface(); ProcessByLine proc; Cube *cube = proc.SetInputCube("FROM"); BigInt npixels(cube->Lines() * cube->Samples()); // Initialize the cleaner routine try { delete iclean; iclean = new HiImageClean(*cube); } catch (iException &ie) { std::string message = "Error attempting to initialize HiRISE cleaner object"; throw (iException::Message(iException::Programmer,message,_FILEINFO_)); } catch (...) { std::string message = "Unknown error occured attempting to initialize " "HiRISE cleaner object"; throw (iException::Message(iException::Programmer,message,_FILEINFO_)); } // For IR10, channel 1 lets restrict the last 3100 lines of dark current PvlGroup &instrument = cube->GetGroup("Instrument"); std::string ccd = (std::string) instrument["CcdId"]; int channel = instrument["ChannelNumber"]; if ((ccd == "IR10") && (channel == 1)) { int bin = instrument["Summing"]; int lastLine = cube->Lines() - ((3100/bin) + iclean->getFilterWidth()/2); if (lastLine > 1) { iclean->setLastGoodLine(lastLine); } } #if defined(DEBUG) std::cout << "Lines: " << cube->Lines() << " GoodLines: " << iclean->getLastGoodLine() << std::endl; #endif // Get the output file reference for label update Cube *ocube = proc.SetOutputCube("TO"); proc.StartProcess(cleanImage); iclean->propagateBlobs(ocube); proc.EndProcess(); // Write statistics to file if requested if (ui.WasEntered("CLEANSTATS")) { std::string darkfile = ui.GetFilename("CLEANSTATS"); std::ofstream dfile; dfile.open(darkfile.c_str(), std::ios::out | std::ios::trunc); dfile << *iclean; dfile.close(); } // Dump stats to standard out Pvl p; PvlGroup grp; iclean->PvlImageStats(grp); p.AddGroup(grp); Application::Log(grp); BigInt nNulled = iclean->TotalNulled(); delete iclean; iclean = 0; // Check for calibration problems if (nNulled != 0) { double tpixels((double) nNulled / (double) npixels); std::ostringstream mess; mess << "There were " << nNulled << " of " << npixels << " (" << std::setw(6) << std::setprecision(2) << (tpixels * 100.0) << "%) due to insufficient calibration data (LUTTED or Gaps)" << std::ends; throw (iException::Message(iException::Math,mess.str(),_FILEINFO_)); } }
void IsisMain () { UserInterface &ui = Application::GetUserInterface(); Filename inFile = ui.GetFilename("FROM"); // Set the processing object ProcessExportMiniRFLroPds cProcess; // Setup the input cube Cube *cInCube = cProcess.SetInputCube("FROM"); Pvl * cInLabel = cInCube->Label(); // Get the output label file Filename outFile(ui.GetFilename("TO", "lbl")); string outFilename(outFile.Expanded()); cProcess.SetDetached (true, outFilename); cProcess.SetExportType ( ProcessExportPds::Fixed ); //Set the resolution to Kilometers cProcess.SetPdsResolution( ProcessExportPds::Kilometer ); // 32bit cProcess.SetOutputType(Isis::Real); cProcess.SetOutputNull(Isis::NULL4); cProcess.SetOutputLrs(Isis::LOW_REPR_SAT4); cProcess.SetOutputLis(Isis::LOW_INSTR_SAT4); cProcess.SetOutputHrs(Isis::HIGH_REPR_SAT4); cProcess.SetOutputHis(Isis::HIGH_INSTR_SAT4); cProcess.SetOutputRange(-DBL_MAX, DBL_MAX); cProcess.SetOutputEndian(Isis::Msb); // Turn off Keywords cProcess.ForceScalingFactor(false); cProcess.ForceSampleBitMask(false); cProcess.ForceCoreNull (false); cProcess.ForceCoreLrs (false); cProcess.ForceCoreLis (false); cProcess.ForceCoreHrs (false); cProcess.ForceCoreHis (false); // Standard label Translation Pvl &pdsLabel = cProcess.StandardPdsLabel( ProcessExportPds::Image); // bLevel => Level 2 = True, Level 3 = False bool bLevel2 = cInCube->HasGroup("Instrument"); // Translate the keywords from the original EDR PDS label that go in // this RDR PDS label for Level2 images only if (bLevel2) { OriginalLabel cOriginalBlob; cInCube->Read(cOriginalBlob); Pvl cOrigLabel; PvlObject cOrigLabelObj = cOriginalBlob.ReturnLabels(); cOrigLabelObj.SetName("OriginalLabelObject"); cOrigLabel.AddObject(cOrigLabelObj); // Translates the ISIS labels along with the original EDR labels cOrigLabel.AddObject( *(cInCube->Label()) ); PvlTranslationManager cCubeLabel2(cOrigLabel, "$lro/translations/mrfExportOrigLabel.trn"); cCubeLabel2.Auto(pdsLabel); if (cInLabel->FindObject("IsisCube").FindGroup("Instrument").HasKeyword("MissionName")) { PvlKeyword & cKeyMissionName = cInLabel->FindObject("IsisCube").FindGroup("Instrument").FindKeyword("MissionName"); size_t sFound = cKeyMissionName[0].find("CHANDRAYAAN"); if (sFound != string::npos ) { cCubeLabel2 = PvlTranslationManager(cOrigLabel, "$lro/translations/mrfExportOrigLabelCH1.trn"); cCubeLabel2.Auto(pdsLabel); } else { cCubeLabel2 = PvlTranslationManager(cOrigLabel, "$lro/translations/mrfExportOrigLabelLRO.trn"); cCubeLabel2.Auto(pdsLabel); } } } else { //Level3 - add Band_Name keyword PvlGroup & cBandBinGrp = cInCube->GetGroup("BandBin"); PvlKeyword cKeyBandBin = PvlKeyword("BAND_NAME"); PvlKeyword cKeyInBandBin; if (cBandBinGrp.HasKeyword("OriginalBand")){ cKeyInBandBin = cBandBinGrp.FindKeyword("OriginalBand"); } else if (cBandBinGrp.HasKeyword("FilterName")){ cKeyInBandBin = cBandBinGrp.FindKeyword("FilterName"); } for (int i=0; i<cKeyInBandBin.Size(); i++) { cKeyBandBin += cKeyInBandBin[i]; } PvlObject &cImageObject( pdsLabel.FindObject("IMAGE") ); cImageObject += cKeyBandBin; } // Get the Sources Product ID if entered for Level2 only as per example if (ui.WasEntered("SRC") && bLevel2) { std::string sSrcFile = ui.GetFilename("SRC"); std::string sSrcType = ui.GetString("TYPE"); GetSourceProductID(sSrcFile, sSrcType, pdsLabel); } // Get the User defined Labels if (ui.WasEntered("USERLBL")) { std::string sUserLbl = ui.GetFilename("USERLBL"); GetUserLabel(sUserLbl, pdsLabel, bLevel2); } // Calculate CheckSum Statistics * cStats = cInCube->Statistics(); iCheckSum = (unsigned int )cStats->Sum(); FixLabel(pdsLabel, bLevel2); // Add an output format template to the PDS PVL // Distinguish betweeen Level 2 and 3 images by calling the camera() // function as only non mosaic images(Level2) have a camera if (bLevel2) { pdsLabel.SetFormatTemplate ("$lro/translations/mrfPdsLevel2.pft"); } else { pdsLabel.SetFormatTemplate ("$lro/translations/mrfPdsLevel3.pft"); } size_t iFound = outFilename.find(".lbl"); outFilename.replace(iFound, 4, ".img"); ofstream oCube(outFilename.c_str()); cProcess.OutputDetatchedLabel(); //cProcess.OutputLabel(oCube); cProcess.StartProcess(oCube); oCube.close(); cProcess.EndProcess(); }
void IsisMain() { // We will be warping a cube ProcessRubberSheet p; // Get the map projection file provided by the user UserInterface &ui = Application::GetUserInterface(); Pvl userPvl(ui.GetFilename("MAP")); PvlGroup &userMappingGrp = userPvl.FindGroup("Mapping",Pvl::Traverse); // Open the input cube and get the projection Cube *icube = p.SetInputCube ("FROM"); // Get the mapping group PvlGroup fromMappingGrp = icube->GetGroup("Mapping"); Projection *inproj = icube->Projection(); PvlGroup outMappingGrp = fromMappingGrp; // If the default range is FROM, then wipe out any range data in user mapping file if(ui.GetString("DEFAULTRANGE").compare("FROM") == 0 && !ui.GetBoolean("MATCHMAP")) { if(userMappingGrp.HasKeyword("MinimumLatitude")) { userMappingGrp.DeleteKeyword("MinimumLatitude"); } if(userMappingGrp.HasKeyword("MaximumLatitude")) { userMappingGrp.DeleteKeyword("MaximumLatitude"); } if(userMappingGrp.HasKeyword("MinimumLongitude")) { userMappingGrp.DeleteKeyword("MinimumLongitude"); } if(userMappingGrp.HasKeyword("MaximumLongitude")) { userMappingGrp.DeleteKeyword("MaximumLongitude"); } } // Deal with user overrides entered in the GUI. Do this by changing the user's mapping group, which // will then overlay anything in the output mapping group. if(ui.WasEntered("MINLAT") && !ui.GetBoolean("MATCHMAP")) { userMappingGrp.AddKeyword( PvlKeyword("MinimumLatitude", ui.GetDouble("MINLAT")), Pvl::Replace ); } if(ui.WasEntered("MAXLAT") && !ui.GetBoolean("MATCHMAP")) { userMappingGrp.AddKeyword( PvlKeyword("MaximumLatitude", ui.GetDouble("MAXLAT")), Pvl::Replace ); } if(ui.WasEntered("MINLON") && !ui.GetBoolean("MATCHMAP")) { userMappingGrp.AddKeyword( PvlKeyword("MinimumLongitude", ui.GetDouble("MINLON")), Pvl::Replace ); } if(ui.WasEntered("MAXLON") && !ui.GetBoolean("MATCHMAP")) { userMappingGrp.AddKeyword( PvlKeyword("MaximumLongitude", ui.GetDouble("MAXLON")), Pvl::Replace ); } /** * If the user is changing from positive east to positive west, or vice-versa, the output minimum is really * the input maximum. However, the user mapping group must be left unaffected (an input minimum must be the * output minimum). To accomplish this, we swap the minimums/maximums in the output group ahead of time. This * causes the minimums and maximums to correlate to the output minimums and maximums. That way when we copy * the user mapping group into the output group a mimimum overrides a minimum and a maximum overrides a maximum. */ bool sameDirection = true; if(userMappingGrp.HasKeyword("LongitudeDirection")) { if(((string)userMappingGrp["LongitudeDirection"]).compare(fromMappingGrp["LongitudeDirection"]) != 0) { sameDirection = false; } } // Since the out mapping group came from the from mapping group, which came from a valid cube, // we can assume both min/max lon exists if min longitude exists. if(!sameDirection && outMappingGrp.HasKeyword("MinimumLongitude")) { double minLon = outMappingGrp["MinimumLongitude"]; double maxLon = outMappingGrp["MaximumLongitude"]; outMappingGrp["MaximumLongitude"] = minLon; outMappingGrp["MinimumLongitude"] = maxLon; } if(ui.GetString("PIXRES").compare("FROM") == 0 && !ui.GetBoolean("MATCHMAP")) { // Resolution will be in fromMappingGrp and outMappingGrp at this time // delete from user mapping grp if(userMappingGrp.HasKeyword("Scale")) { userMappingGrp.DeleteKeyword("Scale"); } if(userMappingGrp.HasKeyword("PixelResolution")) { userMappingGrp.DeleteKeyword("PixelResolution"); } } else if(ui.GetString("PIXRES").compare("MAP") == 0 || ui.GetBoolean("MATCHMAP")) { // Resolution will be in userMappingGrp - delete all others if(outMappingGrp.HasKeyword("Scale")) { outMappingGrp.DeleteKeyword("Scale"); } if(outMappingGrp.HasKeyword("PixelResolution")) { outMappingGrp.DeleteKeyword("PixelResolution"); } if(fromMappingGrp.HasKeyword("Scale")); { fromMappingGrp.DeleteKeyword("Scale"); } if(fromMappingGrp.HasKeyword("PixelResolution")) { fromMappingGrp.DeleteKeyword("PixelResolution"); } } else if(ui.GetString("PIXRES").compare("MPP") == 0) { // Resolution specified - delete all and add to outMappingGrp if(outMappingGrp.HasKeyword("Scale")) { outMappingGrp.DeleteKeyword("Scale"); } if(outMappingGrp.HasKeyword("PixelResolution")) { outMappingGrp.DeleteKeyword("PixelResolution"); } if(fromMappingGrp.HasKeyword("Scale")) { fromMappingGrp.DeleteKeyword("Scale"); } if(fromMappingGrp.HasKeyword("PixelResolution")) { fromMappingGrp.DeleteKeyword("PixelResolution"); } if(userMappingGrp.HasKeyword("Scale")) { userMappingGrp.DeleteKeyword("Scale"); } if(userMappingGrp.HasKeyword("PixelResolution")) { userMappingGrp.DeleteKeyword("PixelResolution"); } outMappingGrp.AddKeyword(PvlKeyword("PixelResolution", ui.GetDouble("RESOLUTION"), "meters/pixel"), Pvl::Replace); } else if(ui.GetString("PIXRES").compare("PPD") == 0) { // Resolution specified - delete all and add to outMappingGrp if(outMappingGrp.HasKeyword("Scale")) { outMappingGrp.DeleteKeyword("Scale"); } if(outMappingGrp.HasKeyword("PixelResolution")) { outMappingGrp.DeleteKeyword("PixelResolution"); } if(fromMappingGrp.HasKeyword("Scale")) { fromMappingGrp.DeleteKeyword("Scale"); } if(fromMappingGrp.HasKeyword("PixelResolution")) { fromMappingGrp.DeleteKeyword("PixelResolution"); } if(userMappingGrp.HasKeyword("Scale")) { userMappingGrp.DeleteKeyword("Scale"); } if(userMappingGrp.HasKeyword("PixelResolution")) { userMappingGrp.DeleteKeyword("PixelResolution"); } outMappingGrp.AddKeyword(PvlKeyword("Scale", ui.GetDouble("RESOLUTION"), "pixels/degree"), Pvl::Replace); } // Rotation will NOT Propagate if(outMappingGrp.HasKeyword("Rotation")) { outMappingGrp.DeleteKeyword("Rotation"); } /** * The user specified map template file overrides what ever is in the * cube's mapping group. */ for(int keyword = 0; keyword < userMappingGrp.Keywords(); keyword ++) { outMappingGrp.AddKeyword(userMappingGrp[keyword], Pvl::Replace); } /** * Now, we have to deal with unit conversions. We convert only if the following are true: * 1) We used values from the input cube * 2) The values are longitudes or latitudes * 3) The map file or user-specified information uses a different measurement system than * the input cube for said values. * * The data is corrected for: * 1) Positive east/positive west * 2) Longitude domain * 3) planetographic/planetocentric. */ // First, the longitude direction if(!sameDirection) { PvlGroup longitudes = inproj->MappingLongitudes(); for(int index = 0; index < longitudes.Keywords(); index ++) { if(!userMappingGrp.HasKeyword(longitudes[index].Name())) { // use the from domain because that's where our values are coming from if(((string)userMappingGrp["LongitudeDirection"]).compare("PositiveEast") == 0) { outMappingGrp[longitudes[index].Name()] = Projection::ToPositiveEast(outMappingGrp[longitudes[index].Name()], outMappingGrp["LongitudeDomain"]); } else { outMappingGrp[longitudes[index].Name()] = Projection::ToPositiveWest(outMappingGrp[longitudes[index].Name()], outMappingGrp["LongitudeDomain"]); } } } } // The minimum/maximum longitudes should be in order now. However, if the user entered a // maximum that was lower than the minimum, or a minimum that was higher than the maximum this // may still fail. Let it throw an error when we instantiate the projection. // Second, longitude domain if(userMappingGrp.HasKeyword("LongitudeDomain")) { // user set a new domain? if((int)userMappingGrp["LongitudeDomain"] != (int)fromMappingGrp["LongitudeDomain"]) { // new domain different? PvlGroup longitudes = inproj->MappingLongitudes(); for(int index = 0; index < longitudes.Keywords(); index ++) { if(!userMappingGrp.HasKeyword(longitudes[index].Name())) { if((int)userMappingGrp["LongitudeDomain"] == 180) { outMappingGrp[longitudes[index].Name()] = Projection::To180Domain(outMappingGrp[longitudes[index].Name()]); } else { outMappingGrp[longitudes[index].Name()] = Projection::To360Domain(outMappingGrp[longitudes[index].Name()]); } } } } } // Third, planetographic/planetocentric if(userMappingGrp.HasKeyword("LatitudeType")) { // user set a new domain? if(((string)userMappingGrp["LatitudeType"]).compare(fromMappingGrp["LatitudeType"]) != 0) { // new lat type different? PvlGroup latitudes = inproj->MappingLatitudes(); for(int index = 0; index < latitudes.Keywords(); index ++) { if(!userMappingGrp.HasKeyword(latitudes[index].Name())) { if(((string)userMappingGrp["LatitudeType"]).compare("Planetographic") == 0) { outMappingGrp[latitudes[index].Name()] = Projection::ToPlanetographic( (double)fromMappingGrp[latitudes[index].Name()], (double)fromMappingGrp["EquatorialRadius"], (double)fromMappingGrp["PolarRadius"]); } else { outMappingGrp[latitudes[index].Name()] = Projection::ToPlanetocentric( (double)fromMappingGrp[latitudes[index].Name()], (double)fromMappingGrp["EquatorialRadius"], (double)fromMappingGrp["PolarRadius"]); } } } } } // If MinLon/MaxLon out of order, we weren't able to calculate the correct values if((double)outMappingGrp["MinimumLongitude"] >= (double)outMappingGrp["MaximumLongitude"]) { if(!ui.WasEntered("MINLON") || !ui.WasEntered("MAXLON")) { string msg = "Unable to determine the correct [MinimumLongitude,MaximumLongitude]."; msg += " Please specify these values in the [MINLON,MAXLON] parameters"; throw iException::Message(iException::Pvl,msg,_FILEINFO_); } } int samples,lines; Pvl mapData; // Copy to preserve cube labels so we can match cube size if (userPvl.HasObject("IsisCube")) { mapData = userPvl; mapData.FindObject("IsisCube").DeleteGroup("Mapping"); mapData.FindObject("IsisCube").AddGroup(outMappingGrp); } else { mapData.AddGroup(outMappingGrp); } // *NOTE: The UpperLeftX,UpperLeftY keywords will not be used in the CreateForCube // method, and they will instead be recalculated. This is correct. Projection *outproj = ProjectionFactory::CreateForCube(mapData,samples,lines, ui.GetBoolean("MATCHMAP")); // Set up the transform object which will simply map // output line/samps -> output lat/lons -> input line/samps Transform *transform = new map2map (icube->Samples(), icube->Lines(), icube->Projection(), samples, lines, outproj, ui.GetBoolean("TRIM")); // Allocate the output cube and add the mapping labels Cube *ocube = p.SetOutputCube ("TO", transform->OutputSamples(), transform->OutputLines(), icube->Bands()); PvlGroup cleanOutGrp = outproj->Mapping(); // ProjectionFactory::CreateForCube updated mapData to have the correct // upperleftcornerx, upperleftcornery, scale and resolution. Use these // updated numbers. cleanOutGrp.AddKeyword(mapData.FindGroup("Mapping",Pvl::Traverse)["UpperLeftCornerX"], Pvl::Replace); cleanOutGrp.AddKeyword(mapData.FindGroup("Mapping",Pvl::Traverse)["UpperLeftCornerY"], Pvl::Replace); cleanOutGrp.AddKeyword(mapData.FindGroup("Mapping",Pvl::Traverse)["Scale"], Pvl::Replace); cleanOutGrp.AddKeyword(mapData.FindGroup("Mapping",Pvl::Traverse)["PixelResolution"], Pvl::Replace); ocube->PutGroup(cleanOutGrp); // Set up the interpolator Interpolator *interp; if (ui.GetString("INTERP") == "NEARESTNEIGHBOR") { interp = new Interpolator(Interpolator::NearestNeighborType); } else if (ui.GetString("INTERP") == "BILINEAR") { interp = new Interpolator(Interpolator::BiLinearType); } else if (ui.GetString("INTERP") == "CUBICCONVOLUTION") { interp = new Interpolator(Interpolator::CubicConvolutionType); } else { string msg = "Unknow value for INTERP [" + ui.GetString("INTERP") + "]"; throw iException::Message(iException::Programmer,msg,_FILEINFO_); } // Warp the cube p.StartProcess(*transform, *interp); p.EndProcess(); Application::Log(cleanOutGrp); // Cleanup delete transform; delete interp; }