void Stretch::Save(Isis::Pvl &pvl, QString &grpName) { PvlGroup *grp = new PvlGroup(grpName); PvlKeyword inputs("Input"); PvlKeyword outputs("Output"); for(int i = 0; i < Pairs(); i++) { inputs.addValue(toString(Input(i))); outputs.addValue(toString(Output(i))); } grp->addKeyword(inputs); grp->addKeyword(outputs); pvl.addGroup(*grp); }
// Updates existing BandBin keywords with additional values to ensure // label compilancy (which should support Camera models). It checks for the // existance of the keyword and uses its (assumed) first value to set nvals // values to a constant. If the keyword doesn't exist, it uses the default // value. void UpdateBandKey(const QString &keyname, PvlGroup &bb, const int &nvals, const QString &default_value) { QString defVal(default_value); if ( bb.hasKeyword(keyname) ) { defVal = bb[keyname][0]; } bb.addKeyword(makeKey(keyname, nvals, defVal), PvlContainer::Replace); return; }
void IsisMain() { // Create a process so we can output the noproj'd labels without overwriting Process p; // Open the user interface and get the input file and the ideal specs file UserInterface &ui = Application::GetUserInterface(); Cube *mcube, *icube; // If a MATCH cube is entered, make sure to SetInputCube it first to get the SPICE blobs // from it propagated to the TO labels // Until polygon blobs are detached without "/" don't propagate them p.PropagatePolygons(false); if((ui.WasEntered("MATCH"))) { mcube = p.SetInputCube("MATCH"); icube = p.SetInputCube("FROM"); } else { mcube = icube = p.SetInputCube("FROM"); } Camera *incam = mcube->camera(); // Extract Instrument groups from input labels for the output match and noproj'd cubes PvlGroup inst = mcube->group("Instrument"); PvlGroup fromInst = icube->group("Instrument"); QString groupName = (QString) inst["SpacecraftName"] + "/"; groupName += (QString) inst.findKeyword("InstrumentId"); // Get Ideal camera specifications FileName specs; if((ui.WasEntered("SPECS"))) { specs = ui.GetFileName("SPECS"); } else { specs = "$base/applications/noprojInstruments???.pvl"; specs = specs.highestVersion(); } Pvl idealSpecs(specs.expanded()); PvlObject obSpecs = idealSpecs.findObject("IdealInstrumentsSpecifications"); PvlGroup idealGp = obSpecs.findGroup(groupName); double transx, transy, transl, transs; transx = transy = transl = transs = 0.; if(idealGp.hasKeyword("TransX")) transx = idealGp["TransX"]; if(idealGp.hasKeyword("TransY")) transy = idealGp["TransY"]; if(idealGp.hasKeyword("ItransL")) transl = idealGp["ItransL"]; if(idealGp.hasKeyword("ItransS")) transs = idealGp["ItransS"]; int detectorSamples = mcube->sampleCount(); if(idealGp.hasKeyword("DetectorSamples")) detectorSamples = idealGp["DetectorSamples"]; int numberLines = mcube->lineCount(); int numberBands = mcube->bandCount(); if(idealGp.hasKeyword("DetectorLines")) numberLines = idealGp["DetectorLines"]; int xDepend = incam->FocalPlaneMap()->FocalPlaneXDependency(); // Get output summing mode if(ui.GetString("SOURCE") == "FROMMATCH") { LoadMatchSummingMode(); } else if(ui.GetString("SOURCE") == "FROMINPUT") { LoadInputSummingMode(); } double pixPitch = incam->PixelPitch() * ui.GetDouble("SUMMINGMODE"); detectorSamples /= (int)(ui.GetDouble("SUMMINGMODE")); // Get the user options int sampleExpansion = int((ui.GetDouble("SAMPEXP") / 100.) * detectorSamples + .5); int lineExpansion = int((ui.GetDouble("LINEEXP") / 100.) * numberLines + .5); QString instType; // Adjust translations for summing mode transl /= ui.GetDouble("SUMMINGMODE"); transs /= ui.GetDouble("SUMMINGMODE"); detectorSamples += sampleExpansion; numberLines += lineExpansion; // Determine whether this ideal camera is a line scan or framing camera and // set the instrument id and exposure int detectorLines; int expandFlag; if(incam->DetectorMap()->LineRate() != 0.0) { instType = "LINESCAN"; // Isis3 line rate is always in seconds so convert to milliseconds for the // Ideal instrument detectorLines = 1; expandFlag = 1; } else { instType = "FRAMING"; detectorLines = numberLines; expandFlag = 0; // Framing cameras don't need exposure time } // Adjust focal plane translations with line expansion for scanners since // the CCD is only 1 line if(expandFlag) { transl += lineExpansion / 2; if(xDepend == CameraFocalPlaneMap::Line) { transx -= lineExpansion / 2.*pixPitch * expandFlag; } else { transy -= lineExpansion / 2.*pixPitch * expandFlag; } } // Get the start time for parent line 1 AlphaCube alpha(*icube); double sample = alpha.BetaSample(.5); double line = alpha.BetaLine(.5); incam->SetImage(sample, line); double et = incam->time().Et(); // Get the output file name and set its attributes CubeAttributeOutput cao; // Can we do a regular label? Didn't work on 12-15-2006 cao.setLabelAttachment(Isis::DetachedLabel); // Determine the output image size from // 1) the idealInstrument pvl if there or // 2) the input size expanded by user specified percentage Cube *ocube = p.SetOutputCube("match.cub", cao, 1, 1, 1); // Extract the times and the target from the instrument group QString startTime = inst["StartTime"]; QString stopTime; if(inst.hasKeyword("StopTime")) stopTime = (QString) inst["StopTime"]; QString target = inst["TargetName"]; // rename the instrument groups inst.setName("OriginalInstrument"); fromInst.setName("OriginalInstrument"); // add it back to the IsisCube object under a new group name ocube->putGroup(inst); // and remove the version from the IsisCube Object ocube->deleteGroup("Instrument"); // Now rename the group back to the Instrument group and clear out old keywords inst.setName("Instrument"); inst.clear(); // Add keywords for the "Ideal" instrument Isis::PvlKeyword key("SpacecraftName", "IdealSpacecraft"); inst.addKeyword(key); key.setName("InstrumentId"); key.setValue("IdealCamera"); inst.addKeyword(key); key.setName("TargetName"); key.setValue(target); inst.addKeyword(key); key.setName("SampleDetectors"); key.setValue(Isis::toString(detectorSamples)); inst.addKeyword(key); key.setName("LineDetectors"); key.setValue(Isis::toString(detectorLines)); inst.addKeyword(key); key.setName("InstrumentType"); key.setValue(instType); inst.addKeyword(key); Pvl &ocubeLabel = *ocube->label(); PvlObject *naifKeywordsObject = NULL; if (ocubeLabel.hasObject("NaifKeywords")) { naifKeywordsObject = &ocubeLabel.findObject("NaifKeywords"); // Clean up the naif keywords object... delete everything that isn't a radii for (int keyIndex = naifKeywordsObject->keywords() - 1; keyIndex >= 0; keyIndex--) { QString keyName = (*naifKeywordsObject)[keyIndex].name(); if (!keyName.contains("RADII")) { naifKeywordsObject->deleteKeyword(keyIndex); } } // Clean up the kernels group... delete everything that isn't internalized or the orig frame // code PvlGroup &kernelsGroup = ocube->group("Kernels"); for (int keyIndex = kernelsGroup.keywords() - 1; keyIndex >= 0; keyIndex--) { PvlKeyword &kernelsKeyword = kernelsGroup[keyIndex]; bool isTable = false; bool isFrameCode = kernelsKeyword.isNamed("NaifFrameCode") || kernelsKeyword.isNamed("NaifIkCode"); bool isShapeModel = kernelsKeyword.isNamed("ShapeModel"); for (int keyValueIndex = 0; keyValueIndex < kernelsKeyword.size(); keyValueIndex++) { if (kernelsKeyword[keyValueIndex] == "Table") { isTable = true; } } if (!isTable && !isFrameCode && !isShapeModel) { kernelsGroup.deleteKeyword(keyIndex); } } } if (naifKeywordsObject) { naifKeywordsObject->addKeyword(PvlKeyword("IDEAL_FOCAL_LENGTH", toString(incam->FocalLength())), Pvl::Replace); } else { inst.addKeyword(PvlKeyword("FocalLength", toString(incam->FocalLength()), "millimeters")); } double newPixelPitch = incam->PixelPitch() * ui.GetDouble("SUMMINGMODE"); if (naifKeywordsObject) { naifKeywordsObject->addKeyword(PvlKeyword("IDEAL_PIXEL_PITCH", toString(newPixelPitch)), Pvl::Replace); } else { inst.addKeyword(PvlKeyword("PixelPitch", toString(newPixelPitch), "millimeters")); } key.setName("EphemerisTime"); key.setValue(Isis::toString(et), "seconds"); inst.addKeyword(key); key.setName("StartTime"); key.setValue(startTime); inst.addKeyword(key); if(stopTime != "") { key.setName("StopTime"); key.setValue(stopTime); inst.addKeyword(key); } key.setName("FocalPlaneXDependency"); key.setValue(toString((int)incam->FocalPlaneMap()->FocalPlaneXDependency())); inst.addKeyword(key); int xDependency = incam->FocalPlaneMap()->FocalPlaneXDependency(); double newInstrumentTransX = incam->FocalPlaneMap()->SignMostSigX(); inst.addKeyword(PvlKeyword("TransX", toString(newInstrumentTransX))); double newInstrumentTransY = incam->FocalPlaneMap()->SignMostSigY(); inst.addKeyword(PvlKeyword("TransY", toString(newInstrumentTransY))); storeSpice(&inst, naifKeywordsObject, "TransX0", "IDEAL_TRANSX", transx, newPixelPitch * newInstrumentTransX, (xDependency == CameraFocalPlaneMap::Sample)); storeSpice(&inst, naifKeywordsObject, "TransY0", "IDEAL_TRANSY", transy, newPixelPitch * newInstrumentTransY, (xDependency == CameraFocalPlaneMap::Line)); double transSXCoefficient = 1.0 / newPixelPitch * newInstrumentTransX; double transLXCoefficient = 1.0 / newPixelPitch * newInstrumentTransY; if (xDependency == CameraFocalPlaneMap::Line) { swap(transSXCoefficient, transLXCoefficient); } storeSpice(&inst, naifKeywordsObject, "TransS0", "IDEAL_TRANSS", transs, transSXCoefficient, (xDependency == CameraFocalPlaneMap::Sample)); storeSpice(&inst, naifKeywordsObject, "TransL0", "IDEAL_TRANSL", transl, transLXCoefficient, (xDependency == CameraFocalPlaneMap::Line)); if(instType == "LINESCAN") { key.setName("ExposureDuration"); key.setValue(Isis::toString(incam->DetectorMap()->LineRate() * 1000.), "milliseconds"); inst.addKeyword(key); } key.setName("MatchedCube"); key.setValue(mcube->fileName()); inst.addKeyword(key); ocube->putGroup(inst); p.EndProcess(); // Now adjust the label to fake the true size of the image to match without // taking all the space it would require for the image data Pvl label; label.read("match.lbl"); PvlGroup &dims = label.findGroup("Dimensions", Pvl::Traverse); dims["Lines"] = toString(numberLines); dims["Samples"] = toString(detectorSamples); dims["Bands"] = toString(numberBands); label.write("match.lbl"); // And run cam2cam to apply the transformation QString parameters; parameters += " FROM= " + ui.GetFileName("FROM"); parameters += " MATCH= " + QString("match.cub"); parameters += " TO= " + ui.GetFileName("TO"); parameters += " INTERP=" + ui.GetString("INTERP"); ProgramLauncher::RunIsisProgram("cam2cam", parameters); // Cleanup by deleting the match files remove("match.History.IsisCube"); remove("match.lbl"); remove("match.cub"); remove("match.OriginalLabel.IsisCube"); remove("match.Table.BodyRotation"); remove("match.Table.HiRISE Ancillary"); remove("match.Table.HiRISE Calibration Ancillary"); remove("match.Table.HiRISE Calibration Image"); remove("match.Table.InstrumentPointing"); remove("match.Table.InstrumentPosition"); remove("match.Table.SunPosition"); // Finally finish by adding the OriginalInstrument group to the TO cube Cube toCube; toCube.open(ui.GetFileName("TO"), "rw"); // Extract label and create cube object Pvl *toLabel = toCube.label(); PvlObject &o = toLabel->findObject("IsisCube"); o.deleteGroup("OriginalInstrument"); o.addGroup(fromInst); toCube.close(); }
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; }
/** * 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() { Preference::Preferences(true); cout << "Testing Isis::ProcessMapMosaic Class ... " << endl; // Create the temp parent cube FileList cubes; cubes.read("unitTest.lis"); cout << "Testing Mosaic 1" << endl; ProcessMapMosaic m1; CubeAttributeOutput oAtt; ProcessMosaic::ImageOverlay priority = ProcessMapMosaic::PlaceImagesOnTop; m1.SetBandBinMatch(false); m1.SetOutputCube(cubes, oAtt, "./unitTest.cub"); //set priority m1.SetImageOverlay(priority); for(int i = 0; i < cubes.size(); i++) { if(m1.StartProcess(cubes[i].toString())) { cout << cubes[i].toString() << " is inside the mosaic" << endl; } else { cout << cubes[i].toString() << " is outside the mosaic" << endl; } } m1.EndProcess(); cout << "Mosaic label: " << endl; Pvl labels("./unitTest.cub"); cout << labels << endl; remove("./unitTest.cub"); cout << "Testing Mosaic 2" << endl; ProcessMapMosaic m2; m2.SetBandBinMatch(false); m2.SetOutputCube(cubes, -6, -4, 29, 31, oAtt, "./unitTest.cub"); //set priority m2.SetImageOverlay(priority); for(int i = 0; i < cubes.size(); i++) { if(m2.StartProcess(cubes[i].toString())) { cout << cubes[i].toString() << " is inside the mosaic" << endl; } else { cout << cubes[i].toString() << " is outside the mosaic" << endl; } } m2.EndProcess(); cout << "Mosaic label: " << endl; labels.clear(); labels.read("./unitTest.cub"); cout << labels << endl; Cube tmp; tmp.open("./unitTest.cub"); LineManager lm(tmp); lm.SetLine(1, 1); while(!lm.end()) { tmp.read(lm); cout << "Mosaic Data: " << lm[lm.SampleDimension()/4] << '\t' << lm[lm.SampleDimension()/2] << '\t' << lm[(3*lm.SampleDimension())/4] << endl; lm++; } tmp.close(); remove("./unitTest.cub"); // Create the temp parent cube cout << endl << "Testing Mosaic where the input (x, y) is negative," " according to the output cube." << endl; QString inputFile = "./unitTest1.cub"; Cube inCube; inCube.open(inputFile); PvlGroup mapGroup = inCube.label()->findGroup("Mapping", Pvl::Traverse); mapGroup.addKeyword(PvlKeyword("MinimumLatitude", toString(-4.9)), Pvl::Replace); mapGroup.addKeyword(PvlKeyword("MaximumLatitude", toString(-4.7)), Pvl::Replace); mapGroup.addKeyword(PvlKeyword("MinimumLongitude", toString(30.7)), Pvl::Replace); mapGroup.addKeyword(PvlKeyword("MaximumLongitude", toString(31)), Pvl::Replace); inCube.close(); CubeAttributeOutput oAtt2( FileName("./unitTest3.cub") ); ProcessMapMosaic m3; m3.SetBandBinMatch(false); m3.SetOutputCube(inputFile, mapGroup, oAtt2, "./unitTest3.cub"); //set priority m3.SetImageOverlay(priority); m3.SetHighSaturationFlag(false); m3.SetLowSaturationFlag(false); m3.SetNullFlag(false); if(m3.StartProcess(inputFile)) { cout << "The mosaic was successfull." << endl; } else { cout << "The mosaic was not successfull." << endl; } m3.EndProcess(); cout << "Mosaic label: " << endl; Pvl labels2("./unitTest3.cub"); cout << labels2 << endl; remove("./unitTest3.cub"); }
/** * GetPointInfo builds the PvlGroup containing all the important * information derived from the Camera. * * @return PvlGroup* Data taken directly from the Camera and * drived from Camera information. Ownership passed. */ PvlGroup *CameraPointInfo::GetPointInfo(bool passed, bool allowOutside, bool allowErrors) { PvlGroup *gp = new PvlGroup("GroundPoint"); { gp->addKeyword(PvlKeyword("Filename")); gp->addKeyword(PvlKeyword("Sample")); gp->addKeyword(PvlKeyword("Line")); gp->addKeyword(PvlKeyword("PixelValue")); gp->addKeyword(PvlKeyword("RightAscension")); gp->addKeyword(PvlKeyword("Declination")); gp->addKeyword(PvlKeyword("PlanetocentricLatitude")); gp->addKeyword(PvlKeyword("PlanetographicLatitude")); gp->addKeyword(PvlKeyword("PositiveEast360Longitude")); gp->addKeyword(PvlKeyword("PositiveEast180Longitude")); gp->addKeyword(PvlKeyword("PositiveWest360Longitude")); gp->addKeyword(PvlKeyword("PositiveWest180Longitude")); gp->addKeyword(PvlKeyword("BodyFixedCoordinate")); gp->addKeyword(PvlKeyword("LocalRadius")); gp->addKeyword(PvlKeyword("SampleResolution")); gp->addKeyword(PvlKeyword("LineResolution")); gp->addKeyword(PvlKeyword("SpacecraftPosition")); gp->addKeyword(PvlKeyword("SpacecraftAzimuth")); gp->addKeyword(PvlKeyword("SlantDistance")); gp->addKeyword(PvlKeyword("TargetCenterDistance")); gp->addKeyword(PvlKeyword("SubSpacecraftLatitude")); gp->addKeyword(PvlKeyword("SubSpacecraftLongitude")); gp->addKeyword(PvlKeyword("SpacecraftAltitude")); gp->addKeyword(PvlKeyword("OffNadirAngle")); gp->addKeyword(PvlKeyword("SubSpacecraftGroundAzimuth")); gp->addKeyword(PvlKeyword("SunPosition")); gp->addKeyword(PvlKeyword("SubSolarAzimuth")); gp->addKeyword(PvlKeyword("SolarDistance")); gp->addKeyword(PvlKeyword("SubSolarLatitude")); gp->addKeyword(PvlKeyword("SubSolarLongitude")); gp->addKeyword(PvlKeyword("SubSolarGroundAzimuth")); gp->addKeyword(PvlKeyword("Phase")); gp->addKeyword(PvlKeyword("Incidence")); gp->addKeyword(PvlKeyword("Emission")); gp->addKeyword(PvlKeyword("NorthAzimuth")); gp->addKeyword(PvlKeyword("EphemerisTime")); gp->addKeyword(PvlKeyword("UTC")); gp->addKeyword(PvlKeyword("LocalSolarTime")); gp->addKeyword(PvlKeyword("SolarLongitude")); if (allowErrors) gp->addKeyword(PvlKeyword("Error")); } bool noErrors = passed; QString error = ""; if (!m_camera->HasSurfaceIntersection()) { error = "Requested position does not project in camera model; no surface intersection"; noErrors = false; if (!allowErrors) throw IException(IException::Unknown, error, _FILEINFO_); } if (!m_camera->InCube() && !allowOutside) { error = "Requested position does not project in camera model; not inside cube"; noErrors = false; if (!allowErrors) throw IException(IException::Unknown, error, _FILEINFO_); } if (!noErrors) { for (int i = 0; i < gp->keywords(); i++) { QString name = (*gp)[i].name(); // These three keywords have 3 values, so they must have 3 N/As if (name == "BodyFixedCoordinate" || name == "SpacecraftPosition" || name == "SunPosition") { (*gp)[i].addValue("N/A"); (*gp)[i].addValue("N/A"); (*gp)[i].addValue("N/A"); } else { (*gp)[i].setValue("N/A"); } } // Set all keywords that still have valid information gp->findKeyword("Error").setValue(error); gp->findKeyword("FileName").setValue(m_currentCube->fileName()); gp->findKeyword("Sample").setValue(toString(m_camera->Sample())); gp->findKeyword("Line").setValue(toString(m_camera->Line())); gp->findKeyword("EphemerisTime").setValue( toString(m_camera->time().Et()), "seconds"); gp->findKeyword("EphemerisTime").addComment("Time"); QString utc = m_camera->time().UTC(); gp->findKeyword("UTC").setValue(utc); gp->findKeyword("SpacecraftPosition").addComment("Spacecraft Information"); gp->findKeyword("SunPosition").addComment("Sun Information"); gp->findKeyword("Phase").addComment("Illumination and Other"); } else { Brick b(3, 3, 1, m_currentCube->pixelType()); int intSamp = (int)(m_camera->Sample() + 0.5); int intLine = (int)(m_camera->Line() + 0.5); b.SetBasePosition(intSamp, intLine, 1); m_currentCube->read(b); double pB[3], spB[3], sB[3]; QString utc; double ssplat, ssplon, sslat, sslon, pwlon, oglat; { gp->findKeyword("FileName").setValue(m_currentCube->fileName()); gp->findKeyword("Sample").setValue(toString(m_camera->Sample())); gp->findKeyword("Line").setValue(toString(m_camera->Line())); gp->findKeyword("PixelValue").setValue(PixelToString(b[0])); gp->findKeyword("RightAscension").setValue(toString( m_camera->RightAscension())); gp->findKeyword("Declination").setValue(toString( m_camera->Declination())); gp->findKeyword("PlanetocentricLatitude").setValue(toString( m_camera->UniversalLatitude())); // Convert lat to planetographic Distance radii[3]; m_camera->radii(radii); oglat = TProjection::ToPlanetographic(m_camera->UniversalLatitude(), radii[0].kilometers(), radii[2].kilometers()); gp->findKeyword("PlanetographicLatitude").setValue(toString(oglat)); gp->findKeyword("PositiveEast360Longitude").setValue(toString( m_camera->UniversalLongitude())); //Convert lon to -180 - 180 range gp->findKeyword("PositiveEast180Longitude").setValue(toString( TProjection::To180Domain(m_camera->UniversalLongitude()))); //Convert lon to positive west pwlon = TProjection::ToPositiveWest( m_camera->UniversalLongitude(), 360); gp->findKeyword("PositiveWest360Longitude").setValue(toString(pwlon)); //Convert pwlon to -180 - 180 range gp->findKeyword("PositiveWest180Longitude").setValue(toString( TProjection::To180Domain(pwlon))); m_camera->Coordinate(pB); gp->findKeyword("BodyFixedCoordinate").addValue(toString(pB[0]), "km"); gp->findKeyword("BodyFixedCoordinate").addValue(toString(pB[1]), "km"); gp->findKeyword("BodyFixedCoordinate").addValue(toString(pB[2]), "km"); gp->findKeyword("LocalRadius").setValue(toString( m_camera->LocalRadius().meters()), "meters"); gp->findKeyword("SampleResolution").setValue(toString( m_camera->SampleResolution()), "meters/pixel"); gp->findKeyword("LineResolution").setValue(toString( m_camera->LineResolution()), "meters/pixel"); //body fixed m_camera->instrumentPosition(spB); gp->findKeyword("SpacecraftPosition").addValue(toString(spB[0]), "km"); gp->findKeyword("SpacecraftPosition").addValue(toString(spB[1]), "km"); gp->findKeyword("SpacecraftPosition").addValue(toString(spB[2]), "km"); gp->findKeyword("SpacecraftPosition").addComment("Spacecraft Information"); gp->findKeyword("SpacecraftAzimuth").setValue(toString( m_camera->SpacecraftAzimuth())); gp->findKeyword("SlantDistance").setValue(toString( m_camera->SlantDistance()), "km"); gp->findKeyword("TargetCenterDistance").setValue(toString( m_camera->targetCenterDistance()), "km"); m_camera->subSpacecraftPoint(ssplat, ssplon); gp->findKeyword("SubSpacecraftLatitude").setValue(toString(ssplat)); gp->findKeyword("SubSpacecraftLongitude").setValue(toString(ssplon)); gp->findKeyword("SpacecraftAltitude").setValue(toString( m_camera->SpacecraftAltitude()), "km"); gp->findKeyword("OffNadirAngle").setValue(toString( m_camera->OffNadirAngle())); double subspcgrdaz; subspcgrdaz = m_camera->GroundAzimuth(m_camera->UniversalLatitude(), m_camera->UniversalLongitude(), ssplat, ssplon); gp->findKeyword("SubSpacecraftGroundAzimuth").setValue(toString(subspcgrdaz)); m_camera->sunPosition(sB); gp->findKeyword("SunPosition").addValue(toString(sB[0]), "km"); gp->findKeyword("SunPosition").addValue(toString(sB[1]), "km"); gp->findKeyword("SunPosition").addValue(toString(sB[2]), "km"); gp->findKeyword("SunPosition").addComment("Sun Information"); gp->findKeyword("SubSolarAzimuth").setValue(toString(m_camera->SunAzimuth())); gp->findKeyword("SolarDistance").setValue(toString( m_camera->SolarDistance()), "AU"); m_camera->subSolarPoint(sslat, sslon); gp->findKeyword("SubSolarLatitude").setValue(toString(sslat)); gp->findKeyword("SubSolarLongitude").setValue(toString(sslon)); double subsolgrdaz; subsolgrdaz = m_camera->GroundAzimuth(m_camera->UniversalLatitude(), m_camera->UniversalLongitude(), sslat, sslon); gp->findKeyword("SubSolarGroundAzimuth").setValue(toString(subsolgrdaz)); gp->findKeyword("Phase").setValue(toString(m_camera->PhaseAngle())); gp->findKeyword("Phase").addComment("Illumination and Other"); gp->findKeyword("Incidence").setValue(toString( m_camera->IncidenceAngle())); gp->findKeyword("Emission").setValue(toString( m_camera->EmissionAngle())); gp->findKeyword("NorthAzimuth").setValue(toString( m_camera->NorthAzimuth())); gp->findKeyword("EphemerisTime").setValue(toString( m_camera->time().Et()), "seconds"); gp->findKeyword("EphemerisTime").addComment("Time"); utc = m_camera->time().UTC(); gp->findKeyword("UTC").setValue(utc); gp->findKeyword("LocalSolarTime").setValue(toString( m_camera->LocalSolarTime()), "hour"); gp->findKeyword("SolarLongitude").setValue(toString( m_camera->solarLongitude().degrees())); if (allowErrors) gp->findKeyword("Error").setValue("N/A"); } } return gp; }