Isis 3 Programmer Reference
Equalization.cpp
1 #include "Equalization.h"
2 
3 #include <iomanip>
4 #include <vector>
5 
6 #include <QString>
7 #include <QStringList>
8 #include <QVector>
9 
10 #include "Buffer.h"
11 #include "Cube.h"
12 #include "FileList.h"
13 #include "IException.h"
14 #include "LeastSquares.h"
15 #include "LineManager.h"
16 #include "OverlapNormalization.h"
17 #include "OverlapStatistics.h"
18 #include "Process.h"
19 #include "ProcessByLine.h"
20 #include "Projection.h"
21 #include "Pvl.h"
22 #include "PvlGroup.h"
23 #include "PvlObject.h"
24 #include "Statistics.h"
25 
26 using namespace std;
27 
28 namespace Isis {
29 
30 
34  Equalization::Equalization() {
35  init();
36  }
37 
38 
46  Equalization::Equalization(OverlapNormalization::SolutionType sType, QString fromListName) {
47  init();
48 
49  m_sType = sType;
50  loadInputs(fromListName);
51  }
52 
53 
57  Equalization::~Equalization() {
58  clearAdjustments();
59  clearNormalizations();
60  clearOverlapStatistics();
61 
62  if (m_results != NULL) {
63  delete m_results;
64  m_results = NULL;
65  }
66  }
67 
68 
78  void Equalization::addHolds(QString holdListName) {
79  FileList holdList;
80  holdList.read(FileName(holdListName));
81 
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.";
85  throw IException(IException::User, msg, _FILEINFO_);
86  }
87 
88  // Make sure each file in the holdlist matches a file in the fromlist
89  for (int i = 0; i < holdList.size(); i++) {
90  bool matched = false;
91  for (int j = 0; j < m_imageList.size(); j++) {
92  if (holdList[i] == m_imageList[j]) {
93  matched = true;
94  m_holdIndices.push_back(j);
95  break;
96  }
97  }
98  if (!matched) {
99  QString msg = "The hold list file [" + holdList[i].toString() +
100  "] does not match a file in the from list";
101  throw IException(IException::User, msg, _FILEINFO_);
102  }
103  }
104  }
105 
106 
130  void Equalization::calculateStatistics(double percent, int mincnt, bool wtopt,
131  LeastSquares::SolveMethod methodType) {
132 
133  // We're going to redetermine which file are non-overlapping (if recalculating)
134  m_badFiles.clear();
135 
136  m_mincnt = mincnt;
137  m_samplingPercent = percent;
138  m_wtopt = wtopt;
139  m_lsqMethod = methodType;
140 
141  // Calculate statistics for each image+band (they've already been calculated if recalculating)
142  if (!m_recalculating) {
143  calculateBandStatistics();
144  }
145 
146  calculateOverlapStatistics();
147 
148  // We can't solve the normalizations if we have invalid overlaps
149  for (int img = 0; img < m_imageList.size(); img++) {
150  // Record name of each input cube without an overlap
151  if (!m_doesOverlapList[img]) {
152  m_badFiles += m_imageList[img].toString();
153  }
154  }
155  if (!m_badFiles.isEmpty()) {
156  // Make sure we set the results for the already calculated overlap statistics
157  setResults();
158 
159  QString msg;
160  // Let user know where to find list of non-overlapping files so they can make corrections.
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.";
163  throw IException(IException::User, msg, _FILEINFO_);
164  }
165 
166  // Loop through each band making all necessary calculations
167  try {
168  for (int band = 0; band < m_maxBand; band++) {
169  m_overlapNorms[band]->Solve(m_sType, methodType);
170 
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)) { // if gain == 0
174  cout << img << endl;
175  cout << band << endl;
176  cout << m_overlapNorms[band]->Gain(img) << endl;
177  setResults();
178  throw IException(IException::Unknown,
179  "Calculation for equalization statistics failed. Gain = 0.",
180  _FILEINFO_);
181  }
182  m_adjustments[img]->addOffset(m_overlapNorms[band]->Offset(img));
183  m_adjustments[img]->addAverage(m_overlapNorms[band]->Average(img));
184  }
185  }
186  m_normsSolved = true;
187  }
188  catch (IException &e) {
189  setResults();
190  QString msg = "Unable to calculate the equalization statistics. You may "
191  "want to try another LeastSquares::SolveMethod.";
192  throw IException(e, IException::Unknown, msg, _FILEINFO_);
193  }
194 
195  setResults();
196  }
197 
198 
206  void Equalization::calculateBandStatistics() {
207  // Loop through all the input cubes, calculating statistics for each cube
208  // to use later
209  for (int band = 1; band <= m_maxBand; band++) {
210  // OverlapNormalization will take ownership of these pointers
211  vector<Statistics *> statsList;
212  for (int img = 0; img < (int) m_imageList.size(); img++) {
213  ProcessByLine p;
214  QString bandStr(toString(band));
215  QString statMsg = "Calculating Statistics for Band " + bandStr +
216  " of " + toString(m_maxBand) + " in Cube " + toString(img + 1) +
217  " of " + toString(m_maxCube);
218  p.Progress()->SetText(statMsg);
219  CubeAttributeInput att("+" + bandStr);
220  QString inp = m_imageList[img].toString();
221  p.SetInputCube(inp, att);
222 
223  Statistics *stats = new Statistics();
224 
225  CalculateFunctor func(stats, m_samplingPercent);
226  p.ProcessCubeInPlace(func, false);
227  p.EndProcess();
228 
229  statsList.push_back(stats);
230  }
231 
232  // Create a separate OverlapNormalization object for every band
233  OverlapNormalization *oNorm = new OverlapNormalization(statsList);
234  loadHolds(oNorm);
235  m_overlapNorms.push_back(oNorm);
236  }
237  }
238 
239 
246  void Equalization::calculateOverlapStatistics() {
247  // Add adjustments for all input images
248  for (int img = 0; img < m_imageList.size(); img++) {
249  addAdjustment(new ImageAdjustment(m_sType));
250  }
251 
252  // Find overlapping areas and add them to the set of known overlaps for
253  // each band shared amongst cubes
254  for (int i = 0; i < m_imageList.size(); i++) {
255  Cube cube1;
256  cube1.open(m_imageList[i].toString());
257 
258  for (int j = (i + 1); j < m_imageList.size(); j++) {
259  // Skip if overlap already calculated
260  if (m_alreadyCalculated[i] == true && m_alreadyCalculated[j] == true) {
261  //cout << " *** Cube " << i << " vs Cube " << j << " already calculated." << endl;
262  //cout << endl << " " << i << " = " << m_imageList[i].toString() << " ; " << j
263  // << " = " << m_imageList[j].toString() << endl << endl;
264  continue;
265  }
266 
267  Cube cube2;
268  cube2.open(m_imageList[j].toString());
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 " +
273  toString(m_maxCube);
274 
275  // Get overlap statistics for new cubes
276  OverlapStatistics *oStats = new OverlapStatistics(cube1, cube2, statMsg, m_samplingPercent);
277  // Only push the stats onto the overlap statistics vector if there is an overlap in at
278  // least one of the bands
279  if (oStats->HasOverlap()) {
280  m_overlapStats.push_back(oStats);
281  oStats->SetMincount(m_mincnt);
282  for (int band = 1; band <= m_maxBand; band++) {
283  // Fill wt vector with 1's if the overlaps are not to be weighted, or
284  // fill the vector with the number of valid pixels in each overlap
285  int weight = 1;
286  if (m_wtopt) weight = oStats->GetMStats(band).ValidPixels();
287 
288  // Make sure overlap has at least MINCOUNT valid pixels and add
289  if (oStats->GetMStats(band).ValidPixels() >= m_mincnt) {
290  m_overlapNorms[band - 1]->AddOverlap(
291  oStats->GetMStats(band).X(), i,
292  oStats->GetMStats(band).Y(), j, weight);
293  m_doesOverlapList[i] = true;
294  m_doesOverlapList[j] = true;
295  }
296  }
297  }
298  }
299  }
300 
301  // Compute the number valid and invalid overlaps
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++;
305  }
306  }
307  }
308 
309 
318  void Equalization::setResults() {
319  if (m_results != NULL) {
320  delete m_results;
321  m_results = NULL;
322  }
323 
324  m_results = new Pvl();
325  m_results->setTerminator("");
326 
327  PvlObject equ("EqualizationInformation");
328  PvlGroup gen("General");
329  gen += PvlKeyword("TotalOverlaps", toString(m_validCnt + m_invalidCnt));
330  gen += PvlKeyword("ValidOverlaps", toString(m_validCnt));
331  gen += PvlKeyword("InvalidOverlaps", toString(m_invalidCnt));
332  gen += PvlKeyword("MinCount", toString(m_mincnt));
333  gen += PvlKeyword("SamplingPercent", toString(m_samplingPercent));
334  gen += PvlKeyword("Weighted", (m_wtopt) ? "true" : "false");
335  int solType = m_sType;
336  int lsqMethod = m_lsqMethod;
337  gen += PvlKeyword("SolutionType", toString(solType));
338  gen += PvlKeyword("SolveMethod" , toString(lsqMethod));
339  PvlKeyword nonOverlaps("NonOverlaps");
340  for (int img = 0; img < m_badFiles.size(); img++) {
341  nonOverlaps += m_badFiles[img];
342  }
343  gen += nonOverlaps;
344  gen += PvlKeyword("HasCorrections", (m_normsSolved) ? "true" : "false");
345  equ.addGroup(gen);
346 
347  // Add normalization statistics
348  for (int img = 0; img < m_imageList.size(); img++) {
349  // Format and name information
350  PvlGroup norm("Normalization");
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());
354 
355  if (m_normsSolved) {
356  // Band by band statistics
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));
361  QString bandNum = toString(band);
362  QString bandStr = "Band" + bandNum;
363  PvlKeyword bandStats(bandStr);
364  bandStats += mult;
365  bandStats += base;
366  bandStats += avg;
367  norm += bandStats;
368  }
369  }
370 
371  equ.addGroup(norm);
372  }
373 
374  m_results->addObject(equ);
375 
376  // Add overlap statistics
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());
380  }
381  }
382 
383 
393  void Equalization::recalculateStatistics(QString instatsFileName) {
394  m_recalculating = true;
395  Pvl inStats(instatsFileName);
396  fromPvl(inStats);
397  calculateStatistics(m_samplingPercent, m_mincnt, m_wtopt, m_lsqMethod);
398  }
399 
400 
412  void Equalization::importStatistics(QString instatsFileName) {
413 
414  // Check for errors with the input statistics
415  QVector<int> normIndices = validateInputStatistics(instatsFileName);
416  Pvl inStats(instatsFileName);
417  PvlObject &equalInfo = inStats.findObject("EqualizationInformation");
418  PvlGroup &general = equalInfo.findGroup("General");
419 
420  // Determine if normalizations were solved
421  // First condition allows backward compatibility so users can use old stats files
422  if (!general.hasKeyword("HasCorrections") || general["HasCorrections"][0] == "true") {
423  m_normsSolved = true;
424 
425  clearAdjustments();
426  for (int img = 0; img < (int) m_imageList.size(); img++) {
427  // Apply correction based on pre-determined statistics information
428  PvlGroup &normalization = equalInfo.group(normIndices[img]);
429 
430  // TODO should we also get the valid and invalid count?
431 
432  ImageAdjustment *adjustment = new ImageAdjustment(m_sType);
433 
434  // Get and store the modifiers for each band
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]));
439  }
440 
441  addAdjustment(adjustment);
442  }
443  }
444  else {
445  m_normsSolved = false;
446  }
447 
448  }
449 
450 
461  void Equalization::applyCorrection(QString toListName="") {
462  if (!isSolved()) {
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] + "] ";
469  }
470  }
471  else {
472  msg += "Add more images to create more overlaps and recalculate, ";
473  msg += "or try another solve method.";
474  }
475  throw IException(IException::User, msg, _FILEINFO_);
476  }
477 
478  FileList outList;
479  fillOutList(outList, toListName);
480 
481  QString maxCubeStr = toString((int) m_imageList.size());
482  for (int img = 0; img < m_imageList.size(); img++) {
483  // Set up for progress bar
484  ProcessByLine p;
485  p.Progress()->SetText("Equalizing Cube " + toString((int) img + 1) +
486  " of " + maxCubeStr);
487 
488  // Open input cube
489  CubeAttributeInput att;
490  const QString inp = m_imageList[img].toString();
491  Cube *icube = p.SetInputCube(inp, att);
492 
493  // Allocate output cube
494  QString out = outList[img].toString();
495  CubeAttributeOutput outAtt;
496  p.SetOutputCube(out, outAtt, icube->sampleCount(),
497  icube->lineCount(), icube->bandCount());
498 
499  // Apply gain/offset to the image
500  ApplyFunctor func(m_adjustments[img]);
501  p.ProcessCube(func, false);
502  p.EndProcess();
503  }
504  }
505 
506 
514  PvlGroup Equalization::getResults() {
515  // TODO combine summary info into getSummary method and use with write
516  PvlGroup results = m_results->findObject("EqualizationInformation").findGroup("General");
517  if (m_normsSolved) {
518 
519  // Name and band modifiers for each image
520  for (int img = 0; img < m_imageList.size(); img++) {
521  results += PvlKeyword("FileName", m_imageList[img].toString());
522 
523  // Band by band statistics
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));
528  QString bandNum = toString(band);
529  QString bandStr = "Band" + bandNum;
530  PvlKeyword bandStats(bandStr);
531  bandStats += mult;
532  bandStats += base;
533  bandStats += avg;
534  results += bandStats;
535  }
536  }
537  }
538  return results;
539  }
540 
541 
547  void Equalization::write(QString outstatsFileName) {
548  // Write the equalization and overlap statistics to the file
549  m_results->write(outstatsFileName);
550  }
551 
552 
553  double Equalization::evaluate(double dn, int imageIndex, int bandIndex) const {
554  return m_adjustments[imageIndex]->evaluate(dn, bandIndex);
555  }
556 
557 
567  void Equalization::loadInputs(QString fromListName) {
568  // Get the list of cubes to mosaic
569  m_imageList.read(fromListName);
570  m_maxCube = m_imageList.size();
571 
572  if (m_imageList.size() < 2) {
573  QString msg = "The input file [" + fromListName +
574  "] must contain at least 2 file names";
575  throw IException(IException::User, msg, _FILEINFO_);
576  }
577 
578  Cube tempCube;
579  tempCube.open(m_imageList[0].toString());
580  m_maxBand = tempCube.bandCount();
581 
582  m_doesOverlapList.resize(m_imageList.size(), false);
583  m_alreadyCalculated.resize(m_imageList.size(), false);
584 
585  errorCheck(fromListName);
586  }
587 
588 
589  void Equalization::setInput(int index, QString value) {
590  m_imageList[index] = value;
591  }
592 
593 
594  const FileList &Equalization::getInputs() const {
595  return m_imageList;
596  }
597 
598 
599  void Equalization::fillOutList(FileList &outList, QString toListName) {
600  if (toListName.isEmpty()) {
601  generateOutputs(outList);
602  }
603  else {
604  loadOutputs(outList, toListName);
605  }
606  }
607 
608 
615  void Equalization::errorCheck(QString fromListName) {
616  for (int i = 0; i < m_imageList.size(); i++) {
617  Cube cube1;
618  cube1.open(m_imageList[i].toString());
619 
620  for (int j = (i + 1); j < m_imageList.size(); j++) {
621  Cube cube2;
622  cube2.open(m_imageList[j].toString());
623 
624  // Make sure number of bands match
625  if (m_maxBand != cube2.bandCount()) {
626  QString msg = "Number of bands do not match between cubes [" +
627  m_imageList[i].toString() + "] and [" + m_imageList[j].toString() + "]";
628  throw IException(IException::User, msg, _FILEINFO_);
629  }
630 
631  //Create projection from each cube
632  Projection *proj1 = cube1.projection();
633  Projection *proj2 = cube2.projection();
634 
635  // Test to make sure projection parameters match
636  if (*proj1 != *proj2) {
637  QString msg = "Mapping groups do not match between cubes [" +
638  m_imageList[i].toString() + "] and [" + m_imageList[j].toString() + "]";
639  throw IException(IException::User, msg, _FILEINFO_);
640  }
641  }
642  }
643  }
644 
645 
649  void Equalization::generateOutputs(FileList &outList) {
650  for (int img = 0; img < m_imageList.size(); img++) {
651  FileName file(m_imageList[img]);
652  QString filename = file.path() + "/" + file.baseName() +
653  ".equ." + file.extension();
654  outList.push_back(FileName(filename));
655  }
656  }
657 
658 
667  void Equalization::loadOutputs(FileList &outList, QString toListName) {
668  outList.read(FileName(toListName));
669 
670  // Make sure each file in the tolist matches a file in the fromlist
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.";
674  throw IException(IException::User, msg, _FILEINFO_);
675  }
676 
677  // Make sure that all output files do not have the same names as their
678  // corresponding input files
679  for (int i = 0; i < outList.size(); i++) {
680  if (outList[i].toString().compare(m_imageList[i].toString()) == 0) {
681  QString msg = "The to list file [" + outList[i].toString() +
682  "] has the same name as its corresponding from list file.";
683  throw IException(IException::User, msg, _FILEINFO_);
684  }
685  }
686  }
687 
688 
689  void Equalization::loadHolds(OverlapNormalization *oNorm) {
690  for (unsigned int h = 0; h < m_holdIndices.size(); h++)
691  oNorm->AddHold(m_holdIndices[h]);
692  }
693 
694 
698  void Equalization::clearAdjustments() {
699  for (unsigned int adj = 0; adj < m_adjustments.size(); adj++) {
700  delete m_adjustments[adj];
701  }
702  m_adjustments.clear();
703  }
704 
705 
713  void Equalization::addAdjustment(ImageAdjustment *adjustment) {
714  m_adjustments.push_back(adjustment);
715  }
716 
717 
721  void Equalization::clearNormalizations() {
722  for (unsigned int oNorm = 0; oNorm < m_overlapNorms.size(); oNorm++) {
723  delete m_overlapNorms[oNorm];
724  }
725  m_overlapNorms.clear();
726  }
727 
728 
732  void Equalization::clearOverlapStatistics() {
733  for (unsigned int oStat = 0; oStat < m_overlapStats.size(); oStat++) {
734  delete m_overlapStats[oStat];
735  }
736  m_overlapStats.clear();
737  }
738 
739 
745  void Equalization::addValid(int count) {
746  m_validCnt += count;
747  }
748 
749 
755  void Equalization::addInvalid(int count) {
756  m_invalidCnt += count;
757  }
758 
759 
768  void Equalization::fromPvl(const PvlObject &inStats) {
769 
770  // Make a copy of our image list with names only (instead of full path)
771  QList<QString> imgNames;
772  for (int img = 0; img < m_imageList.size(); img++) {
773  imgNames.append(m_imageList[img].name());
774  }
775 
776  // Load in previous user params
777  const PvlObject &eqInfo = inStats.findObject("EqualizationInformation");
778  const PvlGroup &eqGen = eqInfo.findGroup("General");
779  m_samplingPercent = eqGen["SamplingPercent"];
780  m_mincnt = eqGen["MinCount"];
781  m_wtopt = (eqGen["Weighted"][0] == "true") ? true : false;
782  m_sType = static_cast<OverlapNormalization::SolutionType>((int)eqGen["SolutionType"]);
783  m_lsqMethod = static_cast<LeastSquares::SolveMethod>(eqGen["SolveMethod"][0].toInt());
784 
785  // Unserialize previous overlap statistics
786  PvlObject::ConstPvlObjectIterator curObj = inStats.beginObject();
787  while (curObj < inStats.endObject()) {
788  if (curObj->isNamed("OverlapStatistics")) {
789  OverlapStatistics *o = new OverlapStatistics(*curObj);
790  m_overlapStats.push_back(o);
791 
792  const PvlObject &oStat = *curObj;
793  QString fileX = oStat["File1"][0];
794  QString fileY = oStat["File2"][0];
795 
796  // Determine already calculated overlaps
797  int x = imgNames.indexOf(fileX);
798  int y = imgNames.indexOf(fileY);
799  m_alreadyCalculated[x] = true;
800  m_alreadyCalculated[y] = true;
801 
802  // Determine which calculated overlaps have valid overlaps
803  // (i.e. valid pixels > mincount)
804  if (oStat["Valid"][0] == "true") {
805  m_doesOverlapList[x] = true;
806  m_doesOverlapList[y] = true;
807  }
808  }
809  curObj++;
810  }
811 
812  // Calculate the image+band statistics
813  calculateBandStatistics();
814 
815  // Calculate x/y indices that map the overlap x/y statistics to the input image index
816  // { {olap1idxX, olap1indxY}, {olap2idxX, olap12idxY} ... }
817  // vector< vector<int> > overlapIndices(m_overlapStats.size(),
818  // vector<int>(2));
819  //int overlapIndices[m_overlapStats.size()][2];
820  QVector< QVector<int> > overlapIndices(m_overlapStats.size());
821  for (int o = 0; o < (int) m_overlapStats.size(); o++) {
822  OverlapStatistics *oStat = m_overlapStats[o];
823 
824  // Calculate the indices - we want to ensure that no matter how the input list of images
825  // changes (e.g. the order is changed), we always add overlaps that same way.
826  // This means ensuring that each overlap has the X overlap statistics associated with
827  // the X index and the Y overlap statistics associated with the Y index.
828  for (int i = 0; i < m_imageList.size(); i++) {
829  QString imageName(m_imageList[i].name());
830 
831  // Always push the X file index to the front (0)
832  if (oStat->FileNameX() == imageName)
833  //overlapIndices[o].insert(overlapIndices[o].begin(), i);
834  //overlapIndices[o][0] = i;
835  overlapIndices[o].push_front(i);
836  // Always push the Y file index to the back (1)
837  if (oStat->FileNameY() == imageName)
838  //overlapIndices[o].push_back(i);
839  //overlapIndices[o][1] = i;
840  overlapIndices[o].push_back(i);
841  }
842  }
843 
844  // Add the overlap
845  for (int o = 0; o < (int) m_overlapStats.size(); o++) {
846  OverlapStatistics *oStat = m_overlapStats[o];
847  for (int band = 1; band <= oStat->Bands(); band++) {
848  int weight = 1;
849  if (m_wtopt) weight = oStat->GetMStats(band).ValidPixels();
850  if (oStat->GetMStats(band).ValidPixels() >= m_mincnt) {
851  m_overlapNorms[band-1]->AddOverlap(oStat->GetMStats(band).X(), overlapIndices[o][0],
852  oStat->GetMStats(band).Y(), overlapIndices[o][1], weight);
853  }
854  }
855  }
856  }
857 
858 
864  void Equalization::setSolved(bool solved) {
865  m_normsSolved = solved;
866  }
867 
868 
874  bool Equalization::isSolved() const {
875  return m_normsSolved;
876  }
877 
878 
882  void Equalization::init() {
883  m_validCnt = 0;
884  m_invalidCnt = 0;
885 
886  m_mincnt = 1000;
887  m_samplingPercent = 100.0;
888  m_wtopt = false;
889 
890  m_maxCube = 0;
891  m_maxBand = 0;
892 
893  m_sType = OverlapNormalization::Both;
894  m_lsqMethod = LeastSquares::SPARSE;
895 
896  m_badFiles.clear();
897  m_doesOverlapList.clear();
898  m_alreadyCalculated.clear();
899  m_normsSolved = false;
900  m_recalculating = false;
901 
902  m_results = NULL;
903  }
904 
905 
921  QVector<int> Equalization::validateInputStatistics(QString instatsFileName) {
922  QVector<int> normIndices;
923 
924  Pvl inStats(instatsFileName);
925  PvlObject &equalInfo = inStats.findObject("EqualizationInformation");
926 
927  // Make sure each file in the instats matches a file in the fromlist
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.";
931  throw IException(IException::User, msg, _FILEINFO_);
932  }
933 
934  // Check that each file in the FROM LIST is present 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++) {
939  PvlGroup &normalization = equalInfo.group(j);
940  QString normFile = normalization["FileName"][0];
941  if (fromFile == normFile) {
942 
943  // Store the index in INPUT STATISTICS file corresponding to the
944  // current FROM LIST file
945  normIndices.push_back(j);
946  foundFile = true;
947  }
948  }
949  if (!foundFile) {
950  QString msg = "The from list file [" + fromFile +
951  "] does not have any corresponding file in the stats list.";
952  throw IException(IException::User, msg, _FILEINFO_);
953  }
954  }
955 
956  return normIndices;
957  }
958 
959 
960  void Equalization::CalculateFunctor::operator()(Buffer &in) const {
961  // Make sure we consider the last line
962  if ((in.Line() - 1) % m_linc == 0 || in.Line() == in.LineDimension()) {
963  addStats(in);
964  }
965  }
966 
967 
968  void Equalization::CalculateFunctor::addStats(Buffer &in) const {
969  // Add data to Statistics object by line
970  m_stats->AddData(&in[0], in.size());
971  }
972 
973 
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++) {
977  out[i] = (IsSpecial(in[i])) ?
978  in[i] : m_adjustment->evaluate(in[i], index);
979  }
980  }
981 
982 
983 }
Buffer for reading and writing cube data.
Definition: Buffer.h:69
Manipulate and parse attributes of input cube filenames.
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.
Definition: PvlContainer.h:100
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.
Definition: FileName.cpp:119
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.
Definition: Equalization.h:226
PvlGroupIterator findGroup(const QString &name, PvlGroupIterator beg, PvlGroupIterator end)
Find a group with the specified name, within these indexes.
Definition: PvlObject.h:141
PvlObjectIterator endObject()
Returns the index of the ending object.
Definition: PvlObject.h:265
Isis::Cube * SetInputCube(const QString &parameter, const int requirements=0)
Opens an input cube specified by the user and verifies requirements are met.
File name manipulation and expansion.
Definition: FileName.h:116
PvlObjectIterator findObject(const QString &name, PvlObjectIterator beg, PvlObjectIterator end)
Find the index of object with a specified name, between two indexes.
Definition: PvlObject.h:286
int sampleCount() const
Definition: Cube.cpp:1452
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.
Definition: PvlObject.h:198
Namespace for the standard library.
Internalizes a list of files.
Definition: FileList.h:70
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.
Definition: IString.cpp:226
Projection * projection()
Definition: Cube.cpp:1439
This class is used as a functor to apply adjustments (equalize) to an image.
Definition: Equalization.h:259
int LineDimension() const
Returns the number of lines in the shape buffer.
Definition: Buffer.h:95
double toDouble(const QString &string)
Global function to convert from a string to a double.
Definition: IString.cpp:164
void AddHold(unsigned holdIndex)
Sets the list of files to be held during the solving process.
void addObject(const PvlObject &object)
Add a PvlObject.
Definition: PvlObject.h:319
This class is used to accumulate statistics on double arrays.
Definition: Statistics.h:107
Base class for Map Projections.
Definition: Projection.h:171
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
Definition: FileList.cpp:68
void SetText(const QString &text)
Changes the value of the text string reported just before 0% processed.
Definition: Progress.cpp:77
Contains multiple PvlContainers.
Definition: PvlGroup.h:57
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
Manipulate and parse attributes of output cube filenames.
A single keyword-value pair.
Definition: PvlKeyword.h:98
int Line(const int index=0) const
Returns the line position associated with a shape buffer index.
Definition: Buffer.cpp:161
bool IsSpecial(const double d)
Returns if the input pixel is special.
Definition: SpecialPixel.h:212
void open(const QString &cfile, QString access="r")
This method will open an isis cube for reading or reading/writing.
Definition: Cube.cpp:544
Container for cube-like labels.
Definition: Pvl.h:135
Isis::Progress * Progress()
This method returns a pointer to a Progress object.
Definition: Process.h:270
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.
Definition: FileName.cpp:161
Calculates statistics in the area of overlap between two projected cubes.
PvlGroup & group(const int index)
Return the group at the specified index.
Definition: PvlObject.cpp:423
void ProcessCube(const Functor &funct, bool threaded=true)
Same functionality as StartProcess(void funct(Isis::Buffer &in, Isis::Buffer &out)) using Functors...
int lineCount() const
Definition: Cube.cpp:1379
int Bands() const
Returns the number of bands both cubes have.
Isis exception class.
Definition: IException.h:107
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
virtual int bandCount() const
Returns the number of virtual bands for the cube.
Definition: Cube.cpp:1125
QString extension() const
Returns the last extension of the file name.
Definition: FileName.cpp:194
int groups() const
Returns the number of groups contained.
Definition: PvlObject.h:87
Contains Pvl Groups and Pvl Objects.
Definition: PvlObject.h:74
Process cubes by line.
PvlObjectIterator beginObject()
Returns the index of the beginning object.
Definition: PvlObject.h:247
Isis::FileName FileNameY() const
Returns the filename of the second cube.
Functor for reduce using average functionality.
Definition: Reduce.h:102
IO Handler for Isis Cubes.
Definition: Cube.h:170