7#include "Equalization.h"
19#include "IException.h"
20#include "LeastSquares.h"
21#include "LineManager.h"
22#include "OverlapNormalization.h"
23#include "OverlapStatistics.h"
25#include "ProcessByLine.h"
26#include "Projection.h"
30#include "Statistics.h"
88 if (holdList.size() > m_imageList.size()) {
89 QString msg =
"The list of identifiers to be held must be less than or ";
90 msg +=
"equal to the total number of identitifers.";
95 for (
int i = 0; i < holdList.size(); i++) {
97 for (
int j = 0; j < m_imageList.size(); j++) {
98 if (holdList[i] == m_imageList[j]) {
105 QString msg =
"The hold list file [" + holdList[i].toString() +
106 "] does not match a file in the from list";
155 for (
int img = 0; img < m_imageList.size(); img++) {
167 msg =
"There are input images that do not overlap with enough valid pixels. ";
168 msg +=
"See application log or \"NonOverlaps\" keyword in output statistics file.";
174 for (
int band = 0; band <
m_maxBand; band++) {
177 for (
unsigned int img = 0; img < m_adjustments.size(); img++) {
181 cout << band << endl;
185 "Calculation for equalization statistics failed. Gain = 0.",
196 QString msg =
"Unable to calculate the equalization statistics. You may "
197 "want to try another LeastSquares::SolveMethod.";
215 for (
int band = 1; band <=
m_maxBand; band++) {
217 vector<Statistics *> statsList;
218 for (
int img = 0; img < (int) m_imageList.size(); img++) {
221 QString statMsg =
"Calculating Statistics for Band " + bandStr +
226 QString inp = m_imageList[img].toString();
235 statsList.push_back(stats);
254 for (
int img = 0; img < m_imageList.size(); img++) {
260 for (
int i = 0; i < m_imageList.size(); i++) {
264 for (
int j = (i + 1); j < m_imageList.size(); j++) {
275 QString cubeStr1 =
toString((
int)(i + 1));
276 QString cubeStr2 =
toString((
int)(j + 1));
277 QString statMsg =
"Gathering Overlap Statisitcs for Cube " +
278 cubeStr1 +
" vs " + cubeStr2 +
" of " +
288 for (
int band = 1; band <=
m_maxBand; band++) {
309 for (
int band = 1; band <=
m_maxBand; band++) {
333 PvlObject equ(
"EqualizationInformation");
346 for (
int img = 0; img <
m_badFiles.size(); img++) {
354 for (
int img = 0; img < m_imageList.size(); img++) {
361 norm.addComment(
"Formula: newDN = (oldDN - AVERAGE) * GAIN + AVERAGE + OFFSET");
362 norm.addComment(
"BandN = (GAIN, OFFSET, AVERAGE)");
365 norm.addComment(
"Formula: newDN = oldDN * GAIN + AVERAGE * GAIN");
366 norm.addComment(
"BandN = (GAIN, AVERAGE)");
369 norm.addComment(
"Formula: newDN = OFFSET + AVERAGE");
370 norm.addComment(
"BandN = (OFFSET, AVERAGE)");
373 norm.addComment(
"Formula: newDN = oldDN * GAIN");
374 norm.addComment(
"BandN = (GAIN)");
377 norm +=
PvlKeyword(
"FileName", m_imageList[img].original());
381 for (
int band = 1; band <=
m_maxBand; band++) {
383 QString bandStr =
"Band" + bandNum;
389 bandStats +=
toString(m_adjustments[img]->getGain(band - 1));
394 bandStats +=
toString(m_adjustments[img]->getOffset(band - 1));
400 bandStats +=
toString(m_adjustments[img]->getAverage(band - 1));
430 Pvl inStats(instatsFileName);
451 Pvl inStats(instatsFileName);
457 if (!general.
hasKeyword(
"HasCorrections") || general[
"HasCorrections"][0] ==
"true") {
461 for (
int img = 0; img < (int) m_imageList.size(); img++) {
470 for (
int band = 1; band < normalization.
keywords(); band++) {
471 adjustment->addGain(
toDouble(normalization[band][0]));
472 adjustment->addOffset(
toDouble(normalization[band][1]));
473 adjustment->addAverage(
toDouble(normalization[band][2]));
498 QString msg =
"Corrective factors have not yet been determined. ";
500 msg +=
"Fix any non-overlapping images and recalculate the image statistics. ";
501 msg +=
"File(s) without overlaps: ";
502 for (
int img = 0; img <
m_badFiles.size(); img++) {
507 msg +=
"Add more images to create more overlaps and recalculate, ";
508 msg +=
"or try another solve method.";
514 fillOutList(outList, toListName);
516 QString maxCubeStr =
toString((
int) m_imageList.size());
517 for (
int img = 0; img < m_imageList.size(); img++) {
521 " of " + maxCubeStr);
525 const QString inp = m_imageList[img].toString();
529 QString out = outList[img].toString();
551 PvlGroup results =
m_results->findObject(
"EqualizationInformation").findGroup(
"General");
555 for (
int img = 0; img < m_imageList.size(); img++) {
559 for (
int band = 1; band <=
m_maxBand; band++) {
560 QString mult =
toString(m_adjustments[img]->getGain(band - 1));
561 QString base =
toString(m_adjustments[img]->getOffset(band - 1));
562 QString avg =
toString(m_adjustments[img]->getAverage(band - 1));
564 QString bandStr =
"Band" + bandNum;
569 results += bandStats;
588 double Equalization::evaluate(
double dn,
int imageIndex,
int bandIndex)
const {
589 return m_adjustments[imageIndex]->evaluate(dn, bandIndex);
604 m_imageList.read(fromListName);
607 if (m_imageList.size() < 2) {
608 QString msg =
"The input file [" + fromListName +
609 "] must contain at least 2 file names";
624 void Equalization::setInput(
int index, QString value) {
625 m_imageList[index] = value;
629 const FileList &Equalization::getInputs()
const {
634 void Equalization::fillOutList(
FileList &outList, QString toListName) {
635 if (toListName.isEmpty()) {
651 for (
int i = 0; i < m_imageList.size(); i++) {
655 for (
int j = (i + 1); j < m_imageList.size(); j++) {
661 QString msg =
"Number of bands do not match between cubes [" +
662 m_imageList[i].toString() +
"] and [" + m_imageList[j].toString() +
"]";
671 if (*proj1 != *proj2) {
672 QString msg =
"Mapping groups do not match between cubes [" +
673 m_imageList[i].toString() +
"] and [" + m_imageList[j].toString() +
"]";
685 for (
int img = 0; img < m_imageList.size(); img++) {
687 QString filename = file.
path() +
"/" + file.
baseName() +
689 outList.push_back(
FileName(filename));
706 if (outList.size() != m_imageList.size()) {
707 QString msg =
"Each input file in the FROM LIST must have a ";
708 msg +=
"corresponding output file in the TO LIST.";
714 for (
int i = 0; i < outList.size(); i++) {
716 QString msg =
"The to list file [" + outList[i].toString() +
717 "] has the same name as its corresponding from list file.";
734 for (
unsigned int adj = 0; adj < m_adjustments.size(); adj++) {
735 delete m_adjustments[adj];
737 m_adjustments.clear();
749 m_adjustments.push_back(adjustment);
757 for (
unsigned int oNorm = 0; oNorm <
m_overlapNorms.size(); oNorm++) {
768 for (
unsigned int oStat = 0; oStat <
m_overlapStats.size(); oStat++) {
807 for (
int img = 0; img < m_imageList.size(); img++) {
808 imgNames.append(m_imageList[img].name());
816 m_wtopt = (eqGen[
"Weighted"][0] ==
"true") ?
true :
false;
821 PvlObject::ConstPvlObjectIterator curObj = inStats.
beginObject();
823 if (curObj->isNamed(
"OverlapStatistics")) {
828 QString fileX = oStat[
"File1"][0];
829 QString fileY = oStat[
"File2"][0];
832 int x = imgNames.indexOf(fileX);
833 int y = imgNames.indexOf(fileY);
839 if (oStat[
"Valid"][0] ==
"true") {
863 for (
int i = 0; i < m_imageList.size(); i++) {
864 QString imageName(m_imageList[i].name());
870 overlapIndices[o].push_front(i);
875 overlapIndices[o].push_back(i);
882 for (
int band = 1; band <= oStat->
Bands(); band++) {
887 oStat->
GetMStats(band).
Y(), overlapIndices[o][1], weight);
959 Pvl inStats(instatsFileName);
963 if (m_imageList.size() > equalInfo.
groups() - 1) {
964 QString msg =
"Each input file in the FROM LIST must have a ";
965 msg +=
"corresponding input file in the INPUT STATISTICS.";
970 for (
int i = 0; i < m_imageList.size(); i++) {
971 QString fromFile = m_imageList[i].original();
972 bool foundFile =
false;
973 for (
int j = 1; j < equalInfo.
groups(); j++) {
975 QString normFile = normalization[
"FileName"][0];
976 if (fromFile == normFile) {
980 normIndices.push_back(j);
985 QString msg =
"The from list file [" + fromFile +
986 "] does not have any corresponding file in the stats list.";
995 void Equalization::CalculateFunctor::operator()(
Buffer &in)
const {
1003 void Equalization::CalculateFunctor::addStats(Buffer &in)
const {
1005 m_stats->AddData(&in[0], in.size());
1009 void Equalization::ApplyFunctor::operator()(Buffer &in, Buffer &out)
const {
1010 int index = in.Band() - 1;
1011 for (
int i = 0; i < in.size(); i++) {
1013 in[i] : m_adjustment->evaluate(in[i], index);
Functor for reduce using average functionality.
Buffer for reading and writing cube data.
int Line(const int index=0) const
Returns the line position associated with a shape buffer index.
int LineDimension() const
Returns the number of lines in the shape buffer.
Manipulate and parse attributes of output cube filenames.
IO Handler for Isis Cubes.
void open(const QString &cfile, QString access="r")
This method will open an existing isis cube for reading or reading/writing.
Projection * projection()
virtual int bandCount() const
Returns the number of virtual bands for the cube.
This class is used as a functor to apply adjustments (equalize) to an image.
This class is used as a functor calculate image statistics.
int m_linc
Line increment value when calculating statistics.
void calculateBandStatistics()
Calculates the image statistics on a band-by-band basis.
void importStatistics(QString instatsFileName)
Imports statistics for applying correction.
void generateOutputs(FileList &outList)
Generates the names of the equalized cubes if no output list is provided.
void clearAdjustments()
Frees image adjustments.
void loadOutputs(FileList &outList, QString toListName)
Checks that the output image list is correct.
bool m_wtopt
Whether or not overlaps should be weighted.
virtual void errorCheck(QString fromListName)
Checks that the input images have the same mapping groups and same number of bands.
vector< OverlapNormalization * > m_overlapNorms
Normalization data for input images.
void calculateStatistics(double samplingPercent, int mincnt, bool wtopt, LeastSquares::SolveMethod methodType)
Calculates the image and overlap statistics, and then determines corrective factors if possible.
LeastSquares::SolveMethod m_lsqMethod
Least squares method for solving normalization correcitve factors.
PvlGroup getResults()
Returns general information about the equalization.
void addAdjustment(ImageAdjustment *adjustment)
Adds an image adjustment.
void fromPvl(const PvlObject &inStats)
Loads a previous Equalization state from an input pvl object.
void applyCorrection(QString toListName)
Equalizes the input images.
void setSolved(bool solved)
Sets solved state indicating if OverlapNormalizations (corrective factors) were solved.
void clearNormalizations()
Frees overlap normalizations.
int m_maxBand
Number of bands in each input image.
bool m_normsSolved
Indicates if corrective factors were solved.
void clearOverlapStatistics()
Frees overlap statistics.
void recalculateStatistics(QString inStatsFileName)
Recalculates statistics for any new input images.
vector< int > m_holdIndices
Indices of images being held.
void addInvalid(int count)
Increments the number of invalid overlaps by a given amount.
OverlapNormalization::SolutionType m_sType
The normalization solution type for solving normalizations (offsets, gains, or both)
void init()
Initializes member variables to default values.
int m_mincnt
Minimum number of pixels for an overlap to be considered valid.
int m_invalidCnt
Number of invalid overlaps.
bool m_recalculating
Indicates if recalculating with loaded statistics.
void write(QString outstatsFileName)
Write the equalization information (results) to a file.
void addHolds(QString holdListName)
Adds a list of images to be held in the equalization.
void loadInputs(QString fromListName)
Loads in the input images.
double m_samplingPercent
Percentage of the lines to consider when gathering cube and overlap statistics (process-by-line)
Equalization()
Default constructor.
void addValid(int count)
Increments the number of valid overlaps by a given amount.
Pvl * m_results
Calculation results and normalization corrective factors (if solved)
vector< bool > m_doesOverlapList
Which images have a valid overlap.
bool isSolved() const
Indicates if the corrective factors were solved.
int m_maxCube
Number of input images.
void calculateOverlapStatistics()
Calculates the overlap statistics for each pair of input images.
vector< OverlapStatistics * > m_overlapStats
Calculated overlap statistics.
QStringList m_badFiles
List of image names that don't overlap.
void setResults()
Creates the results pvl containing statistics and corrective factors.
vector< bool > m_alreadyCalculated
Which images that have statistics already calculated.
virtual ~Equalization()
Destructor.
QVector< int > validateInputStatistics(QString instatsFileName)
Validates the input statistics pvl file.
int m_validCnt
Number of valid overlaps.
Internalizes a list of files.
void read(FileName listFile)
reads in a FileName obj
File name manipulation and expansion.
QString path() const
Returns the path of the file name.
QString baseName() const
Returns the name of the file without the path and without extensions.
QString extension() const
Returns the last extension of the file name.
@ Unknown
A type of error that cannot be classified as any of the other error types.
@ User
A type of error that could only have occurred due to a mistake on the user's part (e....
Isis::Statistics Y() const
Returns a Stats object for all of the Y data fed through the AddData method.
BigInt ValidPixels() const
Returns the number of valid pixels processed.
Isis::Statistics X() const
Returns a Stats object for all of the X data fed through the AddData method.
Calculate the bases and multipliers for normalizing overlapping "data sets" (e.g.,...
void AddHold(unsigned holdIndex)
Sets the list of files to be held during the solving process.
SolutionType
Enumeration for whether user/programmer wants to calculate new gains, offsets, or both when solving.
@ Offsets
Calculate only the offsets.
@ Both
Calculate both gains and offsets.
@ Gains
Calculate only the gains.
@ GainsWithoutNormalization
The equation being solved for Gains, Offsets, and Both is output = (input - average) * gain + offset ...
Calculates statistics in the area of overlap between two projected cubes.
Isis::FileName FileNameY() const
Returns the filename of the second cube.
bool HasOverlap(int band) const
Checks the specified band for an overlap.
int Bands() const
Returns the number of bands both cubes have.
Isis::MultivariateStatistics GetMStats(int band) const
Returns the MultivariateStatistics object containing all the data from both cubes in the overlapping ...
Isis::FileName FileNameX() const
Returns the filename of the first cube.
void SetMincount(unsigned int mincnt)
Sets the minimum number of valid pixels for the overlap to be considered valid for PVL output.
void EndProcess()
End the processing sequence and cleans up by closing cubes, freeing memory, etc.
virtual Cube * SetOutputCube(const QString &fname, const CubeAttributeOutput &att)
Create the output file.
Isis::Cube * SetInputCube(const QString ¶meter, const int requirements=0)
Opens an input cube specified by the user and verifies requirements are met.
void ProcessCube(const Functor &funct, bool threaded=true)
Same functionality as StartProcess(void funct(Isis::Buffer &in, Isis::Buffer &out)) using Functors.
void ProcessCubeInPlace(const Functor &funct, bool threaded=true)
Same functionality as StartProcess(void funct(Isis::Buffer &inout)) using Functors.
Isis::Progress * Progress()
This method returns a pointer to a Progress object.
void SetText(const QString &text)
Changes the value of the text string reported just before 0% processed.
Base class for Map Projections.
bool hasKeyword(const QString &name) const
Check to see if a keyword exists.
int keywords() const
Returns the number of keywords contained in the PvlContainer.
Contains multiple PvlContainers.
Container for cube-like labels.
A single keyword-value pair.
Contains Pvl Groups and Pvl Objects.
PvlObjectIterator beginObject()
Returns the index of the beginning object.
PvlGroup & group(const int index)
Return the group at the specified index.
int groups() const
Returns the number of groups contained.
PvlObjectIterator findObject(const QString &name, PvlObjectIterator beg, PvlObjectIterator end)
Find the index of object with a specified name, between two indexes.
PvlObjectIterator endObject()
Returns the index of the ending object.
void addGroup(const Isis::PvlGroup &group)
Add a group to the object.
PvlGroupIterator findGroup(const QString &name, PvlGroupIterator beg, PvlGroupIterator end)
Find a group with the specified name, within these indexes.
This class is used to accumulate statistics on double arrays.
This is free and unencumbered software released into the public domain.
This is free and unencumbered software released into the public domain.
This is free and unencumbered software released into the public domain.
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
bool IsSpecial(const double d)
Returns if the input pixel is special.
double toDouble(const QString &string)
Global function to convert from a string to a double.
Namespace for the standard library.