#include "IsisDebug.h" #include "CameraStatistics.h" #include "Camera.h" #include "Cube.h" #include "Distance.h" #include "Progress.h" #include "Statistics.h" namespace Isis { /** * Constructs the Camera Statistics object from a Cube filename. This * constructor will first open the cube corresponding to the "filename" * parameter, then gather statistics with the Cube's Camera. Neither the * Cube nor its Camera is retained after statistics gathering has completed, * but the filename used to open the Cube will be output in the "User * Parameters" group of the "toPvl" method. The invoker of this constructor * must also specify the sample and line increments to be used during * statistics gathering. * * @param filename String filename of the Cube whose Camera will be used * @param sinc Sample increment for gathering statistics * @param linc Line increment for gathering statistics */ CameraStatistics::CameraStatistics(QString filename, int sinc, int linc) { Cube cube; cube.open(filename); Camera *cam = cube.camera(); init(cam, sinc, linc, filename); } /** * Constructs the Camera Statistics object from an already-existent Camera * pointer. Specifying sample and line increments of 1 will gather * statistics on the entire area encompassed by the Camera, but higher * numbers can be used to improve performance. Using this * constructor--lacking a Cube filename--the "toPvl" method will not output * the Cube filename associated with the Camera. If the user desires this * information, there is a constructor that will take the filename purely for * this purpose. * * @param cam Camera pointer upon which statistics will be gathered * @param sinc Sample increment for gathering statistics * @param linc Line increment for gathering statistics */ CameraStatistics::CameraStatistics(Camera *cam, int sinc, int linc) { init(cam, sinc, linc, ""); } /** * Constructs the Camera Statistics object from an already-existent Camera * pointer. Specifying sample and line increments of 1 will gather * statistics on the entire area encompassed by the Camera, but higher * numbers can be used to improve performance. The filename provided does * not serve a functional purpose during the statistics gathering process, * but will report the filename used to create the Camera instance in the * "User Parameters" section of the PVL output from the "toPvl" method. * * @param cam Camera pointer upon which statistics will be gathered * @param sinc Sample increment for gathering statistics * @param linc Line increment for gathering statistics * @param filename String filename of the Cube whose Camera is being used */ CameraStatistics::CameraStatistics(Camera *cam, int sinc, int linc, QString filename) { init(cam, sinc, linc, filename); } /** * Initializes this collection of statistics by incrementing over sample/line * positions in the Camera and compiling various Camera values at those * locations into all the Statistics objects maintained as the persistent * state of the object. Statistics can be added to these objects later using * the "addStats" method. * * @param cam Camera pointer upon which statistics will be gathered * @param sinc Sample increment for gathering statistics * @param linc Line increment for gathering statistics * @param filename String filename of the Cube whose Camera is being used */ void CameraStatistics::init(Camera *cam, int sinc, int linc, QString filename) { m_filename = filename; m_sinc = sinc; m_linc = linc; m_latStat = new Statistics(); m_lonStat = new Statistics(); m_resStat = new Statistics(); m_obliqueResStat = new Statistics(); m_obliqueSampleResStat = new Statistics(); m_obliqueLineResStat = new Statistics(); m_sampleResStat = new Statistics(); m_lineResStat = new Statistics(); m_aspectRatioStat = new Statistics(); m_phaseStat = new Statistics(); m_emissionStat = new Statistics(); m_incidenceStat = new Statistics(); m_localSolarTimeStat = new Statistics(); m_localRaduisStat = new Statistics(); m_northAzimuthStat = new Statistics(); int eband = cam->Bands(); // If the camera is band independent then only run one band if (cam->IsBandIndependent()) eband = 1; int pTotal = eband * ((cam->Lines() - 2) / linc + 2); Progress progress; progress.SetMaximumSteps(pTotal); progress.CheckStatus(); for (int band = 1; band <= eband; band++) { cam->SetBand(band); for (int line = 1; line < (int)cam->Lines(); line = line + linc) { for (int sample = 1; sample < cam->Samples(); sample = sample + sinc) { addStats(cam, sample, line); } // Set the sample value to the last sample and run buildstats int sample = cam->Samples(); addStats(cam, sample, line); progress.CheckStatus(); } // Set the line value to the last line and run on all samples (sample + // sinc) int line = cam->Lines(); for (int sample = 1; sample < cam->Samples(); sample = sample + sinc) { addStats(cam, sample, line); } // Set last sample and run with last line int sample = cam->Samples(); addStats(cam, sample, line); progress.CheckStatus(); } } /** * Destroy this instance, deletes all the Statistics objects. */ CameraStatistics::~CameraStatistics() { if (m_latStat != NULL) { delete m_latStat; m_latStat = NULL; } if (m_lonStat != NULL) { delete m_lonStat; m_lonStat = NULL; } if (m_resStat != NULL) { delete m_resStat; m_resStat = NULL; } if (m_obliqueLineResStat != NULL) { delete m_obliqueLineResStat; m_obliqueLineResStat = NULL; } if (m_obliqueSampleResStat != NULL) { delete m_obliqueSampleResStat; m_obliqueSampleResStat = NULL; } if (m_obliqueResStat != NULL) { delete m_obliqueResStat; m_obliqueResStat = NULL; } if (m_sampleResStat != NULL) { delete m_sampleResStat; m_sampleResStat = NULL; } if (m_lineResStat != NULL) { delete m_lineResStat; m_lineResStat = NULL; } if (m_aspectRatioStat != NULL) { delete m_aspectRatioStat; m_aspectRatioStat = NULL; } if (m_phaseStat != NULL) { delete m_phaseStat; m_phaseStat = NULL; } if (m_emissionStat != NULL) { delete m_emissionStat; m_emissionStat = NULL; } if (m_incidenceStat != NULL) { delete m_incidenceStat; m_incidenceStat = NULL; } if (m_localSolarTimeStat != NULL) { delete m_localSolarTimeStat; m_localSolarTimeStat = NULL; } if (m_localRaduisStat != NULL) { delete m_localRaduisStat; m_localRaduisStat = NULL; } if (m_northAzimuthStat != NULL) { delete m_northAzimuthStat; m_northAzimuthStat = NULL; } } /** * Add statistics data to Statistics objects if the Camera position given by * the provided line and sample is looking at the surface of the target. * * @param cam Camera pointer upon which statistics are being gathered * @param sample Sample of the image to gather Camera information on * @param line Line of the image to gather Camera information on */ void CameraStatistics::addStats(Camera *cam, int &sample, int &line) { cam->SetImage(sample, line); if(cam->HasSurfaceIntersection()) { m_latStat->AddData(cam->UniversalLatitude()); m_lonStat->AddData(cam->UniversalLongitude()); m_obliqueResStat->AddData(cam->ObliquePixelResolution()); m_obliqueSampleResStat->AddData(cam->ObliqueSampleResolution()); m_obliqueLineResStat->AddData(cam->ObliqueLineResolution()); m_resStat->AddData(cam->PixelResolution()); m_sampleResStat->AddData(cam->SampleResolution()); m_lineResStat->AddData(cam->LineResolution()); m_phaseStat->AddData(cam->PhaseAngle()); m_emissionStat->AddData(cam->EmissionAngle()); m_incidenceStat->AddData(cam->IncidenceAngle()); m_localSolarTimeStat->AddData(cam->LocalSolarTime()); m_localRaduisStat->AddData(cam->LocalRadius().meters()); // if IsValid m_northAzimuthStat->AddData(cam->NorthAzimuth()); // if resolution not equal to -1.0 double aspectRatio = cam->LineResolution() / cam->SampleResolution(); m_aspectRatioStat->AddData(aspectRatio); } } /** * Takes a name, value, and optionally units and constructs a PVL Keyword. * If the value is determined to be a "special pixel", then the string NULL * will be used for the value. * * @param keyname Name of keyword to generate * @param value Value to write to keyword * @param unit Optional units for keywords * * @return PvlKeyword Keyword constructed from input parameters */ PvlKeyword CameraStatistics::constructKeyword(QString keyname, double value, QString unit="") const { if(IsSpecial(value)) { return (PvlKeyword(keyname, "NULL")); } else { return (PvlKeyword(keyname, toString(value), unit)); } } /** * Constructs a Pvl object from the values in the various statistics objects. * The general format will look as follows: * * @code * Group = User Parameters * Filename (not provided for constructor w/ Camera but not filename) * Linc * Sinc * End_Group * Group = Latitude * LatitudeMinimum * LatitudeMaximum * LatitudeStandardDeviation * End_Group * Group = Longitude * LongitudeMinimum * LongitudeMaximum * LongitudeStandardDeviation * End_Group * Group = SampleResolution * SampleResolutionMinimum * SampleResolutionMaximum * SampleResolutionStandardDeviation * End_Group * Group = LineResolution * LineResolutionMinimum * LineResolutionMaximum * LineResolutionStandardDeviation * End_Group * Group = Resolution * ResolutionMinimum * ResolutionMaximum * ResolutionStandardDeviation * End_Group * Group = AspectRatio * AspectRatioMinimum * AspectRatioMaximum * AspectRatioStandardDeviation * End_Group * Group = PhaseAngle * PhaseMinimum * PhaseMaximum * PhaseStandardDeviation * End_Group * Group = EmissionAngle * EmissionMinimum * EmissionMaximum * EmissionStandardDeviation * End_Group * Group = IncidenceAngle * IncidenceMinimum * IncidenceMaximum * IncidenceStandardDeviation * End_Group * Group = LocalSolarTime * LocalSolarTimeMinimum * LocalSolarTimeMaximum * LocalSolarTimeStandardDeviation * End_Group * Group = LocalRadius * LocalRadiusMinimum * LocalRadiusMaximum * LocalRadiusStandardDeviation * End_Group * Group = NorthAzimuth * NorthAzimuthMinimum * NorthAzimuthMaximum * NorthAzimuthStandardDeviation * End_Group * @endcode * * @return Pvl PVL collection of all values for all statistics gathered */ Pvl CameraStatistics::toPvl() const { // Set up the Pvl groups and get min, max, avg, and sd for each statstics // object PvlGroup pUser("User Parameters"); if (m_filename != "") pUser += PvlKeyword("Filename", m_filename); pUser += PvlKeyword("Linc", toString(m_linc)); pUser += PvlKeyword("Sinc", toString(m_sinc)); PvlGroup pLat("Latitude"); pLat += constructKeyword("LatitudeMinimum", m_latStat->Minimum()); pLat += constructKeyword("LatitudeMaximum", m_latStat->Maximum()); pLat += constructKeyword("LatitudeAverage", m_latStat->Average()); pLat += constructKeyword("LatitudeStandardDeviation", m_latStat->StandardDeviation()); PvlGroup pLon("Longitude"); pLon += constructKeyword("LongitudeMinimum", m_lonStat->Minimum()); pLon += constructKeyword("LongitudeMaximum", m_lonStat->Maximum()); pLon += constructKeyword("LongitudeAverage", m_lonStat->Average()); pLon += constructKeyword("LongitudeStandardDeviation", m_lonStat->StandardDeviation()); PvlGroup pObliqueSampleRes("ObliqueSampleResolution"); pObliqueSampleRes += constructKeyword("ObliqueSampleResolutionMinimum", m_obliqueSampleResStat->Minimum(), "meters/pixel"); pObliqueSampleRes += constructKeyword("ObliqueSampleResolutionMaximum", m_obliqueSampleResStat->Maximum(),"meters/pixel"); pObliqueSampleRes += constructKeyword("ObliqueSampleResolutionAverage", m_obliqueSampleResStat->Average(),"meters/pixel"); pObliqueSampleRes += constructKeyword("ObliqueSampleResolutionStandardDeviation", m_obliqueSampleResStat->StandardDeviation(), "meters/pixel"); PvlGroup pObliqueLineRes("ObliqueLineResolution"); pObliqueLineRes += constructKeyword("ObliqueLineResolutionMinimum", m_obliqueLineResStat->Minimum(), "meters/pixel"); pObliqueLineRes += constructKeyword("ObliqueLineResolutionMaximum", m_obliqueLineResStat->Maximum(), "meters/pixel"); pObliqueLineRes += constructKeyword("ObliqueLineResolutionAverage", m_obliqueLineResStat->Average(), "meters/pixel"); pObliqueLineRes += constructKeyword("ObliqueLineResolutionStandardDeviation", m_obliqueLineResStat->StandardDeviation(), "meters/pixel"); PvlGroup pObliqueResolution("ObliqueResolution"); pObliqueResolution += constructKeyword("ObliqueResolutionMinimum", m_obliqueResStat->Minimum(), "meters/pixel"); pObliqueResolution += constructKeyword("ObliqueResolutionMaximum", m_obliqueResStat->Maximum(), "meters/pixel"); pObliqueResolution += constructKeyword("ObliqueResolutionAverage", m_obliqueResStat->Average(), "meters/pixel"); pObliqueResolution += constructKeyword("ObliqueResolutionStandardDeviation", m_obliqueResStat->StandardDeviation(), "meters/pixel"); PvlGroup pSampleRes("SampleResolution"); pSampleRes += constructKeyword("SampleResolutionMinimum", m_sampleResStat->Minimum(), "meters/pixel"); pSampleRes += constructKeyword("SampleResolutionMaximum", m_sampleResStat->Maximum(), "meters/pixel"); pSampleRes += constructKeyword("SampleResolutionAverage", m_sampleResStat->Average(), "meters/pixel"); pSampleRes += constructKeyword("SampleResolutionStandardDeviation", m_sampleResStat->StandardDeviation(), "meters/pixel"); PvlGroup pLineRes("LineResolution"); pLineRes += constructKeyword("LineResolutionMinimum", m_lineResStat->Minimum(), "meters/pixel"); pLineRes += constructKeyword("LineResolutionMaximum", m_lineResStat->Maximum(), "meters/pixel"); pLineRes += constructKeyword("LineResolutionAverage", m_lineResStat->Average(), "meters/pixel"); pLineRes += constructKeyword("LineResolutionStandardDeviation", m_lineResStat->StandardDeviation(), "meters/pixel"); PvlGroup pResolution("Resolution"); pResolution += constructKeyword("ResolutionMinimum", m_resStat->Minimum(), "meters/pixel"); pResolution += constructKeyword("ResolutionMaximum", m_resStat->Maximum(), "meters/pixel"); pResolution += constructKeyword("ResolutionAverage", m_resStat->Average(), "meters/pixel"); pResolution += constructKeyword("ResolutionStandardDeviation", m_resStat->StandardDeviation(), "meters/pixel"); PvlGroup pAspectRatio("AspectRatio"); pAspectRatio += constructKeyword("AspectRatioMinimum", m_aspectRatioStat->Minimum()); pAspectRatio += constructKeyword("AspectRatioMaximun", m_aspectRatioStat->Maximum()); pAspectRatio += constructKeyword("AspectRatioAverage", m_aspectRatioStat->Average()); pAspectRatio += constructKeyword("AspectRatioStandardDeviation", m_aspectRatioStat->StandardDeviation()); PvlGroup pPhase("PhaseAngle"); pPhase += constructKeyword("PhaseMinimum", m_phaseStat->Minimum()); pPhase += constructKeyword("PhaseMaximum", m_phaseStat->Maximum()); pPhase += constructKeyword("PhaseAverage", m_phaseStat->Average()); pPhase += constructKeyword("PhaseStandardDeviation", m_phaseStat->StandardDeviation()); PvlGroup pEmission("EmissionAngle"); pEmission += constructKeyword("EmissionMinimum", m_emissionStat->Minimum()); pEmission += constructKeyword("EmissionMaximum", m_emissionStat->Maximum()); pEmission += constructKeyword("EmissionAverage", m_emissionStat->Average()); pEmission += constructKeyword("EmissionStandardDeviation", m_emissionStat->StandardDeviation()); PvlGroup pIncidence("IncidenceAngle"); pIncidence += constructKeyword("IncidenceMinimum", m_incidenceStat->Minimum()); pIncidence += constructKeyword("IncidenceMaximum", m_incidenceStat->Maximum()); pIncidence += constructKeyword("IncidenceAverage", m_incidenceStat->Average()); pIncidence += constructKeyword("IncidenceStandardDeviation", m_incidenceStat->StandardDeviation()); PvlGroup pTime("LocalSolarTime"); pTime += constructKeyword("LocalSolarTimeMinimum", m_localSolarTimeStat->Minimum(), "hours"); pTime += constructKeyword("LocalSolarTimeMaximum", m_localSolarTimeStat->Maximum(), "hours"); pTime += constructKeyword("LocalSolarTimeAverage", m_localSolarTimeStat->Average(), "hours"); pTime += constructKeyword("LocalSolarTimeStandardDeviation", m_localSolarTimeStat->StandardDeviation(), "hours"); PvlGroup pLocalRadius("LocalRadius"); pLocalRadius += constructKeyword("LocalRadiusMinimum", m_localRaduisStat->Minimum()); pLocalRadius += constructKeyword("LocalRadiusMaximum", m_localRaduisStat->Maximum()); pLocalRadius += constructKeyword("LocalRadiusAverage", m_localRaduisStat->Average()); pLocalRadius += constructKeyword("LocalRadiusStandardDeviation", m_localRaduisStat->StandardDeviation()); PvlGroup pNorthAzimuth("NorthAzimuth"); pNorthAzimuth += constructKeyword("NorthAzimuthMinimum", m_northAzimuthStat->Minimum()); pNorthAzimuth += constructKeyword("NorthAzimuthMaximum", m_northAzimuthStat->Maximum()); pNorthAzimuth += constructKeyword("NorthAzimuthAverage", m_northAzimuthStat->Average()); pNorthAzimuth += constructKeyword("NorthAzimuthStandardDeviation", m_northAzimuthStat->StandardDeviation()); Pvl returnPvl; returnPvl.setTerminator(""); returnPvl.addGroup(pUser); returnPvl.addGroup(pLat); returnPvl.addGroup(pLon); returnPvl.addGroup(pSampleRes); returnPvl.addGroup(pLineRes); returnPvl.addGroup(pResolution); returnPvl.addGroup(pObliqueSampleRes); returnPvl.addGroup(pObliqueLineRes); returnPvl.addGroup(pObliqueResolution); returnPvl.addGroup(pAspectRatio); returnPvl.addGroup(pPhase); returnPvl.addGroup(pEmission); returnPvl.addGroup(pIncidence); returnPvl.addGroup(pTime); returnPvl.addGroup(pLocalRadius); returnPvl.addGroup(pNorthAzimuth); return returnPvl; } }