void Preference::Load(const QString &file) { // Read the input PVL preference file Isis::Pvl pvl; if(Isis::FileName(file).fileExists()) { pvl.read(file); } // Override parameters each time load is called for(int i = 0; i < pvl.groups(); i++) { Isis::PvlGroup &inGroup = pvl.group(i); if(this->hasGroup(inGroup.name())) { Isis::PvlGroup &outGroup = this->findGroup(inGroup.name()); for(int k = 0; k < inGroup.keywords(); k++) { Isis::PvlKeyword &inKey = inGroup[k]; while(outGroup.hasKeyword(inKey.name())) { outGroup.deleteKeyword(inKey.name()); } outGroup += inKey; } } else { this->addGroup(inGroup); } } // Configure Isis to use the user performance preferences where // appropriate. if (hasGroup("Performance")) { PvlGroup &performance = findGroup("Performance"); if (performance.hasKeyword("GlobalThreads")) { IString threadsPreference = performance["GlobalThreads"][0]; if (threadsPreference.DownCase() != "optimized") { // We need a no-iException conversion here int threads = threadsPreference.ToQt().toInt(); if (threads > 0) { QThreadPool::globalInstance()->setMaxThreadCount(threads); } } } } }
void IsisMain() { QString projName; Process pHist; Cube *icube = pHist.SetInputCube("FROM"); // Check to see if the input cube looks like a HiRISE RDR if (icube->bandCount() > 3) { QString msg = "Input file [" + Application::GetUserInterface().GetFileName("FROM") + "] does not appear to be a HiRISE RDR product. Number of " + "bands is greater than 3"; throw IException(IException::Programmer, msg, _FILEINFO_); } // Setup to get a histogram for each band g_min = new double[icube->bandCount()]; g_max = new double[icube->bandCount()]; UserInterface &ui = Application::GetUserInterface(); // Determine if the data is to be converted to JPEG2000 IString enctype = ui.GetString("ENCODING_TYPE"); enctype.DownCase(); for (int band = 1; band <= icube->bandCount(); ++band) { if (ui.GetString("TYPE").compare("AUTOMATIC") == 0) { // Set up a histogram for this band. This call sets the input range // by making an initial stats pass to find the data min and max Histogram hist(*icube, band, pHist.Progress()); // Loop and accumulate histogram pHist.Progress()->SetText("Gathering Histogram"); pHist.Progress()->SetMaximumSteps(icube->lineCount()); pHist.Progress()->CheckStatus(); LineManager line(*icube); for (int i = 1; i <= icube->lineCount(); i++) { line.SetLine(i, band); icube->read(line); hist.AddData(line.DoubleBuffer(), line.size()); pHist.Progress()->CheckStatus(); } // get the requested cumulative percentages g_min[band-1] = ui.GetDouble("MINPER") == 0.0 ? hist.Minimum() : hist.Percent(ui.GetDouble("MINPER")); g_max[band-1] = ui.GetDouble("MAXPER") == 100.0 ? hist.Maximum() : hist.Percent(ui.GetDouble("MAXPER")); } else { g_min[band-1] = ui.GetDouble("MIN"); g_max[band-1] = ui.GetDouble("MAX"); } } // Find the minimum min and maximum max for all bands double minmin = g_min[0]; double maxmax = g_max[0]; for (int band = 1; band < icube->bandCount(); ++band) { if (g_min[band] < minmin) minmin = g_min[band]; if (g_max[band] > maxmax) maxmax = g_max[band]; } pHist.EndProcess(); // Set up for writing the data to a PDS formatted file ProcessExportPds p; Cube *icube2 = p.SetInputCube("FROM"); if (enctype.Equal("jp2")) { g_jp2buf = new char* [icube2->bandCount()]; FileName lblFile(ui.GetFileName("TO")); QString lblFileName = lblFile.path() + "/" + lblFile.baseName() + ".lbl"; p.SetDetached(lblFileName); p.setFormat(ProcessExport::JP2); } // Set the output pixel type and the special pixel values int nbits = ui.GetInteger("BITS"); if (nbits == 8) { if (enctype.Equal("jp2")) { for (int i = 0; i < icube2->bandCount(); i++) { g_jp2buf[i] = new char[icube2->sampleCount()]; } } g_oType = Isis::UnsignedByte; p.SetOutputType(g_oType); p.SetOutputRange(VALID_MIN1, VALID_MAX1); p.SetOutputNull(NULL1); p.SetOutputLis(LOW_INSTR_SAT1); p.SetOutputLrs(LOW_REPR_SAT1); p.SetOutputHis(HIGH_INSTR_SAT1); p.SetOutputHrs(HIGH_REPR_SAT1); } else if (nbits == 16) { if (enctype.Equal("jp2")) { for (int i = 0; i < icube2->bandCount(); i++) { g_jp2buf[i] = new char[icube2->sampleCount()*2]; } } g_oType = UnsignedWord; p.SetOutputType(g_oType); p.SetOutputRange(VALID_MINU2, VALID_MAXU2); p.SetOutputNull(NULLU2); p.SetOutputLis(LOW_INSTR_SATU2); p.SetOutputLrs(LOW_REPR_SATU2); p.SetOutputHis(HIGH_INSTR_SATU2); p.SetOutputHrs(HIGH_REPR_SATU2); } else { if (enctype.Equal("jp2")) { for (int i = 0; i < icube2->bandCount(); i++) { g_jp2buf[i] = new char[icube2->sampleCount()*2]; } } g_oType = UnsignedWord; p.SetOutputType(g_oType); p.SetOutputRange(3.0, pow(2.0, (double)(nbits)) - 1.0 - 2.0); p.SetOutputNull(0); p.SetOutputLrs(1); p.SetOutputLis(2); p.SetOutputHis(pow(2.0, (double)(nbits)) - 1.0 - 1.0); p.SetOutputHrs(pow(2.0, (double)(nbits)) - 1.0); } p.SetOutputEndian(Isis::Msb); p.SetInputRange(minmin, maxmax); // Get the PDS label from the process ProcessExportPds::PdsFileType type; if (enctype.Equal("jp2")) { type = ProcessExportPds::JP2Image; } else { type = ProcessExportPds::Image; } Pvl &pdsLabel = p.StandardPdsLabel(type); // Translate the keywords from the input cube label that go in the PDS label PvlTranslationManager cubeLab(*(icube2->label()), "$mro/translations/hirisePdsRdrCubeLabel.trn"); cubeLab.Auto(pdsLabel); // Translate the keywords from the original EDR PDS label that go in // this RDR PDS label OriginalLabel origBlob; icube2->read(origBlob); Pvl origLabel; PvlObject origLabelObj = origBlob.ReturnLabels(); origLabelObj.setName("OriginalLabelObject"); origLabel.addObject(origLabelObj); PvlTranslationManager orig(origLabel, "$mro/translations/hirisePdsRdrOriginalLabel.trn"); orig.Auto(pdsLabel); // Add labels to the PDS product that could not be handled by the translater if (ui.WasEntered("RATIONALE_DESC")) { pdsLabel.addKeyword( PvlKeyword("RATIONALE_DESC", ui.GetString("RATIONALE_DESC")), Pvl::Replace); } // Add PRODUCT_CREATION_TIME time_t startTime = time(NULL); struct tm *tmbuf = gmtime(&startTime); char timestr[80]; strftime(timestr, 80, "%Y-%m-%dT%H:%M:%S", tmbuf); QString dateTime = (QString) timestr; iTime tmpDateTime(dateTime); PvlGroup &timeParam = pdsLabel.findGroup("TIME_PARAMETERS"); timeParam += PvlKeyword("PRODUCT_CREATION_TIME", tmpDateTime.UTC()); // Add the N/A constant keyword to the ROOT pdsLabel += PvlKeyword("NOT_APPLICABLE_CONSTANT", toString(-9998)); // Add SOFTWARE_NAME to the ROOT QString sfname; sfname.clear(); sfname += "Isis " + Application::Version() + " " + Application::GetUserInterface().ProgramName(); pdsLabel += PvlKeyword("SOFTWARE_NAME", sfname); // Add the PRODUCT_VERSION_ID from the user parameter VERSION pdsLabel += PvlKeyword("PRODUCT_VERSION_ID", ui.GetString("VERSION")); // Add MRO:CCD_FLAG, MRO:BINNING, MRO:TDI // As pulled from the input Isis cube, the values are in CPMM order, so // convert them to CCD order PvlKeyword ccdFlag("MRO:CCD_FLAG"); PvlKeyword &cpmmFlag = origLabel.findObject("OriginalLabelObject"). findGroup("INSTRUMENT_SETTING_PARAMETERS"). findKeyword("MRO:POWERED_CPMM_FLAG"); PvlKeyword ccdBin("MRO:BINNING"); PvlKeyword &cpmmBin = icube2->label()->findObject("IsisCube"). findGroup("Mosaic")["cpmmSummingFlag"]; PvlKeyword ccdTdi("MRO:TDI"); PvlKeyword &cpmmTdi = icube2->label()->findObject("IsisCube"). findGroup("Mosaic")["cpmmTdiFlag"]; PvlKeyword ccdSpecial("MRO:SPECIAL_PROCESSING_FLAG"); PvlKeyword &cpmmSpecial = icube2->label()->findObject("IsisCube"). findGroup("Mosaic")["SpecialProcessingFlag"]; for (int ccd = 0; ccd < 14; ++ccd) { const unsigned int cpmmByCcd[] = {0, 1, 2, 3, 5, 8, 10, 11, 12, 13, 6, 7, 4, 9}; ccdFlag.addValue(cpmmFlag[cpmmByCcd[ccd]]); ccdBin.addValue(cpmmBin[cpmmByCcd[ccd]] != "Null" ? cpmmBin[cpmmByCcd[ccd]] : "-9998"); ccdTdi.addValue(cpmmTdi[cpmmByCcd[ccd]] != "Null" ? cpmmTdi[cpmmByCcd[ccd]] : "-9998"); IString tmp = cpmmSpecial[cpmmByCcd[ccd]]; tmp.Trim("\""); ccdSpecial.addValue(tmp.ToQt()); } if (!pdsLabel.hasGroup("INSTRUMENT_SETTING_PARAMETERS")) { pdsLabel.addGroup(PvlGroup("INSTRUMENT_SETTING_PARAMETERS")); } pdsLabel.findGroup("INSTRUMENT_SETTING_PARAMETERS") += ccdFlag; pdsLabel.findGroup("INSTRUMENT_SETTING_PARAMETERS") += ccdBin; pdsLabel.findGroup("INSTRUMENT_SETTING_PARAMETERS") += ccdTdi; pdsLabel.findGroup("INSTRUMENT_SETTING_PARAMETERS") += ccdSpecial; // Add/modify projection info if there is a projection if (pdsLabel.hasObject("IMAGE_MAP_PROJECTION")) { PvlObject &mapObject = pdsLabel.findObject("IMAGE_MAP_PROJECTION"); mapObject += PvlKeyword("^DATA_SET_MAP_PROJECTION", "DSMAP.CAT"); // Add the HiRISE comment to the CENTER_LATITUDE keyword PvlKeyword &clat = mapObject["CENTER_LATITUDE"]; clat.addComment("/* NOTE: CENTER_LATITUDE and CENTER_LONGITUDE describe the location */"); clat.addComment("/* of the center of projection, which is not necessarily equal to the */"); clat.addComment("/* location of the center point of the image. */"); if (mapObject.hasKeyword("CENTER_LATITUDE")) { PvlKeyword ¢erLat = mapObject["CENTER_LATITUDE"]; // if (centerLat[0] == "N/A") centerLat = -9998; if (centerLat[0] == "N/A") mapObject.deleteKeyword("CENTER_LATITUDE"); } if (mapObject.hasKeyword("CENTER_LONGITUDE")) { PvlKeyword ¢erLon = mapObject["CENTER_LONGITUDE"]; // if (centerLon[0] == "N/A") centerLon = -9998; if (centerLon[0] == "N/A") mapObject.deleteKeyword("CENTER_LONGITUDE"); } if (mapObject.hasKeyword("REFERENCE_LATITUDE")) { PvlKeyword &refLat = mapObject["REFERENCE_LATITUDE"]; // if (refLat[0] == "N/A") refLat = -9998; if (refLat[0] == "N/A") mapObject.deleteKeyword("REFERENCE_LATITUDE"); } if (mapObject.hasKeyword("REFERENCE_LONGITUE")) { PvlKeyword &refLon = mapObject["REFERENCE_LONGITUDE"]; // if (refLon[0] == "N/A") refLon = -9998; if (refLon[0] == "N/A") mapObject.deleteKeyword("REFERENCE_LONGITUDE"); } if (mapObject.hasKeyword("FIRST_STANDARD_PARALLEL")) { PvlKeyword &firstSP = mapObject["FIRST_STANDARD_PARALLEL"]; // if (firstSP[0] == "N/A") firstSP = -9998; if (firstSP[0] == "N/A") mapObject.deleteKeyword("FIRST_STANDARD_PARALLEL"); } if (mapObject.hasKeyword("SECOND_STANDARD_PARALLEL")) { PvlKeyword &secondSP = mapObject["SECOND_STANDARD_PARALLEL"]; // if (secondSP[0] == "N/A") secondSP = -9998; if (secondSP[0] == "N/A") mapObject.deleteKeyword("SECOND_STANDARD_PARALLEL"); } // For Equirectangular ONLY // Modify the radii in the pds label to use the radius at the center latitude // instead of the target radii from NAIF if (mapObject["MAP_PROJECTION_TYPE"][0] == "EQUIRECTANGULAR") { Projection *proj = ProjectionFactory::CreateFromCube(*icube2); PvlGroup &mapping = icube2->label()->findGroup("MAPPING", Pvl::Traverse); double radius = proj->LocalRadius((double)mapping["CenterLatitude"]) / 1000.0; mapObject["A_AXIS_RADIUS"].setValue(toString(radius), "KM"); mapObject["B_AXIS_RADIUS"].setValue(toString(radius), "KM"); mapObject["C_AXIS_RADIUS"].setValue(toString(radius), "KM"); } projName = mapObject["MAP_PROJECTION_TYPE"][0]; } // Calculate the min/max per band keywords // These come from the input real DN and are converted to the PDS file DN // The input to output mapping is opposite from the one above double slope = (p.GetOutputMaximum() - p.GetOutputMinimum()) / (maxmax - minmin); double intercept = p.GetOutputMaximum() - slope * maxmax; PvlKeyword minimum("MRO:MINIMUM_STRETCH", toString(slope * g_min[0] + intercept)); PvlKeyword maximum("MRO:MAXIMUM_STRETCH", toString(slope * g_max[0] + intercept)); for (int band = 1; band < icube2->bandCount(); ++band) { minimum += toString(slope * g_min[band] + intercept); maximum += toString(slope * g_max[band] + intercept); } if (enctype.Equal("jp2")) { // Add keywords to the PDS JP2 IMAGE object PvlObject &imagejp2 = pdsLabel.findObject("UNCOMPRESSED_FILE").findObject("IMAGE"); // Add the HiRISE specific description of the IMAGE object imagejp2 += PvlKeyword("DESCRIPTION", "HiRISE projected and mosaicked product"); // Add the SCALLING_FACTOR and OFFSET keywords imagejp2.addKeyword(PvlKeyword("SCALING_FACTOR", toString(slope)), Pvl::Replace); imagejp2.addKeyword(PvlKeyword("OFFSET", toString(intercept)), Pvl::Replace); // Reformat some keyword units in the image object // This is lame, but PDS units are difficult to work with, so for now??? PvlKeyword &oldFilterNamejp2 = imagejp2["FILTER_NAME"]; PvlKeyword newFilterName("FILTER_NAME"); for (int val = 0; val < oldFilterNamejp2.size(); ++val) { QString filtname(oldFilterNamejp2[val].toUpper()); if (filtname == "BLUEGREEN") filtname = "BLUE-GREEN"; else if (filtname == "NEARINFRARED") filtname = "NEAR-INFRARED"; newFilterName.addValue(filtname); } imagejp2.addKeyword(newFilterName, Pvl::Replace); PvlKeyword &oldCenterjp2 = imagejp2["CENTER_FILTER_WAVELENGTH"]; PvlKeyword newCenter("CENTER_FILTER_WAVELENGTH"); for (int val = 0; val < oldCenterjp2.size(); ++val) { if (((IString)(oldCenterjp2.unit(val))).UpCase() == "NANOMETERS") { newCenter.addValue(oldCenterjp2[val], "NM"); } else { newCenter.addValue(oldCenterjp2[val], oldCenterjp2.unit(val)); } } imagejp2.addKeyword(newCenter, Pvl::Replace); PvlKeyword &oldBandWidthjp2 = imagejp2["BAND_WIDTH"]; PvlKeyword newBandWidth("BAND_WIDTH"); for (int val = 0; val < oldBandWidthjp2.size(); ++val) { if (((IString)(oldBandWidthjp2.unit(val))).UpCase() == "NANOMETERS") { newBandWidth.addValue(oldBandWidthjp2[val], "nm"); } else { newBandWidth.addValue(oldBandWidthjp2[val], oldBandWidthjp2.unit(val)); } } imagejp2.addKeyword(newBandWidth, Pvl::Replace); // Add the min/max per band keywords imagejp2 += minimum; imagejp2 += maximum; // Modify the default SAMPLE_BIT_MASK keyword placed there by the // ProcessExportPds if (nbits != 8 && nbits != 16) { imagejp2.addKeyword(PvlKeyword("SAMPLE_BIT_MASK", toString((int)pow(2.0, (double)ui.GetInteger("BITS")) - 1)), Pvl::Replace); } } else { // Add keywords to the PDS IMAGE object PvlObject &image = pdsLabel.findObject("IMAGE"); // Add the HiRISE specific description of the IMAGE object image += PvlKeyword("DESCRIPTION", "HiRISE projected and mosaicked product"); /** * Calculate the SCALING_FACTOR and OFFSET keywords * Set these so the unsigned 16bit PDS disk values can be converted back * to the correct values Isis had * These keywords are used to map stored/disk values to the correct values so, * the input(x axis) values are the unsigned Xbit values from the PDS file */ // ??? unneccessary calculation - this is done by ProcessExportPds class. double slope = (maxmax - minmin) / (p.GetOutputMaximum() - p.GetOutputMinimum()); double intercept = maxmax - slope * p.GetOutputMaximum(); image.addKeyword(PvlKeyword("SCALING_FACTOR", toString(slope)), Pvl::Replace); image.addKeyword(PvlKeyword("OFFSET", toString(intercept)), Pvl::Replace); // Reformat some keyword units in the image object // This is lame, but PDS units are difficult to work with, so for now PvlKeyword &oldFilterName = image["FILTER_NAME"]; PvlKeyword newFilterName("FILTER_NAME"); for (int val = 0; val < oldFilterName.size(); ++val) { QString filtname(oldFilterName[val].toUpper()); if (filtname == "BLUEGREEN") filtname = "BLUE-GREEN"; else if (filtname == "NEARINFRARED") filtname = "NEAR-INFRARED"; newFilterName.addValue(filtname); } image.addKeyword(newFilterName, Pvl::Replace); PvlKeyword &oldCenter = image["CENTER_FILTER_WAVELENGTH"]; PvlKeyword newCenter("CENTER_FILTER_WAVELENGTH"); for (int val = 0; val < oldCenter.size(); ++val) { if (((IString)(oldCenter.unit(val))).UpCase() == "NANOMETERS") { newCenter.addValue(oldCenter[val], "NM"); } else { newCenter.addValue(oldCenter[val], oldCenter.unit(val)); } } image.addKeyword(newCenter, Pvl::Replace); PvlKeyword &oldBandWidth = image["BAND_WIDTH"]; PvlKeyword newBandWidth("BAND_WIDTH"); for (int val = 0; val < oldBandWidth.size(); ++val) { if (((IString)(oldBandWidth.unit(val))).UpCase() == "NANOMETERS") { newBandWidth.addValue(oldBandWidth[val], "NM"); } else { newBandWidth.addValue(oldBandWidth[val], oldBandWidth.unit(val)); } } image.addKeyword(newBandWidth, Pvl::Replace); // Add the min/max per band keywords image += minimum; image += maximum; // Modify the default SAMPLE_BIT_MASK keyword placed there by the // ProcessExportPds if (nbits != 8 && nbits != 16) { image.addKeyword(PvlKeyword("SAMPLE_BIT_MASK", toString((int)pow(2.0, (double)ui.GetInteger("BITS")) - 1)), Pvl::Replace); } } // Modify the units in the viewing_parameters group // if (pdsLabel.hasGroup("VIEWING_PARAMETERS")) { // PvlGroup &viewGroup = pdsLabel.findGroup("VIEWING_PARAMETERS"); // PvlKeyword &incidence = viewGroup["INCIDENCE_ANGLE"]; // IString tstr = incidence.unit(); // if (tstr.UpCase() == "DEG") incidence.setValue((QString)incidence, "deg"); // PvlKeyword &emission = viewGroup["EMISSION_ANGLE"]; // tstr = emission.unit(); // if (tstr.UpCase() == "DEG") emission.setValue((QString)emission, "deg"); // PvlKeyword &phase = viewGroup["PHASE_ANGLE"]; // tstr = phase.unit(); // if (tstr.UpCase() == "DEG") phase.setValue((QString)phase, "deg"); // PvlKeyword &solarLon = viewGroup["SOLAR_LONGITUDE"]; // tstr = solarLon.unit(); q // if (tstr.UpCase() == "DEG") solarLon.setValue((QString)solarLon, "deg"); // PvlKeyword &localTime = viewGroup["LOCAL_TIME"]; // tstr = localTime.unit(); // if (tstr.UpCase() == "LOCALDAY/24") localTime.setValue((QString)localTime, "local day/24"); // } // Add a keyword type (i.e., QString, bool, int...) file to the PDS label Pvl PvlFormat *formatter = pdsLabel.format(); formatter->add("$mro/translations/hirisePdsRdrExtras.typ"); // Add an output format template (group, object, & keyword output order) to // the PDS PVL if (projName == "EQUIRECTANGULAR") { if (enctype.Equal("jp2")) { pdsLabel.setFormatTemplate("$mro/templates/labels/hirisePdsRdrEquiJP2.pft"); } else { pdsLabel.setFormatTemplate("$mro/templates/labels/hirisePdsRdrEqui.pft"); } } else { if (enctype.Equal("jp2")) { pdsLabel.setFormatTemplate("$mro/templates/labels/hirisePdsRdrPolarJP2.pft"); } else { pdsLabel.setFormatTemplate("$mro/templates/labels/hirisePdsRdrPolar.pft"); } } // Open the output PDS file and dump the label and cube data if (enctype.Equal("jp2")) { p.OutputDetachedLabel(); g_jp2Encoder = new JP2Encoder(ui.GetFileName("TO"), icube2->sampleCount(), icube2->lineCount(), icube2->bandCount(), g_oType); g_jp2Encoder->OpenFile(); g_jp2ns = icube2->sampleCount(); g_jp2nb = icube2->bandCount(); g_jp2band = 0; p.StartProcess(writeJP2Image); p.EndProcess(); delete g_jp2Encoder; for (int i = 0; i < icube2->bandCount(); i++) { delete [] g_jp2buf[i]; } } else { FileName outFile(ui.GetFileName("TO")); ofstream oCube(outFile.expanded().toAscii().data()); p.OutputLabel(oCube); p.StartProcess(oCube); oCube.close(); p.EndProcess(); } delete [] g_min; delete [] g_max; }