34 Equalization::Equalization() {
50 loadInputs(fromListName);
57 Equalization::~Equalization() {
59 clearNormalizations();
60 clearOverlapStatistics();
62 if (m_results != NULL) {
78 void Equalization::addHolds(QString holdListName) {
82 if (holdList.size() > m_imageList.size()) {
83 QString msg =
"The list of identifiers to be held must be less than or ";
84 msg +=
"equal to the total number of identitifers.";
89 for (
int i = 0; i < holdList.size(); i++) {
91 for (
int j = 0; j < m_imageList.size(); j++) {
92 if (holdList[i] == m_imageList[j]) {
94 m_holdIndices.push_back(j);
99 QString msg =
"The hold list file [" + holdList[i].toString() +
100 "] does not match a file in the from list";
130 void Equalization::calculateStatistics(
double percent,
int mincnt,
bool wtopt,
137 m_samplingPercent = percent;
139 m_lsqMethod = methodType;
142 if (!m_recalculating) {
143 calculateBandStatistics();
146 calculateOverlapStatistics();
149 for (
int img = 0; img < m_imageList.size(); img++) {
151 if (!m_doesOverlapList[img]) {
152 m_badFiles += m_imageList[img].toString();
155 if (!m_badFiles.isEmpty()) {
161 msg =
"There are input images that do not overlap with enough valid pixels. ";
162 msg +=
"See application log or \"NonOverlaps\" keyword in output statistics file.";
168 for (
int band = 0; band < m_maxBand; band++) {
169 m_overlapNorms[band]->Solve(m_sType, methodType);
171 for (
unsigned int img = 0; img < m_adjustments.size(); img++) {
172 m_adjustments[img]->addGain(m_overlapNorms[band]->Gain(img));
173 if (qFuzzyCompare(m_overlapNorms[band]->Gain(img), 0.0)) {
175 cout << band << endl;
176 cout << m_overlapNorms[band]->Gain(img) << endl;
179 "Calculation for equalization statistics failed. Gain = 0.",
182 m_adjustments[img]->addOffset(m_overlapNorms[band]->Offset(img));
183 m_adjustments[img]->addAverage(m_overlapNorms[band]->
Average(img));
186 m_normsSolved =
true;
190 QString msg =
"Unable to calculate the equalization statistics. You may " 191 "want to try another LeastSquares::SolveMethod.";
206 void Equalization::calculateBandStatistics() {
209 for (
int band = 1; band <= m_maxBand; band++) {
211 vector<Statistics *> statsList;
212 for (
int img = 0; img < (int) m_imageList.size(); img++) {
215 QString statMsg =
"Calculating Statistics for Band " + bandStr +
220 QString inp = m_imageList[img].toString();
229 statsList.push_back(stats);
235 m_overlapNorms.push_back(oNorm);
246 void Equalization::calculateOverlapStatistics() {
248 for (
int img = 0; img < m_imageList.size(); img++) {
254 for (
int i = 0; i < m_imageList.size(); i++) {
258 for (
int j = (i + 1); j < m_imageList.size(); j++) {
260 if (m_alreadyCalculated[i] ==
true && m_alreadyCalculated[j] ==
true) {
269 QString cubeStr1 =
toString((
int)(i + 1));
270 QString cubeStr2 =
toString((
int)(j + 1));
271 QString statMsg =
"Gathering Overlap Statisitcs for Cube " +
272 cubeStr1 +
" vs " + cubeStr2 +
" of " +
280 m_overlapStats.push_back(oStats);
282 for (
int band = 1; band <= m_maxBand; band++) {
290 m_overlapNorms[band - 1]->AddOverlap(
293 m_doesOverlapList[i] =
true;
294 m_doesOverlapList[j] =
true;
302 for (
unsigned int o = 0; o < m_overlapStats.size(); o++) {
303 for (
int band = 1; band <= m_maxBand; band++) {
304 (m_overlapStats[o]->IsValid(band)) ? m_validCnt++ : m_invalidCnt++;
318 void Equalization::setResults() {
319 if (m_results != NULL) {
324 m_results =
new Pvl();
325 m_results->setTerminator(
"");
327 PvlObject equ(
"EqualizationInformation");
334 gen +=
PvlKeyword(
"Weighted", (m_wtopt) ?
"true" :
"false");
335 int solType = m_sType;
336 int lsqMethod = m_lsqMethod;
340 for (
int img = 0; img < m_badFiles.size(); img++) {
341 nonOverlaps += m_badFiles[img];
344 gen +=
PvlKeyword(
"HasCorrections", (m_normsSolved) ?
"true" :
"false");
348 for (
int img = 0; img < m_imageList.size(); img++) {
351 norm.addComment(
"Formula: newDN = (oldDN - AVERAGE) * GAIN + AVERAGE + OFFSET");
352 norm.addComment(
"BandN = (GAIN, OFFSET, AVERAGE)");
353 norm +=
PvlKeyword(
"FileName", m_imageList[img].original());
357 for (
int band = 1; band <= m_maxBand; band++) {
358 QString mult =
toString(m_adjustments[img]->getGain(band - 1));
359 QString base =
toString(m_adjustments[img]->getOffset(band - 1));
360 QString avg =
toString(m_adjustments[img]->getAverage(band - 1));
362 QString bandStr =
"Band" + bandNum;
374 m_results->addObject(equ);
377 for (
unsigned int i = 0; i < m_overlapStats.size(); i++) {
378 PvlObject oStat = m_overlapStats[i]->toPvl();
379 m_results->
addObject(m_overlapStats[i]->toPvl());
393 void Equalization::recalculateStatistics(QString instatsFileName) {
394 m_recalculating =
true;
395 Pvl inStats(instatsFileName);
397 calculateStatistics(m_samplingPercent, m_mincnt, m_wtopt, m_lsqMethod);
412 void Equalization::importStatistics(QString instatsFileName) {
415 QVector<int> normIndices = validateInputStatistics(instatsFileName);
416 Pvl inStats(instatsFileName);
422 if (!general.
hasKeyword(
"HasCorrections") || general[
"HasCorrections"][0] ==
"true") {
423 m_normsSolved =
true;
426 for (
int img = 0; img < (int) m_imageList.size(); img++) {
435 for (
int band = 1; band < normalization.
keywords(); band++) {
436 adjustment->addGain(
toDouble(normalization[band][0]));
437 adjustment->addOffset(
toDouble(normalization[band][1]));
438 adjustment->addAverage(
toDouble(normalization[band][2]));
441 addAdjustment(adjustment);
445 m_normsSolved =
false;
461 void Equalization::applyCorrection(QString toListName=
"") {
463 QString msg =
"Corrective factors have not yet been determined. ";
464 if (m_badFiles.size() > 0) {
465 msg +=
"Fix any non-overlapping images and recalculate the image statistics. ";
466 msg +=
"File(s) without overlaps: ";
467 for (
int img = 0; img < m_badFiles.size(); img++) {
468 msg +=
" [" + m_badFiles[img] +
"] ";
472 msg +=
"Add more images to create more overlaps and recalculate, ";
473 msg +=
"or try another solve method.";
479 fillOutList(outList, toListName);
481 QString maxCubeStr =
toString((
int) m_imageList.size());
482 for (
int img = 0; img < m_imageList.size(); img++) {
486 " of " + maxCubeStr);
490 const QString inp = m_imageList[img].toString();
494 QString out = outList[img].toString();
516 PvlGroup results = m_results->findObject(
"EqualizationInformation").findGroup(
"General");
520 for (
int img = 0; img < m_imageList.size(); img++) {
524 for (
int band = 1; band <= m_maxBand; band++) {
525 QString mult =
toString(m_adjustments[img]->getGain(band - 1));
526 QString base =
toString(m_adjustments[img]->getOffset(band - 1));
527 QString avg =
toString(m_adjustments[img]->getAverage(band - 1));
529 QString bandStr =
"Band" + bandNum;
534 results += bandStats;
547 void Equalization::write(QString outstatsFileName) {
549 m_results->write(outstatsFileName);
553 double Equalization::evaluate(
double dn,
int imageIndex,
int bandIndex)
const {
554 return m_adjustments[imageIndex]->evaluate(dn, bandIndex);
567 void Equalization::loadInputs(QString fromListName) {
569 m_imageList.read(fromListName);
570 m_maxCube = m_imageList.size();
572 if (m_imageList.size() < 2) {
573 QString msg =
"The input file [" + fromListName +
574 "] must contain at least 2 file names";
582 m_doesOverlapList.resize(m_imageList.size(),
false);
583 m_alreadyCalculated.resize(m_imageList.size(),
false);
585 errorCheck(fromListName);
589 void Equalization::setInput(
int index, QString value) {
590 m_imageList[index] = value;
594 const FileList &Equalization::getInputs()
const {
599 void Equalization::fillOutList(FileList &outList, QString toListName) {
600 if (toListName.isEmpty()) {
601 generateOutputs(outList);
604 loadOutputs(outList, toListName);
615 void Equalization::errorCheck(QString fromListName) {
616 for (
int i = 0; i < m_imageList.size(); i++) {
620 for (
int j = (i + 1); j < m_imageList.size(); j++) {
626 QString msg =
"Number of bands do not match between cubes [" +
627 m_imageList[i].toString() +
"] and [" + m_imageList[j].toString() +
"]";
636 if (*proj1 != *proj2) {
637 QString msg =
"Mapping groups do not match between cubes [" +
638 m_imageList[i].toString() +
"] and [" + m_imageList[j].toString() +
"]";
649 void Equalization::generateOutputs(
FileList &outList) {
650 for (
int img = 0; img < m_imageList.size(); img++) {
652 QString filename = file.
path() +
"/" + file.
baseName() +
654 outList.push_back(
FileName(filename));
667 void Equalization::loadOutputs(
FileList &outList, QString toListName) {
671 if (outList.size() != m_imageList.size()) {
672 QString msg =
"Each input file in the FROM LIST must have a ";
673 msg +=
"corresponding output file in the TO LIST.";
679 for (
int i = 0; i < outList.size(); i++) {
681 QString msg =
"The to list file [" + outList[i].toString() +
682 "] has the same name as its corresponding from list file.";
690 for (
unsigned int h = 0; h < m_holdIndices.size(); h++)
691 oNorm->
AddHold(m_holdIndices[h]);
698 void Equalization::clearAdjustments() {
699 for (
unsigned int adj = 0; adj < m_adjustments.size(); adj++) {
700 delete m_adjustments[adj];
702 m_adjustments.clear();
714 m_adjustments.push_back(adjustment);
721 void Equalization::clearNormalizations() {
722 for (
unsigned int oNorm = 0; oNorm < m_overlapNorms.size(); oNorm++) {
723 delete m_overlapNorms[oNorm];
725 m_overlapNorms.clear();
732 void Equalization::clearOverlapStatistics() {
733 for (
unsigned int oStat = 0; oStat < m_overlapStats.size(); oStat++) {
734 delete m_overlapStats[oStat];
736 m_overlapStats.clear();
745 void Equalization::addValid(
int count) {
755 void Equalization::addInvalid(
int count) {
756 m_invalidCnt += count;
772 for (
int img = 0; img < m_imageList.size(); img++) {
773 imgNames.append(m_imageList[img].name());
779 m_samplingPercent = eqGen[
"SamplingPercent"];
780 m_mincnt = eqGen[
"MinCount"];
781 m_wtopt = (eqGen[
"Weighted"][0] ==
"true") ?
true :
false;
786 PvlObject::ConstPvlObjectIterator curObj = inStats.
beginObject();
788 if (curObj->isNamed(
"OverlapStatistics")) {
790 m_overlapStats.push_back(o);
793 QString fileX = oStat[
"File1"][0];
794 QString fileY = oStat[
"File2"][0];
797 int x = imgNames.indexOf(fileX);
798 int y = imgNames.indexOf(fileY);
799 m_alreadyCalculated[x] =
true;
800 m_alreadyCalculated[y] =
true;
804 if (oStat[
"Valid"][0] ==
"true") {
805 m_doesOverlapList[x] =
true;
806 m_doesOverlapList[y] =
true;
813 calculateBandStatistics();
821 for (
int o = 0; o < (int) m_overlapStats.size(); o++) {
828 for (
int i = 0; i < m_imageList.size(); i++) {
829 QString imageName(m_imageList[i].name());
835 overlapIndices[o].push_front(i);
840 overlapIndices[o].push_back(i);
845 for (
int o = 0; o < (int) m_overlapStats.size(); o++) {
847 for (
int band = 1; band <= oStat->
Bands(); band++) {
851 m_overlapNorms[band-1]->AddOverlap(oStat->
GetMStats(band).
X(), overlapIndices[o][0],
852 oStat->
GetMStats(band).
Y(), overlapIndices[o][1], weight);
864 void Equalization::setSolved(
bool solved) {
865 m_normsSolved = solved;
874 bool Equalization::isSolved()
const {
875 return m_normsSolved;
882 void Equalization::init() {
887 m_samplingPercent = 100.0;
893 m_sType = OverlapNormalization::Both;
894 m_lsqMethod = LeastSquares::SPARSE;
897 m_doesOverlapList.clear();
898 m_alreadyCalculated.clear();
899 m_normsSolved =
false;
900 m_recalculating =
false;
921 QVector<int> Equalization::validateInputStatistics(QString instatsFileName) {
924 Pvl inStats(instatsFileName);
928 if (m_imageList.size() > equalInfo.
groups() - 1) {
929 QString msg =
"Each input file in the FROM LIST must have a ";
930 msg +=
"corresponding input file in the INPUT STATISTICS.";
935 for (
int i = 0; i < m_imageList.size(); i++) {
936 QString fromFile = m_imageList[i].original();
937 bool foundFile =
false;
938 for (
int j = 1; j < equalInfo.
groups(); j++) {
940 QString normFile = normalization[
"FileName"][0];
941 if (fromFile == normFile) {
945 normIndices.push_back(j);
950 QString msg =
"The from list file [" + fromFile +
951 "] does not have any corresponding file in the stats list.";
960 void Equalization::CalculateFunctor::operator()(
Buffer &in)
const {
968 void Equalization::CalculateFunctor::addStats(Buffer &in)
const {
970 m_stats->AddData(&in[0], in.size());
974 void Equalization::ApplyFunctor::operator()(Buffer &in, Buffer &out)
const {
975 int index = in.Band() - 1;
976 for (
int i = 0; i < in.size(); i++) {
978 in[i] : m_adjustment->evaluate(in[i], index);
Buffer for reading and writing cube data.
void SetMincount(unsigned int mincnt)
Sets the minimum number of valid pixels for the overlap to be considered valid for PVL output...
int keywords() const
Returns the number of keywords contained in the PvlContainer.
Isis::Statistics Y() const
Returns a Stats object for all of the Y data fed through the AddData method.
QString path() const
Returns the path of the file name.
bool hasKeyword(const QString &name) const
Check to see if a keyword exists.
void ProcessCubeInPlace(const Functor &funct, bool threaded=true)
Same functionality as StartProcess(void funct(Isis::Buffer &inout)) using Functors.
Isis::FileName FileNameX() const
Returns the filename of the first cube.
void EndProcess()
End the processing sequence and cleans up by closing cubes, freeing memory, etc.
This class is used as a functor calculate image statistics.
PvlGroupIterator findGroup(const QString &name, PvlGroupIterator beg, PvlGroupIterator end)
Find a group with the specified name, within these indexes.
PvlObjectIterator endObject()
Returns the index of the ending object.
Isis::Cube * SetInputCube(const QString ¶meter, const int requirements=0)
Opens an input cube specified by the user and verifies requirements are met.
File name manipulation and expansion.
PvlObjectIterator findObject(const QString &name, PvlObjectIterator beg, PvlObjectIterator end)
Find the index of object with a specified name, between two indexes.
BigInt ValidPixels() const
Returns the number of valid pixels processed.
virtual Cube * SetOutputCube(const QString &fname, const CubeAttributeOutput &att)
Create the output file.
void addGroup(const Isis::PvlGroup &group)
Add a group to the object.
Namespace for the standard library.
Internalizes a list of files.
SolutionType
Enumeration for whether user/programmer wants to calculate new gains, offsets, or both when solving...
Isis::Statistics X() const
Returns a Stats object for all of the X data fed through the AddData method.
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Projection * projection()
This class is used as a functor to apply adjustments (equalize) to an image.
int LineDimension() const
Returns the number of lines in the shape buffer.
double toDouble(const QString &string)
Global function to convert from a string to a double.
void AddHold(unsigned holdIndex)
Sets the list of files to be held during the solving process.
void addObject(const PvlObject &object)
Add a PvlObject.
This class is used to accumulate statistics on double arrays.
Base class for Map Projections.
Calculate the bases and multipliers for normalizing overlapping "data sets" (e.g., cubes).
Isis::MultivariateStatistics GetMStats(int band) const
Returns the MultivariateStatistics object containing all the data from both cubes in the overlapping ...
void read(FileName listFile)
reads in a FileName obj
void SetText(const QString &text)
Changes the value of the text string reported just before 0% processed.
Contains multiple PvlContainers.
#define _FILEINFO_
Macro for the filename and line number.
Manipulate and parse attributes of output cube filenames.
A single keyword-value pair.
int Line(const int index=0) const
Returns the line position associated with a shape buffer index.
bool IsSpecial(const double d)
Returns if the input pixel is special.
void open(const QString &cfile, QString access="r")
This method will open an isis cube for reading or reading/writing.
Container for cube-like labels.
Isis::Progress * Progress()
This method returns a pointer to a Progress object.
bool HasOverlap(int band) const
Checks the specified band for an overlap.
QString baseName() const
Returns the name of the file without the path and without extensions.
Calculates statistics in the area of overlap between two projected cubes.
PvlGroup & group(const int index)
Return the group at the specified index.
void ProcessCube(const Functor &funct, bool threaded=true)
Same functionality as StartProcess(void funct(Isis::Buffer &in, Isis::Buffer &out)) using Functors...
int Bands() const
Returns the number of bands both cubes have.
Namespace for ISIS/Bullet specific routines.
virtual int bandCount() const
Returns the number of virtual bands for the cube.
QString extension() const
Returns the last extension of the file name.
int groups() const
Returns the number of groups contained.
Contains Pvl Groups and Pvl Objects.
PvlObjectIterator beginObject()
Returns the index of the beginning object.
Isis::FileName FileNameY() const
Returns the filename of the second cube.
Functor for reduce using average functionality.
IO Handler for Isis Cubes.