void IsisMain() { // We will be processing by line first ProcessByTile lProc; lProc.Progress()->SetText("First pass"); // Setup the input and output cubes Cube *magCube = lProc.SetInputCube("MAGNITUDE"); Cube *phaseCube = lProc.SetInputCube("PHASE"); AlphaCube acube(*magCube); int initSamples = acube.BetaSamples(); int initLines = acube.BetaLines(); int numSamples = magCube->sampleCount(); int numLines = magCube->lineCount(); int numBands = magCube->bandCount(); // error checking for valid input cubes // i.e. the dimensions of the magnitude and phase cubes // are the same and are powers of two if(!fft.IsPowerOfTwo(numSamples) || !fft.IsPowerOfTwo(numLines) || magCube->sampleCount() != phaseCube->sampleCount() || magCube->lineCount() != phaseCube->lineCount()) { cerr << "Invalid Cubes: the dimensions of both cubes must be equal" " powers of 2." << endl; return; } lProc.SetTileSize(numSamples, 1); Isis::CubeAttributeOutput cao; lProc.SetOutputCube(tmpMagFileName, cao, numSamples, numLines, numBands); lProc.SetOutputCube(tmpPhaseFileName, cao, numSamples, numLines, numBands); // Start the line processing lProc.ProcessCubes(&IFFT2); lProc.Finalize(); // Then process by sample ProcessByTile sProc; sProc.Progress()->SetText("Second pass"); sProc.SetTileSize(1, numLines); // Setup the input and output cubes Isis::CubeAttributeInput cai; sProc.SetInputCube(tmpMagFileName, cai); sProc.SetInputCube(tmpPhaseFileName, cai); // the final output cube is cropped back to the original size sProc.SetOutputCube("TO", initSamples, initLines, numBands); //Start the sample proccessing sProc.ProcessCubes(&IFFT1); sProc.Finalize(); remove(tmpMagFileName.toAscii().data()); remove(tmpPhaseFileName.toAscii().data()); }
void IsisMain() { // Create a process by line object ProcessByLine p; // Get the size of the cube Cube *icube = p.SetInputCube("FROM"); // Open output text file UserInterface &ui = Application::GetUserInterface(); QString to = ui.GetFileName("TO", "txt"); fout.open(to.toAscii().data()); // Print header if needed if(ui.GetBoolean("HEADER")) { fout << "Input Cube: " << icube->fileName() << endl; fout << "Samples:Lines:Bands: " << icube->sampleCount() << ":" << icube->lineCount() << ":" << icube->bandCount() << endl; } // List the cube p.StartProcess(isis2ascii); p.EndProcess(); fout.close(); }
/** * @brief Initialize class from input PVL and Cube files * * This method is typically called at class instantiation time, * but is reentrant. It reads the parameter PVL file and * extracts Photometric model and Normalization models from it. * The cube is needed to match all potential profiles for each * band. * * @param pvl Input PVL parameter files * @param cube Input cube file to correct * * @author Kris Becker - 2/22/2010 * @history 2010-02-25 Kris Becker Added check for valid incidence angle */ void Hillier::init(PvlObject &pvl, Cube &cube) { // Make it reentrant _profiles.clear(); _bandpho.clear(); // Interate over all Photometric groups _normProf = DbProfile(pvl.findObject("NormalizationModel").findGroup("Algorithm", Pvl::Traverse)); _iRef = toDouble(ConfKey(_normProf, "IncRef", toString(30.0))); _eRef = toDouble(ConfKey(_normProf, "EmaRef", toString(0.0))); _gRef = toDouble(ConfKey(_normProf, "PhaRef", toString(_iRef))); // Check for valid incidence angle if(_iRef > fabs(90.0)) { ostringstream mess; mess << "Invalid incidence angle (" << _iRef << " >= 90.0) provided in PVL config file " << pvl.fileName(); throw IException(IException::User, mess.str(), _FILEINFO_); } PvlObject &phoObj = pvl.findObject("PhotometricModel"); DbProfile phoProf = DbProfile(phoObj); PvlObject::PvlGroupIterator algo = phoObj.beginGroup(); while(algo != phoObj.endGroup()) { if(algo->name().toLower() == "algorithm") { _profiles.push_back(DbProfile(phoProf, DbProfile(*algo))); } ++algo; } Pvl *label = cube.label(); PvlKeyword center = label->findGroup("BandBin", Pvl::Traverse)["Center"]; QString errs(""); for(int i = 0; i < cube.bandCount() ; i++) { Parameters parms = findParameters(toDouble(center[i])); if(parms.IsValid()) { parms.band = i + 1; _camera->SetBand(i + 1); parms.phoStd = photometry(parms, _iRef, _eRef, _gRef); _bandpho.push_back(parms); } else { // Appropriate photometric parameters not found ostringstream mess; mess << "Band " << i + 1 << " with wavelength Center = " << center[i] << " does not have PhotometricModel Algorithm group/profile"; IException e(IException::User, mess.str(), _FILEINFO_); errs += e.toString() + "\n"; } } // Check for errors and throw them all at the same time if(!errs.isEmpty()) { errs += " --> Errors in the input PVL file \"" + pvl.fileName() + "\""; throw IException(IException::User, errs, _FILEINFO_); } return; }
void IsisMain() { ProcessByBrick p; Cube *icube = p.SetInputCube("FROM"); int numDimensions = icube->bandCount(); p.SetBrickSize(128, 128, numDimensions); // The output cube with no attributes and real pixel type Isis::CubeAttributeOutput cao; cao.setPixelType(Isis::Real); p.SetOutputCube(tmpFileName, cao, icube->sampleCount(), icube->lineCount(), icube->bandCount()); // Get the data for the transform matrix pca = Isis::PrincipalComponentAnalysis(numDimensions); ProcessByBrick p2; p2.SetBrickSize(128, 128, numDimensions); p2.SetInputCube("FROM"); p2.Progress()->SetText("Computing Transform"); p2.StartProcess(GetData); p2.EndProcess(); pca.ComputeTransform(); p.Progress()->SetText("Transforming Cube"); p.StartProcess(Transform); p.EndProcess(); Isis::CubeAttributeInput cai; Cube *icube2 = p.SetInputCube(tmpFileName, cai); for(int i = 0; i < numDimensions; i++) { stretches.push_back(new GaussianStretch(*(icube2->histogram(i + 1)))); } p.SetOutputCube("TO"); p.SetBrickSize(128, 128, numDimensions); p.Progress()->SetText("Stretching Cube"); p.StartProcess(NormalizeAndInvert); for(int i = 0; i < numDimensions; i++) delete stretches[i]; stretches.clear(); p.EndProcess(); remove(tmpFileName.toAscii().data()); }
void IsisMain() { ProcessByLine p; Cube *icube = p.SetInputCube("FROM"); p.SetOutputCube("TO"); double gsigma = Isis::Application::GetUserInterface().GetDouble("GSIGMA"); for(int i = 0; i < icube->bandCount(); i++) { Histogram hist = *(icube->histogram(i + 1)); double mean = (hist.Maximum() + hist.Minimum()) / 2.0; double stdev = (hist.Maximum() - hist.Minimum()) / (2.0 * gsigma); stretch.push_back(new GaussianStretch(hist, mean, stdev)); } p.StartProcess(gauss); for(int i = 0; i < icube->bandCount(); i++) delete stretch[i]; stretch.clear(); p.EndProcess(); }
/** * Set the output cube to specified file name and specified input images * and output attributes and lat,lons */ Isis::Cube *ProcessMapMosaic::SetOutputCube(const QString &inputFile, PvlGroup mapping, CubeAttributeOutput &oAtt, const QString &mosaicFile) { if (OutputCubes.size() != 0) { QString msg = "You can only specify one output cube and projection"; throw IException(IException::Programmer, msg, _FILEINFO_); } if (mapping.hasKeyword("UpperLeftCornerX")) mapping.deleteKeyword("UpperLeftCornerX"); if (mapping.hasKeyword("UpperLeftCornerY")) mapping.deleteKeyword("UpperLeftCornerY"); if (p_createMosaic) { Pvl newMap; newMap.addGroup(mapping); int samps, lines, bands; delete ProjectionFactory::CreateForCube(newMap, samps, lines, false); // Initialize the mosaic ProcessByLine p; CubeAttributeInput inAtt(inputFile); Cube *propCube = p.SetInputCube(inputFile, inAtt); bands = propCube->bandCount(); // If track set, create the origin band if (GetTrackFlag()) { bands += 1; } // For average priority, get the new band count else if (GetImageOverlay() == AverageImageWithMosaic) { bands *= 2; } p.PropagateHistory(false); p.PropagateLabels(false); Cube *ocube = p.SetOutputCube(mosaicFile, oAtt, samps, lines, bands); p.Progress()->SetText("Initializing mosaic"); p.ClearInputCubes(); p.StartProcess(ProcessMapMosaic::FillNull); // CreateForCube created some keywords in the mapping group that needs to be added ocube->putGroup(newMap.findGroup("Mapping", Pvl::Traverse)); p.EndProcess(); } Cube *mosaicCube = new Cube(); AddOutputCube(mosaicCube); mosaicCube->open(mosaicFile, "rw"); mosaicCube->addCachingAlgorithm(new UniqueIOCachingAlgorithm(2)); return mosaicCube; }
void CopyCubeIntoBuffer ( QString &fileString, Buffer* &data) { Cube cube; FileName filename(fileString); if (filename.isVersioned()) filename = filename.highestVersion(); if (!filename.fileExists()) { QString msg = fileString + " does not exist."; throw IException(IException::User, msg, _FILEINFO_); } cube.open(filename.expanded()); Brick brick(cube.sampleCount(), cube.lineCount(), cube.bandCount(), cube.pixelType()); brick.SetBasePosition(1, 1, 1); cube.read(brick); data = new Buffer(brick); fileString = filename.expanded(); }
void IsisMain() { ProcessRubberSheet p; // Open the input cube Cube *icube = p.SetInputCube("FROM"); // Set up the transform object UserInterface &ui = Application::GetUserInterface(); Transform *transform = new Rotate(icube->sampleCount(), icube->lineCount(), ui.GetDouble("DEGREES")); // Determine the output size int samples = transform->OutputSamples(); int lines = transform->OutputLines(); // Allocate the output file p.SetOutputCube("TO", samples, lines, icube->bandCount()); // 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 { QString msg = "Unknow value for INTERP [" + ui.GetString("INTERP") + "]"; throw IException(IException::Programmer, msg, _FILEINFO_); } p.StartProcess(*transform, *interp); p.EndProcess(); delete transform; delete interp; }
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->group("Mapping"); TProjection *inproj = (TProjection *) 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", toString(ui.GetDouble("MINLAT"))), Pvl::Replace); } if(ui.WasEntered("MAXLAT") && !ui.GetBoolean("MATCHMAP")) { userMappingGrp.addKeyword(PvlKeyword("MaximumLatitude", toString(ui.GetDouble("MAXLAT"))), Pvl::Replace); } if(ui.WasEntered("MINLON") && !ui.GetBoolean("MATCHMAP")) { userMappingGrp.addKeyword(PvlKeyword("MinimumLongitude", toString(ui.GetDouble("MINLON"))), Pvl::Replace); } if(ui.WasEntered("MAXLON") && !ui.GetBoolean("MATCHMAP")) { userMappingGrp.addKeyword(PvlKeyword("MaximumLongitude", toString(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(((QString)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"] = toString(minLon); outMappingGrp["MinimumLongitude"] = toString(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", toString(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", toString(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(((QString)userMappingGrp["LongitudeDirection"]).compare("PositiveEast") == 0) { outMappingGrp[longitudes[index].name()] = toString( TProjection::ToPositiveEast(outMappingGrp[longitudes[index].name()], outMappingGrp["LongitudeDomain"])); } else { outMappingGrp[longitudes[index].name()] = toString( TProjection::ToPositiveWest(outMappingGrp[longitudes[index].name()], outMappingGrp["LongitudeDomain"])); } } } } // 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()] = toString( TProjection::To180Domain(outMappingGrp[longitudes[index].name()])); } else { outMappingGrp[longitudes[index].name()] = toString( TProjection::To360Domain(outMappingGrp[longitudes[index].name()])); } } } } } // Third, planetographic/planetocentric if(userMappingGrp.hasKeyword("LatitudeType")) { // user set a new domain? if(((QString)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(((QString)userMappingGrp["LatitudeType"]).compare("Planetographic") == 0) { outMappingGrp[latitudes[index].name()] = toString(TProjection::ToPlanetographic( (double)fromMappingGrp[latitudes[index].name()], (double)fromMappingGrp["EquatorialRadius"], (double)fromMappingGrp["PolarRadius"])); } else { outMappingGrp[latitudes[index].name()] = toString(TProjection::ToPlanetocentric( (double)fromMappingGrp[latitudes[index].name()], (double)fromMappingGrp["EquatorialRadius"], (double)fromMappingGrp["PolarRadius"])); } } } } } // Try a couple equivalent longitudes to fix the ordering of min,max for border cases if ((double)outMappingGrp["MinimumLongitude"] >= (double)outMappingGrp["MaximumLongitude"]) { if ((QString)outMappingGrp["MinimumLongitude"] == "180.0" && (int)userMappingGrp["LongitudeDomain"] == 180) outMappingGrp["MinimumLongitude"] = "-180"; if ((QString)outMappingGrp["MaximumLongitude"] == "-180.0" && (int)userMappingGrp["LongitudeDomain"] == 180) outMappingGrp["MaximumLongitude"] = "180"; if ((QString)outMappingGrp["MinimumLongitude"] == "360.0" && (int)userMappingGrp["LongitudeDomain"] == 360) outMappingGrp["MinimumLongitude"] = "0"; if ((QString)outMappingGrp["MaximumLongitude"] == "0.0" && (int)userMappingGrp["LongitudeDomain"] == 360) outMappingGrp["MaximumLongitude"] = "360"; } // 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")) { QString msg = "Unable to determine the correct [MinimumLongitude,MaximumLongitude]."; msg += " Please specify these values in the [MINLON,MAXLON] parameters"; throw IException(IException::Unknown, 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. TProjection *outproj = (TProjection *) 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->sampleCount(), icube->lineCount(), (TProjection *) 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->bandCount()); 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 { QString msg = "Unknow value for INTERP [" + ui.GetString("INTERP") + "]"; throw IException(IException::Programmer, msg, _FILEINFO_); } // Warp the cube p.StartProcess(*transform, *interp); p.EndProcess(); Application::Log(cleanOutGrp); // Cleanup delete transform; delete interp; }
/** The ISIS smtk main application */ void IsisMain() { UserInterface &ui = Application::GetUserInterface(); // Open the first cube. It is the left hand image. Cube lhImage; CubeAttributeInput &attLeft = ui.GetInputAttribute("FROM"); vector<QString> bandLeft = attLeft.bands(); lhImage.setVirtualBands(bandLeft); lhImage.open(ui.GetFileName("FROM"),"r"); // Open the second cube, it is geomertricallty altered. We will be matching the // first to this one by attempting to compute a sample/line offsets Cube rhImage; CubeAttributeInput &attRight = ui.GetInputAttribute("MATCH"); vector<QString> bandRight = attRight.bands(); rhImage.setVirtualBands(bandRight); rhImage.open(ui.GetFileName("MATCH"),"r"); // Ensure only single bands if (lhImage.bandCount() != 1 || rhImage.bandCount() != 1) { QString msg = "Input Cubes must have only one band!"; throw IException(IException::User,msg,_FILEINFO_); } // Both images must have a Camera and can also have a Projection. We will // only deal with a Camera, however as a projected, non-mosaicked image // uses a Projection internal to the Camera object. Camera *lhCamera = NULL; Camera *rhCamera = NULL; try { lhCamera = lhImage.camera(); rhCamera = rhImage.camera(); } catch (IException &ie) { QString msg = "Both input images must have a camera"; throw IException(ie, IException::User, msg, _FILEINFO_); } // Since we are generating a DEM, we must turn off any existing // DEM that may have been initialized with spiceinit. lhCamera->IgnoreElevationModel(true); rhCamera->IgnoreElevationModel(true); // Get serial number QString serialLeft = SerialNumber::Compose(lhImage, true); QString serialRight = SerialNumber::Compose(rhImage, true); // This still precludes band to band registrations. if (serialLeft == serialRight) { QString sLeft = FileName(lhImage.fileName()).name(); QString sRight = FileName(rhImage.fileName()).name(); if (sLeft == sRight) { QString msg = "Cube Serial Numbers must be unique - FROM=" + serialLeft + ", MATCH=" + serialRight; throw IException(IException::User,msg,_FILEINFO_); } serialLeft = sLeft; serialRight = sRight; } Progress prog; prog.SetText("Finding Initial Seeds"); int nl = lhImage.lineCount(); int ns = lhImage.sampleCount(); BigInt numAttemptedInitialPoints = 0; // Declare Gruen matcher SmtkMatcher matcher(ui.GetFileName("REGDEF"), &lhImage, &rhImage); // Get line/sample linc/sinc parameters int space = ui.GetInteger("SPACE"); int linc (space), sinc(space); // Do we have a seed points from a control net file? bool useseed = ui.WasEntered("CNET"); // Base points on an input cnet SmtkQStack gstack; double lastEigen(0.0); if (useseed) { ControlNet cnet(ui.GetFileName("CNET")); prog.SetMaximumSteps(cnet.GetNumPoints()); prog.CheckStatus(); gstack.reserve(cnet.GetNumPoints()); for (int cpIndex = 0; cpIndex < cnet.GetNumPoints(); cpIndex ++) { ControlPoint *cp = cnet.GetPoint(cpIndex); if (!cp->IsIgnored()) { ControlMeasure *cmLeft(0), *cmRight(0); for(int cmIndex = 0; cmIndex < cp->GetNumMeasures(); cmIndex ++) { ControlMeasure *cm = cp->GetMeasure(cmIndex); if (!cm->IsIgnored()) { if (cm->GetCubeSerialNumber() == serialLeft) cmLeft = cp->GetMeasure(cmIndex); if (cm->GetCubeSerialNumber() == serialRight) cmRight = cp->GetMeasure(cmIndex); } } // If we have both left and right images in the control point, save it if ( (cmLeft != 0) && (cmRight != 0) ) { Coordinate left = Coordinate(cmLeft->GetLine(), cmLeft->GetSample()); Coordinate right = Coordinate(cmRight->GetLine(), cmRight->GetSample()); SmtkPoint spnt = matcher.Create(left, right); // Insert the point (unregistered) if ( spnt.isValid() ) { int line = (int) cmLeft->GetLine(); int samp = (int) cmLeft->GetSample(); matcher.isValid(spnt); gstack.insert(qMakePair(line, samp), spnt); lastEigen = spnt.GoodnessOfFit(); } } } prog.CheckStatus(); } } else { // We want to create a grid of control points that is N rows by M columns. int rows = (lhImage.lineCount() + linc - 1)/linc; int cols = (lhImage.sampleCount() + sinc - 1)/sinc; prog.SetMaximumSteps(rows * cols); prog.CheckStatus(); // First pass stack and eigen value statistics SmtkQStack fpass; fpass.reserve(rows * cols); Statistics temp_mev; // Loop through grid of points and get statistics to compute // initial set of points for (int line = linc / 2 + 1; line < nl; line += linc) { for (int samp = sinc / 2 + 1 ; samp < ns; samp += sinc) { numAttemptedInitialPoints ++; SmtkPoint spnt = matcher.Register(Coordinate(line,samp)); if ( spnt.isValid() ) { matcher.isValid(spnt); fpass.insert(qMakePair(line, samp), spnt); temp_mev.AddData(spnt.GoodnessOfFit()); } prog.CheckStatus(); } } // Now select a subset of fpass points as the seed points cout << "Number of Potential Seed Points: " << fpass.size() << "\n"; cout << "Min / Max Eigenvalues Matched: " << temp_mev.Minimum() << ", " << temp_mev.Maximum() << "\n"; // How many seed points are requested double nseed = ui.GetDouble("NSEED"); int inseed; if (nseed >= 1.0) inseed = (int) nseed; else if (nseed > 0.0) inseed = (int) (nseed * (double) (fpass.size())); else inseed = (int) ((double) (fpass.size()) * 0.05); double seedsample = ui.GetDouble("SEEDSAMPLE"); // Generate a new stack gstack.reserve(inseed); while ((gstack.size() < inseed) && (!fpass.isEmpty() )) { SmtkQStack::iterator bestm; if (seedsample <= 0.0) { bestm = matcher.FindSmallestEV(fpass); } else { bestm = matcher.FindExpDistEV(fpass, seedsample, temp_mev.Minimum(), temp_mev.Maximum()); } // Add point to stack if (bestm != fpass.end()) { Coordinate right = bestm.value().getRight(); matcher.isValid(bestm.value()); gstack.insert(bestm.key(), bestm.value()); lastEigen = bestm.value().GoodnessOfFit(); fpass.erase(bestm); } } // If a user wants to see the seed network, write it out here if (ui.WasEntered("OSEEDNET")) { WriteCnet(ui.GetFileName("OSEEDNET"), gstack, lhCamera->target()->name(), serialLeft, serialRight); } } /////////////////////////////////////////////////////////////////////// // All done with seed points. Sanity check ensures we actually found // some. /////////////////////////////////////////////////////////////////////// if (gstack.size() <= 0) { QString msg = "No seed points found - may need to check Gruen parameters."; throw IException(IException::User, msg, _FILEINFO_); } // Report seed point status if (!useseed) { cout << "Number of Seed Points used: " << gstack.size() << "\n"; cout << "EV of last Seed Point: " << lastEigen << "\n"; } else { cout << "Number of Manual Seed Points: " << gstack.size() << "\n"; } // Use seed points (in stack) to grow SmtkQStack bmf; bmf.reserve(gstack.size()); // Probably need much more but for starters... BigInt numOrigPoints = gstack.size(); BigInt passpix2 = 0; int subcbox = ui.GetInteger("SUBCBOX"); int halfBox((subcbox-1)/2); while (!gstack.isEmpty()) { SmtkQStackIter cstack = matcher.FindSmallestEV(gstack); // Print number on stack if ((gstack.size() % 1000) == 0) { cout << "Number on Stack: " << gstack.size() << ". " << cstack.value().GoodnessOfFit() << "\n"; } // Test to see if already determined SmtkQStackIter bmfPt = bmf.find(cstack.key()); if (bmfPt == bmf.end()) { // Its not in the final stack, process it // Retrieve the point SmtkPoint spnt = cstack.value(); // Register if its not already registered if (!spnt.isRegistered()) { spnt = matcher.Register(spnt, spnt.getAffine()); } // Still must check for validity if the point was just registered, // otherwise should be good if ( spnt.isValid() ) { passpix2++; bmf.insert(cstack.key(), spnt); // inserts (0,0) offset excluded below int line = cstack.key().first; int sample = cstack.key().second; // Determine match points double eigen(spnt.GoodnessOfFit()); for (int sampBox = -halfBox ; sampBox <= halfBox ; sampBox++ ) { int csamp = sample + sampBox; for (int lineBox = -halfBox ; lineBox <= halfBox ; lineBox++) { int cline = line + lineBox; if ( !( (sampBox == 0) && (lineBox == 0)) ) {// Already added above SmtkQPair dupPair(cline, csamp); SmtkQStackIter temp = bmf.find(dupPair); SmtkPoint bmfpnt; if (temp != bmf.end()) { if (temp.value().GoodnessOfFit() > eigen) { // Create cloned point with better fit bmfpnt = matcher.Clone(spnt, Coordinate(cline,csamp)); } } else { // ISIS2 is BMF(SAMP,LINE,7) .EQ VALID_MAX4) // Clone new point for insert bmfpnt = matcher.Clone(spnt, Coordinate(cline,csamp)); } // Add if good point if (bmfpnt.isValid()) { bmf.insert(dupPair, bmfpnt); } } } } // Grow stack with spacing adding info to stack for (int i = -1 ; i <= 1 ; i ++) { // Sample for (int j = -1 ; j <= 1 ; j ++) { // Line // Don't re-add the original sample, line if ( !((i == 0) && (j == 0)) ) { // Grow based upon spacing double ssamp = sample + (i * space); double sline = line + (j * space); Coordinate pnt = Coordinate(sline, ssamp); SmtkPoint gpnt = matcher.Clone(spnt, pnt); if ( gpnt.isValid() ) { SmtkQPair growpt((int) sline, (int) ssamp); // double check we don't have a finalized result at this position SmtkQStackIter temp = bmf.find(growpt); if(temp == bmf.end()) { gstack.insert(growpt, gpnt); } } } } } } } // Remove the current point from the grow stack (hole) gstack.erase(cstack); } ///////////////////////////////////////////////////////////////////////// // All done with creating points. Perform output options. ///////////////////////////////////////////////////////////////////////// // If a TO parameter was specified, create DEM with errors if (ui.WasEntered("TO")) { // Create the output DEM cout << "\nCreating output DEM from " << bmf.size() << " points.\n"; Process p; Cube *icube = p.SetInputCube("FROM"); Cube *ocube = p.SetOutputCube("TO", icube->sampleCount(), icube->lineCount(), 3); p.ClearInputCubes(); int boxsize = ui.GetInteger("BOXSIZE"); double plotdist = ui.GetDouble("PLOTDIST"); TileManager dem(*ocube), eigen(*ocube), stErr(*ocube); dem.SetTile(1, 1); // DEM Data/elevation stErr.SetTile(1, 2); // Error in stereo computation eigen.SetTile(1, 3); // Eigenvalue of the solution int nBTiles(eigen.Tiles()/3); // Total tiles / 3 bands prog.SetText("Creating DEM"); prog.SetMaximumSteps(nBTiles); prog.CheckStatus(); Statistics stAng; while ( !eigen.end() ) { // Must use the last band for this!! PointPlot tm = for_each(bmf.begin(), bmf.end(), PointPlot(dem, plotdist)); tm.FillPoints(*lhCamera, *rhCamera, boxsize, dem, stErr, eigen, &stAng); ocube->write(dem); ocube->write(stErr); ocube->write(eigen); dem.next(); stErr.next(); eigen.next(); prog.CheckStatus(); } // Report Stereo separation angles PvlGroup stresultsPvl("StereoSeparationAngle"); stresultsPvl += PvlKeyword("Minimum", toString(stAng.Minimum()), "deg"); stresultsPvl += PvlKeyword("Average", toString(stAng.Average()), "deg"); stresultsPvl += PvlKeyword("Maximum", toString(stAng.Maximum()), "deg"); stresultsPvl += PvlKeyword("StandardDeviation", toString(stAng.StandardDeviation()), "deg"); Application::Log(stresultsPvl); // Update the label with BandBin keywords PvlKeyword filter("FilterName", "Elevation", "meters"); filter.addValue("ElevationError", "meters"); filter.addValue("GoodnessOfFit", "unitless"); PvlKeyword center("Center", "1.0"); center.addValue("1.0"); center.addValue("1.0"); PvlGroup &bandbin = ocube->label()->findGroup("BandBin", PvlObject::Traverse); bandbin.addKeyword(filter, PvlContainer::Replace); bandbin.addKeyword(center, PvlContainer::Replace); center.setName("Width"); bandbin.addKeyword(center, PvlContainer::Replace); p.EndProcess(); } // If a cnet file was entered, write the ControlNet pvl to the file if (ui.WasEntered("ONET")) { WriteCnet(ui.GetFileName("ONET"), bmf, lhCamera->target()->name(), serialLeft, serialRight); } // Create output data PvlGroup totalPointsPvl("Totals"); totalPointsPvl += PvlKeyword("AttemptedPoints", toString(numAttemptedInitialPoints)); totalPointsPvl += PvlKeyword("InitialSuccesses", toString(numOrigPoints)); totalPointsPvl += PvlKeyword("GrowSuccesses", toString(passpix2)); totalPointsPvl += PvlKeyword("ResultingPoints", toString(bmf.size())); Application::Log(totalPointsPvl); Pvl arPvl = matcher.RegistrationStatistics(); PvlGroup smtkresultsPvl("SmtkResults"); smtkresultsPvl += PvlKeyword("SpiceOffImage", toString(matcher.OffImageErrorCount())); smtkresultsPvl += PvlKeyword("SpiceDistanceError", toString(matcher.SpiceErrorCount())); arPvl.addGroup(smtkresultsPvl); for(int i = 0; i < arPvl.groups(); i++) { Application::Log(arPvl.group(i)); } // add the auto registration information to print.prt PvlGroup autoRegTemplate = matcher.RegTemplate(); Application::Log(autoRegTemplate); // Don't need the cubes opened anymore lhImage.close(); rhImage.close(); }
void IsisMain() { try { // We will be processing by line ProcessByLine p; double sscale, lscale; int ins, inl, inb; int ons, onl; vector<QString> bands; Cube inCube; // To propogate labels, set input cube, // this cube will be cleared after output cube is set. p.SetInputCube("FROM"); // Setup the input and output cubes UserInterface &ui = Application::GetUserInterface(); QString replaceMode = ui.GetAsString("VPER_REPLACE"); CubeAttributeInput cai(ui.GetAsString("FROM")); bands = cai.bands(); inCube.setVirtualBands(bands); QString from = ui.GetFileName("FROM"); inCube.open(from); ins = inCube.sampleCount(); inl = inCube.lineCount(); inb = inCube.bandCount(); QString alg = ui.GetString("ALGORITHM"); double vper = ui.GetDouble("VALIDPER") / 100.; if(ui.GetString("MODE") == "TOTAL") { ons = ui.GetInteger("ONS"); onl = ui.GetInteger("ONL"); sscale = (double)ins / (double)ons; lscale = (double)inl / (double)onl; } else { sscale = ui.GetDouble("SSCALE"); lscale = ui.GetDouble("LSCALE"); ons = (int)((double)ins / sscale + 0.5); onl = (int)((double)inl / lscale + 0.5); } if(ons > ins || onl > inl) { QString msg = "Number of output samples/lines must be less than or equal"; msg = msg + " to the input samples/lines."; throw IException(IException::User, msg, _FILEINFO_); } // Allocate output file Cube *ocube = p.SetOutputCube("TO", ons, onl, inb); // Our processing routine only needs 1 // the original set was for info about the cube only p.ClearInputCubes(); // Start the processing PvlGroup results; if(alg == "AVERAGE"){ Average average(&inCube, sscale, lscale, vper, replaceMode); p.ProcessCubeInPlace(average, false); results = average.UpdateOutputLabel(ocube); } else if(alg == "NEAREST") { Nearest near(&inCube, sscale, lscale); p.ProcessCubeInPlace(near, false); results = near.UpdateOutputLabel(ocube); } // Cleanup inCube.close(); p.EndProcess(); // Write the results to the log Application::Log(results); } // REFORMAT THESE ERRORS INTO ISIS TYPES AND RETHROW catch (IException &) { throw; } catch (std::exception const &se) { QString message = "std::exception: " + (QString)se.what(); throw IException(IException::User, message, _FILEINFO_); } catch (...) { QString message = "Other Error"; throw IException(IException::User, message, _FILEINFO_); } }
void IsisMain() { // Get the list of cubes to stack Process p; UserInterface &ui = Application::GetUserInterface(); FileList cubeList(ui.GetFileName("FROMLIST")); // Loop through the list int nsamps(0), nlines(0), nbands(0); PvlGroup outBandBin("BandBin"); try { for(int i = 0; i < cubeList.size(); i++) { Cube cube; CubeAttributeInput inatt(cubeList[i].original()); vector<QString> bands = inatt.bands(); cube.setVirtualBands(bands); cube.open(cubeList[i].toString()); if(i == 0) { nsamps = cube.sampleCount(); nlines = cube.lineCount(); nbands = cube.bandCount(); } else { // Make sure they are all the same size if((nsamps != cube.sampleCount()) || (nlines != cube.lineCount())) { QString msg = "Spatial dimensions of cube [" + cubeList[i].toString() + "] does not match other cubes in list"; throw IException(IException::User, msg, _FILEINFO_); } // Get the total number of bands nbands += cube.bandCount(); } // Build up the band bin group PvlObject &isiscube = cube.label()->findObject("IsisCube"); if(isiscube.hasGroup("BandBin")) { PvlGroup &inBandBin = isiscube.findGroup("BandBin"); for(int key = 0; key < inBandBin.keywords(); key++) { PvlKeyword &inKey = inBandBin[key]; if(!outBandBin.hasKeyword(inKey.name())) { outBandBin += inKey; } else { PvlKeyword &outKey = outBandBin[inKey.name()]; for(int index = 0; index < (int)inKey.size(); index++) { outKey.addValue(inKey[index], inKey.unit(index)); } } } } cube.close(); } } catch(IException &e) { QString msg = "Invalid cube in list file [" + ui.GetFileName("FROMLIST") + "]"; throw IException(e, IException::User, msg, _FILEINFO_); } // Setup to propagate from the first input cube ProcessByLine p2; CubeAttributeInput inatt; int index = 0; if(ui.WasEntered("PROPLAB")) { bool match = false; QString fname = ui.GetFileName("PROPLAB"); for(int i = 0; i < cubeList.size(); i++) { if(fname == cubeList[i].toString()) { index = i; match = true; break; } } if(!match) { QString msg = "FileName [" + ui.GetFileName("PROPLAB") + "] to propagate labels from is not in the list file [" + ui.GetFileName("FROMLIST") + "]"; throw IException(IException::User, msg, _FILEINFO_); } } p2.SetInputCube(cubeList[index].toString(), inatt); // Create the output cube Cube *ocube = p2.SetOutputCube("TO", nsamps, nlines, nbands); p2.ClearInputCubes(); p2.Progress()->SetText("Allocating cube"); p2.StartProcess(NullBand); // Add the band bin group if necessary if(outBandBin.keywords() > 0) { ocube->putGroup(outBandBin); } p2.EndProcess(); // Now loop and mosaic in each cube int sband = 1; for(int i = 0; i < cubeList.size(); i++) { ProcessMosaic m; m.SetBandBinMatch(false); Progress *prog = m.Progress(); prog->SetText("Adding band " + toString((int)i + 1) + " of " + toString(nbands)); m.SetOutputCube("TO"); CubeAttributeInput attrib(cubeList[i].toString()); Cube *icube = m.SetInputCube(cubeList[i].toString(), attrib); m.SetImageOverlay(ProcessMosaic::PlaceImagesOnTop); m.StartProcess(1, 1, sband); sband += icube->bandCount(); m.EndProcess(); } }
void IsisMain () { ResetGlobals(); UserInterface &ui = Application::GetUserInterface(); ProcessByBrick p; Cube *icube = p.SetInputCube("FROM"); // Make sure it is a WAC cube Isis::PvlGroup &inst = icube->label()->findGroup("Instrument", Pvl::Traverse); QString instId = (QString) inst["InstrumentId"]; instId = instId.toUpper(); if (instId != "WAC-VIS" && instId != "WAC-UV") { QString msg = "This program is intended for use on LROC WAC images only. ["; msg += icube->fileName() + "] does not appear to be a WAC image."; throw IException(IException::User, msg, _FILEINFO_); } // And check if it has already run through calibration if (icube->label()->findObject("IsisCube").hasGroup("Radiometry")) { QString msg = "This image has already been calibrated"; throw IException(IException::User, msg, _FILEINFO_); } if (icube->label()->findObject("IsisCube").hasGroup("AlphaCube")) { QString msg = "This application can not be run on any image that has been geometrically transformed (i.e. scaled, rotated, sheared, or reflected) or cropped."; throw IException(IException::User, msg, _FILEINFO_); } g_dark = ui.GetBoolean("DARK"); g_flatfield = ui.GetBoolean("FLATFIELD"); g_radiometric = ui.GetBoolean("RADIOMETRIC"); g_iof = (ui.GetString("RADIOMETRICTYPE") == "IOF"); g_specpix = ui.GetBoolean("SPECIALPIXELS"); g_temprature = ui.GetBoolean("TEMPERATURE"); // Determine the dark/flat files to use QString offset = (QString) inst["BackgroundOffset"]; QString mode = (QString) inst["Mode"]; QString instModeId = (QString) inst["InstrumentModeId"]; instModeId = instModeId.toUpper(); if (instModeId == "COLOR" && (QString) inst["InstrumentId"] == "WAC-UV") instModeId = "UV"; else if (instModeId == "VIS") instModeId = "COLOR"; g_startTemperature = (double) inst["BeginTemperatureFpa"]; g_endTemperature = (double) inst["EndTemperatureFpa"]; g_numFrames = (int) inst["NumFramelets"]; vector<QString> darkFiles; ui.GetAsString("DARKFILE", darkFiles); QString flatFile = ui.GetAsString("FLATFIELDFILE"); QString radFile = ui.GetAsString("RADIOMETRICFILE"); QString specpixFile = ui.GetAsString("SPECIALPIXELSFILE"); QString tempFile = ui.GetAsString("TEMPERATUREFILE"); // Figure out which bands are input for (int i = 1; i <= icube->bandCount(); i++) { g_bands.push_back(icube->physicalBand(i)); } Isis::PvlGroup &bandBin = icube->label()->findGroup("BandBin", Pvl::Traverse); QString filter = (QString) bandBin["Center"][0]; QString filterNum = (QString) bandBin["FilterNumber"][0]; //We have to pay special attention incase we are passed a //single band image that has been "exploded" from a multiband wac if (instModeId == "COLOR" && g_bands.size() == 1) g_bands[0] = (toInt(filterNum) -2); else if (instModeId == "UV" && g_bands.size() == 1) g_bands[0] = (toInt(filterNum)); if (g_dark) { if (darkFiles.size() == 0 || darkFiles[0] =="Default" || darkFiles[0].length() == 0) { darkFiles.resize(2); double temp = (double) inst["MiddleTemperatureFpa"]; double time = iTime(inst["StartTime"][0]).Et(); QString darkFile = "$lro/calibration/wac_darks/WAC_" + instModeId; if (instModeId == "BW") darkFile += "_" + filter + "_Mode" + mode; darkFile += "_Offset" + offset + "_*C_*T_Dark.????.cub"; GetDark (darkFile, temp, time, g_darkCube1, g_darkCube2, g_temp1, g_temp2, darkFiles[0], darkFiles[1]); } else if (darkFiles.size() == 1) { CopyCubeIntoBuffer(darkFiles[0], g_darkCube1); g_temp1 = 0.0; g_darkCube2 = new Buffer(*g_darkCube1); g_temp2 = g_temp1; } else { CopyCubeIntoBuffer(darkFiles[0], g_darkCube1); int index = darkFiles[0].lastIndexOf("_"); g_temp1 = IString(darkFiles[0].mid( darkFiles[0].lastIndexOf("_", index-1), index)).ToDouble(); CopyCubeIntoBuffer(darkFiles[1], g_darkCube2); index = darkFiles[1].lastIndexOf("_"); g_temp2 = IString(darkFiles[1].mid( darkFiles[1].lastIndexOf("_", index-1), index)).ToDouble(); } } if (g_flatfield) { if (flatFile.toLower() == "default" || flatFile.length() == 0) { flatFile = "$lro/calibration/wac_flats/WAC_" + instModeId; if (instModeId == "BW") flatFile += "_" + filter + "_Mode" + mode; flatFile += "_Flatfield.????.cub"; } CopyCubeIntoBuffer(flatFile, g_flatCube); // invert the flat-field data here so we don't have to divide for every pixel of the wac for (int i = 0; i < g_flatCube->size(); i++) { (*g_flatCube)[i] = 1.0 / (*g_flatCube)[i]; } } PvlKeyword responsivity; if (g_radiometric) { Isis::PvlKeyword &bands = icube->label()->findGroup("BandBin", Pvl::Traverse).findKeyword("FilterNumber"); if (radFile.toLower() == "default" || radFile.length() == 0) radFile = "$lro/calibration/WAC_RadiometricResponsivity.????.pvl"; FileName radFileName(radFile); if (radFileName.isVersioned()) radFileName = radFileName.highestVersion(); if (!radFileName.fileExists()) { QString msg = radFile + " does not exist."; throw IException(IException::User, msg, _FILEINFO_); } Pvl radPvl(radFileName.expanded()); if (g_iof) { responsivity = radPvl["IOF"]; for (int i = 0; i < bands.size(); i++) g_iofResponsivity.push_back(toDouble(responsivity[toInt(bands[i]) - 1])); try { iTime startTime((QString) inst["StartTime"]); double etStart = startTime.Et(); // Get the distance between the Moon and the Sun at the given time in // Astronomical Units (AU) QString bspKernel1 = p.MissionData("lro", "/kernels/tspk/moon_pa_de421_1900-2050.bpc", false); QString bspKernel2 = p.MissionData("lro", "/kernels/tspk/de421.bsp", false); furnsh_c(bspKernel1.toAscii().data()); furnsh_c(bspKernel2.toAscii().data()); QString pckKernel1 = p.MissionData("base", "/kernels/pck/pck?????.tpc", true); QString pckKernel2 = p.MissionData("lro", "/kernels/pck/moon_080317.tf", false); QString pckKernel3 = p.MissionData("lro", "/kernels/pck/moon_assoc_me.tf", false); furnsh_c(pckKernel1.toAscii().data()); furnsh_c(pckKernel2.toAscii().data()); furnsh_c(pckKernel3.toAscii().data()); double sunpos[6], lt; spkezr_c("sun", etStart, "MOON_ME", "LT+S", "MOON", sunpos, <); g_solarDistance = vnorm_c(sunpos) / KM_PER_AU; unload_c(bspKernel1.toAscii().data()); unload_c(bspKernel2.toAscii().data()); unload_c(pckKernel1.toAscii().data()); unload_c(pckKernel2.toAscii().data()); unload_c(pckKernel3.toAscii().data()); } catch (IException &e) { QString msg = "Can not find necessary SPICE kernels for converting to IOF"; throw IException(e, IException::User, msg, _FILEINFO_); } } else { responsivity = radPvl["Radiance"]; for (int i = 0; i < bands.size(); i++) g_radianceResponsivity.push_back(toDouble(responsivity[toInt(bands[i]) - 1])); } } if (g_specpix) { if (specpixFile.toLower() == "default" || specpixFile.length() == 0) { specpixFile = "$lro/calibration/wac_masks/WAC_" + instModeId; double temp = (double) inst["MiddleTemperatureFpa"]; if (instModeId == "BW") specpixFile += "_" + filter + "_Mode" + mode; specpixFile += "_*C_SpecialPixels.????.cub"; GetMask(specpixFile, temp, g_specpixCube); } else CopyCubeIntoBuffer(specpixFile, g_specpixCube); } if (g_temprature) { if (tempFile.toLower() == "default" || tempFile.length() == 0) tempFile = "$lro/calibration/WAC_TempratureConstants.????.pvl"; FileName tempFileName(tempFile); if (tempFileName.isVersioned()) tempFileName = tempFileName.highestVersion(); if (!tempFileName.fileExists()) { QString msg = tempFile + " does not exist."; throw IException(IException::User, msg, _FILEINFO_); } Isis::PvlKeyword &bands = icube->label()->findGroup("BandBin", Pvl::Traverse).findKeyword("FilterNumber"); Pvl tempPvl(tempFileName.expanded()); for (int b = 0; b < bands.size(); b++){ g_TempratureConstants[g_bands[b]][0]=toDouble(tempPvl[bands[b]][0]); g_TempratureConstants[g_bands[b]][1]=toDouble(tempPvl[bands[b]][1]); } } if (instModeId == "BW") { if (mode == "1" || mode == "0") p.SetBrickSize(NO_POLAR_MODE_SAMPLES, VIS_LINES, (int)min(BW_BANDS, g_bands.size())); else p.SetBrickSize(POLAR_MODE_SAMPLES, VIS_LINES, (int)min(BW_BANDS, g_bands.size())); } else if (instModeId == "COLOR") { p.SetBrickSize(NO_POLAR_MODE_SAMPLES, VIS_LINES, (int)min(COLOR_BANDS, g_bands.size())); } else if (instModeId == "UV") { p.SetBrickSize(UV_SAMPLES, UV_LINES, (int)min(UV_BANDS, g_bands.size())); } g_exposure = inst["ExposureDuration"]; Cube *ocube = p.SetOutputCube("TO"); p.ProcessCube(Calibrate, false); // Add an output group with the appropriate information PvlGroup calgrp("Radiometry"); if (g_dark) { PvlKeyword darks("DarkFiles"); darks.addValue(darkFiles[0]); if (darkFiles.size() > 1) darks.addValue(darkFiles[1]); calgrp += darks; } if (g_flatfield) calgrp += PvlKeyword("FlatFile", flatFile); if (g_radiometric) { PvlKeyword vals("ResponsivityValues"); if (g_iof) { calgrp += PvlKeyword("RadiometricType", "IOF"); for (unsigned int i=0; i< g_iofResponsivity.size(); i++) vals.addValue(toString(g_iofResponsivity[i])); } else { calgrp += PvlKeyword("RadiometricType", "AbsoluteRadiance"); for (unsigned int i=0; i< g_radianceResponsivity.size(); i++) vals.addValue(toString(g_radianceResponsivity[i])); } calgrp += vals; calgrp += PvlKeyword("SolarDistance", toString(g_solarDistance)); } if (g_specpix) calgrp += PvlKeyword("SpecialPixelsFile", specpixFile); ocube->putGroup(calgrp); }
void IsisMain() { const QString caminfo_program = "caminfo"; UserInterface &ui = Application::GetUserInterface(); QList< QPair<QString, QString> > *general = NULL, *camstats = NULL, *statistics = NULL; BandGeometry *bandGeom = NULL; // Get input filename FileName in = ui.GetFileName("FROM"); // Get the format QString sFormat = ui.GetAsString("FORMAT"); // if true then run spiceinit, xml default is FALSE // spiceinit will use system kernels if(ui.GetBoolean("SPICE")) { QString parameters = "FROM=" + in.expanded(); ProgramLauncher::RunIsisProgram("spiceinit", parameters); } Process p; Cube *incube = p.SetInputCube("FROM"); // General data gathering general = new QList< QPair<QString, QString> >; general->append(MakePair("Program", caminfo_program)); general->append(MakePair("IsisVersion", Application::Version())); general->append(MakePair("RunDate", iTime::CurrentGMT())); general->append(MakePair("IsisId", SerialNumber::Compose(*incube))); general->append(MakePair("From", in.baseName() + ".cub")); general->append(MakePair("Lines", toString(incube->lineCount()))); general->append(MakePair("Samples", toString(incube->sampleCount()))); general->append(MakePair("Bands", toString(incube->bandCount()))); // Run camstats on the entire image (all bands) // another camstats will be run for each band and output // for each band. if(ui.GetBoolean("CAMSTATS")) { camstats = new QList< QPair<QString, QString> >; QString filename = ui.GetAsString("FROM"); int sinc = ui.GetInteger("SINC"); int linc = ui.GetInteger("LINC"); CameraStatistics stats(filename, sinc, linc); Pvl camPvl = stats.toPvl(); PvlGroup cg = camPvl.findGroup("Latitude", Pvl::Traverse); camstats->append(MakePair("MinimumLatitude", cg["latitudeminimum"][0])); camstats->append(MakePair("MaximumLatitude", cg["latitudemaximum"][0])); cg = camPvl.findGroup("Longitude", Pvl::Traverse); camstats->append(MakePair("MinimumLongitude", cg["longitudeminimum"][0])); camstats->append(MakePair("MaximumLongitude", cg["longitudemaximum"][0])); cg = camPvl.findGroup("Resolution", Pvl::Traverse); camstats->append(MakePair("MinimumResolution", cg["resolutionminimum"][0])); camstats->append(MakePair("MaximumResolution", cg["resolutionmaximum"][0])); cg = camPvl.findGroup("PhaseAngle", Pvl::Traverse); camstats->append(MakePair("MinimumPhase", cg["phaseminimum"][0])); camstats->append(MakePair("MaximumPhase", cg["phasemaximum"][0])); cg = camPvl.findGroup("EmissionAngle", Pvl::Traverse); camstats->append(MakePair("MinimumEmission", cg["emissionminimum"][0])); camstats->append(MakePair("MaximumEmission", cg["emissionmaximum"][0])); cg = camPvl.findGroup("IncidenceAngle", Pvl::Traverse); camstats->append(MakePair("MinimumIncidence", cg["incidenceminimum"][0])); camstats->append(MakePair("MaximumIncidence", cg["incidencemaximum"][0])); cg = camPvl.findGroup("LocalSolarTime", Pvl::Traverse); camstats->append(MakePair("LocalTimeMinimum", cg["localsolartimeMinimum"][0])); camstats->append(MakePair("LocalTimeMaximum", cg["localsolartimeMaximum"][0])); } // Compute statistics for entire cube if(ui.GetBoolean("STATISTICS")) { statistics = new QList< QPair<QString, QString> >; LineManager iline(*incube); Statistics stats; Progress progress; progress.SetText("Statistics..."); progress.SetMaximumSteps(incube->lineCount()*incube->bandCount()); progress.CheckStatus(); iline.SetLine(1); for(; !iline.end() ; iline.next()) { incube->read(iline); stats.AddData(iline.DoubleBuffer(), iline.size()); progress.CheckStatus(); } // Compute stats of entire cube double nPixels = stats.TotalPixels(); double nullpercent = (stats.NullPixels() / (nPixels)) * 100; double hispercent = (stats.HisPixels() / (nPixels)) * 100; double hrspercent = (stats.HrsPixels() / (nPixels)) * 100; double lispercent = (stats.LisPixels() / (nPixels)) * 100; double lrspercent = (stats.LrsPixels() / (nPixels)) * 100; // Statitics output for band statistics->append(MakePair("MeanValue", toString(stats.Average()))); statistics->append(MakePair("StandardDeviation", toString(stats.StandardDeviation()))); statistics->append(MakePair("MinimumValue", toString(stats.Minimum()))); statistics->append(MakePair("MaximumValue", toString(stats.Maximum()))); statistics->append(MakePair("PercentHIS", toString(hispercent))); statistics->append(MakePair("PercentHRS", toString(hrspercent))); statistics->append(MakePair("PercentLIS", toString(lispercent))); statistics->append(MakePair("PercentLRS", toString(lrspercent))); statistics->append(MakePair("PercentNull", toString(nullpercent))); statistics->append(MakePair("TotalPixels", toString(stats.TotalPixels()))); } bool getFootBlob = ui.GetBoolean("USELABEL"); bool doGeometry = ui.GetBoolean("GEOMETRY"); bool doPolygon = ui.GetBoolean("POLYGON"); if(doGeometry || doPolygon || getFootBlob) { Camera *cam = incube->camera(); QString incType = ui.GetString("INCTYPE"); int polySinc, polyLinc; if(doPolygon && incType.toUpper() == "VERTICES") { ImagePolygon poly; poly.initCube(*incube); polySinc = polyLinc = (int)(0.5 + (((poly.validSampleDim() * 2) + (poly.validLineDim() * 2) - 3.0) / ui.GetInteger("NUMVERTICES"))); } else if (incType.toUpper() == "LINCSINC"){ if(ui.WasEntered("POLYSINC")) { polySinc = ui.GetInteger("POLYSINC"); } else { polySinc = (int)(0.5 + 0.10 * incube->sampleCount()); if(polySinc == 0) polySinc = 1; } if(ui.WasEntered("POLYLINC")) { polyLinc = ui.GetInteger("POLYLINC"); } else { polyLinc = (int)(0.5 + 0.10 * incube->lineCount()); if(polyLinc == 0) polyLinc = 1; } } else { QString msg = "Invalid INCTYPE option[" + incType + "]"; throw IException(IException::Programmer, msg, _FILEINFO_); } bandGeom = new BandGeometry(); bandGeom->setSampleInc(polySinc); bandGeom->setLineInc(polyLinc); bandGeom->setMaxIncidence(ui.GetDouble("MAXINCIDENCE")); bandGeom->setMaxEmission(ui.GetDouble("MAXEMISSION")); bool precision = ui.GetBoolean("INCREASEPRECISION"); if (getFootBlob) { // Need to read history to obtain parameters that were used to // create the footprint History hist("IsisCube", in.expanded()); Pvl pvl = hist.ReturnHist(); PvlObject::PvlObjectIterator objIter; bool found = false; PvlGroup fpgrp; for (objIter=pvl.endObject()-1; objIter>=pvl.beginObject(); objIter--) { if (objIter->name().toUpper() == "FOOTPRINTINIT") { found = true; fpgrp = objIter->findGroup("UserParameters"); break; } } if (!found) { QString msg = "Footprint blob was not found in input image history"; throw IException(IException::User, msg, _FILEINFO_); } QString prec = (QString)fpgrp.findKeyword("INCREASEPRECISION"); prec = prec.toUpper(); if (prec == "TRUE") { precision = true; } else { precision = false; } QString inctype = (QString)fpgrp.findKeyword("INCTYPE"); inctype = inctype.toUpper(); if (inctype == "LINCSINC") { int linc = fpgrp.findKeyword("LINC"); int sinc = fpgrp.findKeyword("SINC"); bandGeom->setSampleInc(sinc); bandGeom->setLineInc(linc); } else { int vertices = fpgrp.findKeyword("NUMVERTICES"); int lincsinc = (int)(0.5 + (((incube->sampleCount() * 2) + (incube->lineCount() * 2) - 3.0) / vertices)); bandGeom->setSampleInc(lincsinc); bandGeom->setLineInc(lincsinc); } if (fpgrp.hasKeyword("MAXINCIDENCE")) { double maxinc = fpgrp.findKeyword("MAXINCIDENCE"); bandGeom->setMaxIncidence(maxinc); } if (fpgrp.hasKeyword("MAXEMISSION")) { double maxema = fpgrp.findKeyword("MAXEMISSION"); bandGeom->setMaxEmission(maxema); } } bandGeom->collect(*cam, *incube, doGeometry, doPolygon, getFootBlob, precision); // Check if the user requires valid image center geometry if(ui.GetBoolean("VCAMERA") && (!bandGeom->hasCenterGeometry())) { QString msg = "Image center does not project in camera model"; throw IException(IException::Unknown, msg, _FILEINFO_); } } if(sFormat.toUpper() == "PVL") GeneratePVLOutput(incube, general, camstats, statistics, bandGeom); else GenerateCSVOutput(incube, general, camstats, statistics, bandGeom); // Clean the data delete general; general = NULL; if(camstats) { delete camstats; camstats = NULL; } if(statistics) { delete statistics; statistics = NULL; } if(bandGeom) { delete bandGeom; bandGeom = NULL; } }
// Main Program void IsisMain() { vector<double> filter; int rowcol; // how many rows or cols per band bool normalizeUsingAverage; // mult/sub using average or median? int totalBands; // Used for filtering the initial cubenorm averages and median values int filtsize; bool pause_crop; int channel; // ERROR CHECK: The user must specify at least the TO or STATS // parameters. UserInterface &ui = Application::GetUserInterface(); if(!(ui.WasEntered("TO")) && !(ui.WasEntered("STATS"))) { QString msg = "User must specify a TO and/or STATS file."; throw IException(IException::User, msg, _FILEINFO_); } // We will be processing by tile. ProcessByTile p; // Setup the input cube; // Obtain information from the input file Cube *icube = p.SetInputCube("FROM"); totalSamples = icube->sampleCount(); totalLines = icube->lineCount(); totalBands = icube->bandCount(); channel = icube->group("Instrument")["ChannelNumber"]; // Cubenorm New Version Flag bool bNewVersion = ui.GetBoolean("NEW_VERSION"); // Setup the tile size for columnar processing p.SetTileSize(1, totalLines); rowcol = totalSamples; // Gather statistics from the configured source if(!bNewVersion && ui.GetString("STATSOURCE") == "CUBE") { p.StartProcess(getStats); } else if(ui.GetString("STATSOURCE") == "TABLE") { tableIn(ui.GetFileName("FROMSTATS")); } else { PVLIn(ui.GetFileName("FROMSTATS")); } // Check to make sure the first vector has as many elements as the last // vector, and that there is a vector element for each row/col if(!bNewVersion && band.size() != (unsigned int)(rowcol * totalBands)) { QString message = "You have entered an invalid input file " + ui.GetFileName("FROMSTATS"); throw IException(IException::Io, message, _FILEINFO_); } // Get the information needed to filter the statistics filtsize = ui.GetInteger("FILTER"); pause_crop = ui.GetBoolean("PAUSECROP"); if(bNewVersion) { CorrectCubenormStats(filtsize, pause_crop, channel, ui.GetString("HIGHPASS_MODE")); } else { // Filter the column averages filter = average; filterStats(filter, filtsize, pause_crop, channel); average = filter; // Filter the column medians filter = median; filterStats(filter, filtsize, pause_crop, channel); median = filter; } // If a STATS file was specified then create statistics file if(ui.WasEntered("STATS")) { QString op = ui.GetString("FORMAT"); if(op == "PVL"){ pvlOut(ui.GetFileName("STATS")); } if(op == "TABLE"){ tableOut(ui.GetFileName("STATS")); } } // Update the statistics vectors before creating the output // file. Now get the statistics for each column normalizeUsingAverage = ui.GetString("NORMALIZER") == "AVERAGE"; if(normalizeUsingAverage) { normalizer = average; } else { normalizer = median; } // If an output file was specified then normalize the cube if(ui.WasEntered("TO")) { // Before creating a normalized cube check to see if there // are any column averages less than or equal to zero. if(ui.GetString("MODE") == "MULTIPLY") { for(unsigned int i = 0; i < band.size(); i++) { if(IsValidPixel(normalizer[i]) && normalizer[i] <= 0.0) { QString msg = "Cube file can not be normalized with [MULTIPLY] "; msg += "option, some column averages <= 0.0"; throw IException(IException::User, msg, _FILEINFO_); } } } // Setup the output file and apply the coefficients by either // subtracting or multipling them p.SetOutputCube("TO"); // Should we preserve the average/median of the input image??? if(ui.GetBoolean("PRESERVE")) { if(ui.GetString("MODE") == "SUBTRACT") { keepSame(totalBands, rowcol, SUBTRACT); } else { keepSame(totalBands, rowcol, DIVIDE); } } // Process based on the mode if(ui.GetString("MODE") == "SUBTRACT") { p.StartProcess(subtract); } else { p.StartProcess(multiply); } } // Cleanup p.EndProcess(); stddev.clear(); validpixels.clear(); minimum.clear(); maximum.clear(); band.clear(); element.clear(); median.clear(); average.clear(); normalizer.clear(); filter.clear(); }
void IsisMain() { // Open the match cube and get the camera model on it ProcessRubberSheet m; Cube *mcube = m.SetInputCube("MATCH"); Cube *ocube = m.SetOutputCube("TO"); // Set up the default reference band to the middle of the cube // If we have even bands it will be close to the middle int referenceBand = ocube->bandCount(); referenceBand += (referenceBand % 2); referenceBand /= 2; // See if the user wants to override the reference band UserInterface &ui = Application::GetUserInterface(); if(ui.WasEntered("REFBAND")) { referenceBand = ui.GetInteger("REFBAND"); } // Using the Camera method out of the object opack will not work, because the // filename required by the Camera is not passed by the process class in this // case. Use the CameraFactory to create the Camera instead to get around this // problem. Camera *outcam = CameraFactory::Create(*(mcube->label())); // Set the reference band we want to match PvlGroup instgrp = mcube->group("Instrument"); if(!outcam->IsBandIndependent()) { PvlKeyword rBand("ReferenceBand", toString(referenceBand)); rBand.addComment("# All bands are aligned to reference band"); instgrp += rBand; mcube->putGroup(instgrp); delete outcam; outcam = NULL; } // Only recreate the output camera if it was band dependent if(outcam == NULL) outcam = CameraFactory::Create(*(mcube->label())); // We might need the instrument group later, so get a copy before clearing the input // cubes. m.ClearInputCubes(); Cube *icube = m.SetInputCube("FROM"); incam = icube->camera(); // Set up the transform object which will simply map // output line/samps -> output lat/lons -> input line/samps Transform *transform = new cam2cam(icube->sampleCount(), icube->lineCount(), incam, ocube->sampleCount(), ocube->lineCount(), outcam); // Add the reference band to the output if necessary ocube->putGroup(instgrp); // Set up the interpolator Interpolator *interp = NULL; 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); } // See if we need to deal with band dependent camera models if(!incam->IsBandIndependent()) { m.BandChange(BandChange); } // Warp the cube m.StartProcess(*transform, *interp); m.EndProcess(); // Cleanup delete transform; delete interp; }
void IsisMain() { UserInterface &ui = Application::GetUserInterface(); Process p; // Get the histogram Cube *icube = p.SetInputCube("FROM"); double validMin = Isis::ValidMinimum; double validMax = Isis::ValidMaximum; if(ui.WasEntered("VALIDMIN")) { validMin = ui.GetDouble("VALIDMIN"); } if(ui.WasEntered("VALIDMAX")) { validMax = ui.GetDouble("VALIDMAX"); } // Set a global Pvl for storing results Pvl mainpvl; // Get the number of bands to process int bandcount = icube->bandCount(); for (int i = 1; i <= bandcount; i++) { Histogram *stats = icube->histogram(i, validMin, validMax); // Construct a label with the results PvlGroup results("Results"); results += PvlKeyword("From", icube->fileName()); results += PvlKeyword("Band", toString(icube->physicalBand(i))); if(stats->ValidPixels() != 0) { results += PvlKeyword("Average", toString(stats->Average())); results += PvlKeyword("StandardDeviation", toString(stats->StandardDeviation())); results += PvlKeyword("Variance", toString(stats->Variance())); // These statistics only worked on a histogram results += PvlKeyword("Median", toString(stats->Median())); results += PvlKeyword("Mode", toString(stats->Mode())); results += PvlKeyword("Skew", toString(stats->Skew())); results += PvlKeyword("Minimum", toString(stats->Minimum())); results += PvlKeyword("Maximum", toString(stats->Maximum())); results += PvlKeyword("Sum", toString(stats->Sum())); } results += PvlKeyword("TotalPixels", toString(stats->TotalPixels())); results += PvlKeyword("ValidPixels", toString(stats->ValidPixels())); results += PvlKeyword("OverValidMaximumPixels", toString(stats->OverRangePixels())); results += PvlKeyword("UnderValidMinimumPixels", toString(stats->UnderRangePixels())); results += PvlKeyword("NullPixels", toString(stats->NullPixels())); results += PvlKeyword("LisPixels", toString(stats->LisPixels())); results += PvlKeyword("LrsPixels", toString(stats->LrsPixels())); results += PvlKeyword("HisPixels", toString(stats->HisPixels())); results += PvlKeyword("HrsPixels", toString(stats->HrsPixels())); mainpvl.addGroup(results); delete stats; // Write the results to the log Application::Log(results); } // Write the results to the output file if the user specified one if(ui.WasEntered("TO")) { QString outFile = FileName(ui.GetFileName("TO")).expanded(); bool exists = FileName(outFile).fileExists(); bool append = ui.GetBoolean("APPEND"); ofstream os; bool writeHeader = false; //write the results in the requested format. if(ui.GetString("FORMAT") == "PVL") { if(append) { mainpvl.append(outFile); } else { mainpvl.write(outFile); } } else { //if the format was not PVL, write out a flat file. if(append) { os.open(outFile.toAscii().data(), ios::app); if(!exists) { writeHeader = true; } } else { os.open(outFile.toAscii().data(), ios::out); writeHeader = true; } if(writeHeader) { for(int i = 0; i < mainpvl.group(0).keywords(); i++) { os << mainpvl.group(0)[i].name(); if( i < mainpvl.group(0).keywords() - 1 ) { os << ","; } } os << endl; } for(int i = 0; i < mainpvl.groups(); i++) { for (int j = 0; j < mainpvl.group(i).keywords(); j++) { os << (QString)mainpvl.group(i)[j]; if(j < mainpvl.group(i).keywords() - 1) { os << ","; } } os << endl; } } } }
/** * Set the output cube to specified file name and specified input images * and output attributes */ Isis::Cube *ProcessMapMosaic::SetOutputCube(FileList &propagationCubes, CubeAttributeOutput &oAtt, const QString &mosaicFile) { int bands = 0; double xmin = DBL_MAX; double xmax = -DBL_MAX; double ymin = DBL_MAX; double ymax = -DBL_MAX; double slat = DBL_MAX; double elat = -DBL_MAX; double slon = DBL_MAX; double elon = -DBL_MAX; Projection *proj = NULL; if (propagationCubes.size() < 1) { QString msg = "The list does not contain any data"; throw IException(IException::Programmer, msg, _FILEINFO_); } for (int i = 0; i < propagationCubes.size(); i++) { // Open the cube and get the maximum number of band in all cubes Cube cube; cube.open(propagationCubes[i].toString()); bands = max(bands, cube.bandCount()); // See if the cube has a projection and make sure it matches // previous input cubes Projection *projNew = Isis::ProjectionFactory::CreateFromCube(*(cube.label())); if ((proj != NULL) && (*proj != *projNew)) { QString msg = "Mapping groups do not match between cubes [" + propagationCubes[0].toString() + "] and [" + propagationCubes[i].toString() + "]"; throw IException(IException::User, msg, _FILEINFO_); } // Figure out the x/y range as it may be needed later double x = projNew->ToProjectionX(0.5); double y = projNew->ToProjectionY(0.5); if (x < xmin) xmin = x; if (y < ymin) ymin = y; if (x > xmax) xmax = x; if (y > ymax) ymax = y; x = projNew->ToProjectionX(cube.sampleCount() + 0.5); y = projNew->ToProjectionY(cube.lineCount() + 0.5); if (x < xmin) xmin = x; if (y < ymin) ymin = y; if (x > xmax) xmax = x; if (y > ymax) ymax = y; slat = min(slat, projNew->MinimumLatitude()); elat = max(elat, projNew->MaximumLatitude()); slon = min(slon, projNew->MinimumLongitude()); elon = max(elon, projNew->MaximumLongitude()); // Cleanup cube.close(); if (proj) delete proj; proj = projNew; } if (proj) delete proj; return SetOutputCube(propagationCubes[0].toString(), xmin, xmax, ymin, ymax, slat, elat, slon, elon, bands, oAtt, mosaicFile); }
void IsisMain() { latLonGrid = NULL; // We will be processing by line ProcessByLine p; Cube *icube = p.SetInputCube("FROM"); UserInterface &ui = Application::GetUserInterface(); QString mode = ui.GetString("MODE"); outline = ui.GetBoolean("OUTLINE"); ticks = ui.GetBoolean("TICKS"); if (ticks) { tickSize = ui.GetInteger("TICKSIZE") / 2; diagonalTicks = ui.GetBoolean("DIAGONALTICKS"); } lineWidth = ui.GetInteger("LINEWIDTH") / 2; QString bval = ui.GetString("BKGNDVALUE").toUpper(); image = (bval == "IMAGE"); bkgndValue = Null; if (bval == "HRS") { bkgndValue = Hrs; } else if (bval == "LRS") { bkgndValue = Lrs; } else if (bval == "DN") { bkgndValue = ui.GetDouble("BKGNDDNVALUE"); } QString lval = ui.GetString("LINEVALUE").toUpper(); if (lval == "HRS") { lineValue = Hrs; } else if (lval == "LRS") { lineValue = Lrs; } else if (lval == "NULL") { lineValue = Null; } else if (lval == "DN") { if (ui.WasEntered("DNVALUE")) { lineValue = ui.GetDouble("DNVALUE"); } else { throw IException(IException::User, "Must enter value in DNVALUE", _FILEINFO_); } } else { IString msg = "Invalid LINEVALUE string [" + ui.GetString("LINEVALUE"); msg += "], must be one of HRS, LRS, NULL, or DN."; throw IException(IException::User, msg, _FILEINFO_); } inputSamples = icube->sampleCount(); inputLines = icube->lineCount(); // Line & sample based grid if (mode == "IMAGE") { p.SetOutputCube("TO"); baseLine = ui.GetInteger("BASELINE"); baseSample = ui.GetInteger("BASESAMPLE"); lineInc = ui.GetInteger("LINC"); sampleInc = ui.GetInteger("SINC"); p.StartProcess(imageGrid); p.EndProcess(); } // Lat/Lon based grid else { CubeAttributeOutput oatt("+32bit"); p.SetOutputCube(ui.GetFileName("TO"), oatt, icube->sampleCount(), icube->lineCount(), icube->bandCount()); UniversalGroundMap *gmap = new UniversalGroundMap(*icube, UniversalGroundMap::ProjectionFirst); latLonGrid = new GroundGrid(gmap, ticks, icube->sampleCount(), icube->lineCount()); baseLat = Latitude(ui.GetDouble("BASELAT"), *latLonGrid->GetMappingGroup(), Angle::Degrees); baseLon = Longitude(ui.GetDouble("BASELON"), *latLonGrid->GetMappingGroup(), Angle::Degrees); latInc = Angle(ui.GetDouble("LATINC"), Angle::Degrees); lonInc = Angle(ui.GetDouble("LONINC"), Angle::Degrees); Progress progress; progress.SetText("Calculating Grid"); Latitude minLat, maxLat; if (ui.WasEntered("MINLAT")) minLat = Latitude(ui.GetDouble("MINLAT"), *latLonGrid->GetMappingGroup(), Angle::Degrees); if (ui.WasEntered("MAXLAT")) maxLat = Latitude(ui.GetDouble("MAXLAT"), *latLonGrid->GetMappingGroup(), Angle::Degrees); Longitude minLon, maxLon; if (ui.WasEntered("MINLON")) minLon = Longitude(ui.GetDouble("MINLON"), *latLonGrid->GetMappingGroup(), Angle::Degrees); if (ui.WasEntered("MAXLON")) maxLon = Longitude(ui.GetDouble("MAXLON"), *latLonGrid->GetMappingGroup(), Angle::Degrees); latLonGrid->SetGroundLimits(minLat, minLon, maxLat, maxLon); latLonGrid->CreateGrid(baseLat, baseLon, latInc, lonInc, &progress); if (ui.GetBoolean("BOUNDARY")) latLonGrid->WalkBoundary(); p.StartProcess(groundGrid); p.EndProcess(); delete latLonGrid; latLonGrid = NULL; delete gmap; gmap = NULL; } }
/** * Set the output cube to specified file name and specified input images * and output attributes and lat,lons */ Isis::Cube *ProcessMapMosaic::SetOutputCube(FileList &propagationCubes, double slat, double elat, double slon, double elon, CubeAttributeOutput &oAtt, const QString &mosaicFile) { if (propagationCubes.size() < 1) { QString msg = "The list does not contain any data"; throw IException(IException::Programmer, msg, _FILEINFO_); } int samples, lines, bands = 0; Pvl label; label.read(propagationCubes[0].toString()); PvlGroup mGroup = label.findGroup("Mapping", Pvl::Traverse); mGroup.addKeyword(PvlKeyword("MinimumLatitude", toString(slat)), Pvl::Replace); mGroup.addKeyword(PvlKeyword("MaximumLatitude", toString(elat)), Pvl::Replace); mGroup.addKeyword(PvlKeyword("MinimumLongitude", toString(slon)), Pvl::Replace); mGroup.addKeyword(PvlKeyword("MaximumLongitude", toString(elon)), Pvl::Replace); if (mGroup.hasKeyword("UpperLeftCornerX")) mGroup.deleteKeyword("UpperLeftCornerX"); if (mGroup.hasKeyword("UpperLeftCornerY")) mGroup.deleteKeyword("UpperLeftCornerY"); Pvl mapPvl; mapPvl += mGroup; // Use CreateForCube because our range differs from any of the cubes (manually specified) Projection *proj = Isis::ProjectionFactory::CreateForCube(mapPvl, samples, lines, false); double xmin, xmax, ymin, ymax; proj->XYRange(xmin, xmax, ymin, ymax); // The xmin/ymax should be rounded for the labels xmin = mapPvl.findGroup("Mapping")["UpperLeftCornerX"]; ymax = mapPvl.findGroup("Mapping")["UpperLeftCornerY"]; for (int i = 0; i < propagationCubes.size(); i++) { Cube cube; cube.open(propagationCubes[i].toString()); bands = max(cube.bandCount(), bands); // See if the cube has a projection and make sure it matches // previous input cubes Projection *projNew = Isis::ProjectionFactory::CreateFromCube(*(cube.label())); if (proj == NULL) { } else if (*proj != *projNew) { QString msg = "Mapping groups do not match between cube [" + propagationCubes[i].toString() + "] and [" + propagationCubes[0].toString() + "]"; throw IException(IException::User, msg, _FILEINFO_); } if (proj) delete proj; proj = projNew; } if (proj) delete proj; return SetOutputCube(propagationCubes[0].toString(), xmin, xmax, ymin, ymax, slat, elat, slon, elon, bands, oAtt, mosaicFile); }
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; }
void IsisMain(){ UserInterface &ui = Application::GetUserInterface(); //We will process by line ProcessByLine p; Cube* cubeptr = p.SetInputCube("FROM"); // Histogram* histptr = (cubeptr -> Histogram()); double max = ui.GetDouble("MAXVAL"); double min = ui.GetDouble("MINVAL"); /* A histogram is made from the input cube, as the default min of the bit2bit output is at .5% of the data range, and the default max is at 99.5% */ Histogram* histptr = cubeptr -> histogram(); double maxper = histptr -> Percent(ui.GetDouble("MAXPER")); double minper = histptr -> Percent(ui.GetDouble("MINPER")); double validMin = Isis::ValidMinimum; double validMax = Isis::ValidMaximum; // Set properties MIN,MAX, and PixelType for output cube CubeAttributeOutput outputProperties; if(ui.GetString("CLIP") == "PERCENT"){ outputProperties.setMaximum(maxper); outputProperties.setMinimum(minper); validMax = maxper; validMin = minper; } else{ outputProperties.setMaximum(max); outputProperties.setMinimum(min); validMax = max; validMin = min; } if(ui.GetString("BITTYPE")=="8BIT"){ outputProperties.setPixelType(UnsignedByte); } else if(ui.GetString("BITTYPE")=="16BIT"){ outputProperties.setPixelType(SignedWord); } else { outputProperties.setPixelType(Real); } if(ui.GetBoolean("STATS")) { //! Run extended statistics Cube* ocubeptr = p.SetOutputCube (ui.GetFileName("TO"),outputProperties, cubeptr->sampleCount(),cubeptr->lineCount(), cubeptr->bandCount()); p.StartProcess(populate); Histogram* ohistptr = (ocubeptr -> histogram(1,validMin,validMax)); int iLrs = histptr -> LrsPixels(); int iHrs = histptr -> HrsPixels(); int iNull = histptr -> NullPixels(); int oLrs = ohistptr -> LrsPixels(); int oHrs = ohistptr -> HrsPixels(); int oNull = ohistptr -> NullPixels(); double invalid_pi = (( (histptr -> TotalPixels()) - (histptr -> ValidPixels()))*100.0) / ((histptr -> TotalPixels())*1.0); double invalid_po = (( (ohistptr -> TotalPixels()) - (ohistptr -> ValidPixels()))*100.0) / ((ohistptr -> TotalPixels())*1.0); p.EndProcess(); //!Write bit2bit summary to the screen cout << "\n\nIN:\n"; cout << " LRS:\t\t" << iLrs << endl; cout << " HRS:\t\t" << iHrs << endl; cout << " NULL:\t\t" << iNull << endl; cout << " Invalid Pixel %:\t\t" << invalid_pi << endl; cout << "\nOUT:\n\n"; cout << " Data Range:\t\t"; cout << validMin << " < x < " << validMax << endl; cout << " LRS:\t\t" << oLrs << endl; cout << " HRS:\t\t" << oHrs << endl; cout << " NULL:\t\t" << oNull << endl; cout << " Invalid Pixel %:\t\t" << invalid_po << endl<< endl; //!Write bit2bit summary to print.prt logfile PvlGroup results("bit2bit_Results"); results += PvlKeyword ("INPUT_LRS",toString(iLrs)); results += PvlKeyword ("INPUT_HRS",toString(iHrs)); results += PvlKeyword ("INPUT_NULL",toString(iNull)); results += PvlKeyword ("INPUT_INVALID_PERCENT",toString(invalid_pi)); results += PvlKeyword ("OUTPUT_MIN",toString(validMin)); results += PvlKeyword ("OUTPUT_MAX",toString(validMax)); results += PvlKeyword ("OUTPUT_LRS",toString(oLrs)); results += PvlKeyword ("OUTPUT_HRS",toString(oHrs)); results += PvlKeyword ("OUTPUT_NULL",toString(oNull)); results += PvlKeyword ("OUTPUT_INVALID_PERCENT",toString(invalid_po)); Application::Log(results); delete histptr; delete ohistptr; } else{ //! run minimal statistics (runs faster) int iLrs = histptr -> LrsPixels(); int iHrs = histptr -> HrsPixels(); int iNull = histptr -> NullPixels(); double invalid_pi = (( (histptr -> TotalPixels()) - (histptr -> ValidPixels()))*100.0) / ((histptr -> TotalPixels())*1.0); p.EndProcess(); //!Write bit2bit summary to the screen cout << "\n\nIN:\n"; cout << " LRS:\t\t" << iLrs << endl; cout << " HRS:\t\t" << iHrs << endl; cout << " NULL:\t\t" << iNull << endl; cout << " Invalid Pixel %:\t\t" << invalid_pi << endl; cout << "\nOUT:\n\n"; cout << " Data Range:\t\t"; cout << validMin << " < x < " << validMax << endl; //!Write bit2bit summary to print.prt logfile PvlGroup results("bit2bit_Results"); results += PvlKeyword ("INPUT_LRS",toString(iLrs)); results += PvlKeyword ("INPUT_HRS",toString(iHrs)); results += PvlKeyword ("INPUT_NULL",toString(iNull)); results += PvlKeyword ("INPUT_INVALID_PERCENT",toString(invalid_pi)); results += PvlKeyword ("OUTPUT_MIN",toString(validMin)); results += PvlKeyword ("OUTPUT_MAX",toString(validMax)); Application::Log(results); delete histptr; } }