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"
86 holdList.
read(FileName(holdListName));
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.";
91 throw IException(IException::User, msg, _FILEINFO_);
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";
107 throw IException(IException::User, msg, _FILEINFO_);
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.";
169 throw IException(IException::User, msg, _FILEINFO_);
174 for (
int band = 0; band <
m_maxBand; band++) {
177 for (
unsigned int img = 0; img < m_adjustments.size(); img++) {
181 cout << band << endl;
184 throw IException(IException::Unknown,
185 "Calculation for equalization statistics failed. Gain = 0.",
194 catch (IException &e) {
196 QString msg =
"Unable to calculate the equalization statistics. You may "
197 "want to try another LeastSquares::SolveMethod.";
198 throw IException(e, IException::Unknown, msg, _FILEINFO_);
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");
334 PvlGroup gen(
"General");
340 gen += PvlKeyword(
"Weighted", (
m_wtopt) ?
"true" :
"false");
343 gen += PvlKeyword(
"SolutionType",
toString(solType));
344 gen += PvlKeyword(
"SolveMethod" ,
toString(lsqMethod));
345 PvlKeyword nonOverlaps(
"NonOverlaps");
346 for (
int img = 0; img <
m_badFiles.size(); img++) {
350 gen += PvlKeyword(
"HasCorrections", (
m_normsSolved) ?
"true" :
"false");
354 for (
int img = 0; img < m_imageList.size(); img++) {
358 PvlGroup norm(
"Normalization");
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;
384 PvlKeyword bandStats(bandStr);
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);
452 PvlObject &equalInfo = inStats.findObject(
"EqualizationInformation");
453 PvlGroup &general = equalInfo.findGroup(
"General");
457 if (!general.hasKeyword(
"HasCorrections") || general[
"HasCorrections"][0] ==
"true") {
461 for (
int img = 0; img < (int) m_imageList.size(); img++) {
463 PvlGroup &normalization = equalInfo.group(normIndices[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.";
510 throw IException(IException::User, msg, _FILEINFO_);
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++) {
556 results += PvlKeyword(
"FileName", m_imageList[img].
toString());
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;
565 PvlKeyword bandStats(bandStr);
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";
610 throw IException(IException::User, msg, _FILEINFO_);
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() +
"]";
663 throw IException(IException::User, msg, _FILEINFO_);
671 if (*proj1 != *proj2) {
672 QString msg =
"Mapping groups do not match between cubes [" +
673 m_imageList[i].toString() +
"] and [" + m_imageList[j].toString() +
"]";
674 throw IException(IException::User, msg, _FILEINFO_);
685 for (
int img = 0; img < m_imageList.size(); img++) {
686 FileName file(m_imageList[img]);
687 QString filename = file.path() +
"/" + file.baseName() +
688 ".equ." + file.extension();
689 outList.push_back(FileName(filename));
703 outList.
read(FileName(toListName));
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.";
709 throw IException(IException::User, msg, _FILEINFO_);
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.";
718 throw IException(IException::User, msg, _FILEINFO_);
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());
812 const PvlObject &eqInfo = inStats.findObject(
"EqualizationInformation");
813 const PvlGroup &eqGen = eqInfo.findGroup(
"General");
816 m_wtopt = (eqGen[
"Weighted"][0] ==
"true") ?
true :
false;
821 PvlObject::ConstPvlObjectIterator curObj = inStats.beginObject();
822 while (curObj != inStats.endObject()) {
823 if (curObj->isNamed(
"OverlapStatistics")) {
827 const PvlObject &oStat = *curObj;
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);
960 PvlObject &equalInfo = inStats.findObject(
"EqualizationInformation");
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.";
966 throw IException(IException::User, msg, _FILEINFO_);
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++) {
974 PvlGroup &normalization = equalInfo.group(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.";
987 throw IException(IException::User, msg, _FILEINFO_);
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++) {
1012 out[i] = (IsSpecial(in[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 try to open a file as either a cube or geotiff in either read or read/write.
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
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.
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.
QString toString(const LinearAlgebra::Vector &vector, int precision)
A global function to format LinearAlgebra::Vector as a QString with the given precision.
Namespace for the standard library.