Isis 3 Programmer Reference
HiEqualization.cpp
1
7/* SPDX-License-Identifier: CC0-1.0 */
8
9#include "HiEqualization.h"
10
11#include <iomanip>
12
13#include "Buffer.h"
14#include "Cube.h"
15#include "IException.h"
16#include "LineManager.h"
17#include "OverlapNormalization.h"
18#include "OverlapStatistics.h"
19#include "Process.h"
20#include "ProcessByLine.h"
21
22using std::string;
23using std::vector;
24
25
26namespace Isis {
27
28
29 HiEqualization::HiEqualization(QString fromListName) :
30 Equalization() {
31 loadInputs(fromListName);
32 }
33
34
35 HiEqualization::~HiEqualization() {
36 }
37
38
39 void HiEqualization::calculateStatistics() {
40 // TODO member variable
41 const FileList &imageList = getInputs();
42 QString maxCubeStr = toString((int) imageList.size());
43
44 // Adds statistics for whole and side regions of every cube
45 vector<Statistics *> statsList;
46 vector<Statistics *> leftStatsList;
47 vector<Statistics *> rightStatsList;
48 for (int img = 0; img < imageList.size(); img++) {
49 Statistics *stats = new Statistics();
50 Statistics *statsLeft = new Statistics();
51 Statistics *statsRight = new Statistics();
52
53 QString cubeStr = toString((int) img + 1);
54
55 ProcessByLine p;
56 p.Progress()->SetText("Calculating Statistics for Cube " +
57 cubeStr + " of " + maxCubeStr);
58 CubeAttributeInput att;
59 QString inp = imageList[img].toString();
60 p.SetInputCube(inp, att);
61 HiCalculateFunctor func(stats, statsLeft, statsRight, 100.0);
62 p.ProcessCubeInPlace(func, false);
63
64 statsList.push_back(stats);
65 leftStatsList.push_back(statsLeft);
66 rightStatsList.push_back(statsRight);
67 }
68
69 // Initialize the object that will calculate the gains and offsets
70 OverlapNormalization oNorm(statsList);
71
72 // Add the known overlaps between two cubes, and apply a weight to each
73 // overlap equal the number of pixels in the overlapping area
74 for (int i = 0; i < imageList.size() - 1; i++) {
75 int j = i + 1;
76 oNorm.AddOverlap(*rightStatsList[i], i, *leftStatsList[j], j,
77 rightStatsList[i]->ValidPixels());
78 }
79
80 loadHolds(&oNorm);
81
82 // Attempt to solve the least squares equation
83 oNorm.Solve(OverlapNormalization::Both);
84 setSolved(true);
85
86 clearAdjustments();
87 for (int img = 0; img < imageList.size(); img++) {
88 ImageAdjustment *adjustment = new ImageAdjustment(OverlapNormalization::Both);
89 adjustment->addGain(oNorm.Gain(img));
90 adjustment->addOffset(oNorm.Offset(img));
91 adjustment->addAverage(oNorm.Average(img));
92 addAdjustment(adjustment);
93 }
94
95 addValid(imageList.size() - 1);
96 setResults();
97 }
98
99
100 void HiEqualization::fillOutList(FileList &outList, QString toListName) {
101 if (toListName.isEmpty()) {
102 generateOutputs(outList);
103 }
104 else {
105 FileList tempList;
106 loadOutputs(tempList, toListName);
107
108 for (unsigned int i = 0; i < movedIndices.size(); i++) {
109 outList.push_back(tempList[movedIndices[i]]);
110 }
111 }
112 }
113
114
115 void HiEqualization::errorCheck(QString fromListName) {
116 const FileList &imageList = getInputs();
117
118 // Ensures number of images is within bound
119 if (imageList.size() > 10) {
120 QString msg = "The input file [" + fromListName +
121 "] cannot contain more than 10 file names";
122 throw IException(IException::User, msg, _FILEINFO_);
123 }
124
125 // Reference for converting a CPMM number to a CCD number
126 const int cpmm2ccd[] = {0, 1, 2, 3, 12, 4, 10, 11, 5, 13, 6, 7, 8, 9};
127
128 // Place ccd in vector, try-catch opening cubes
129 vector<int> ccds;
130 for (int i = 0; i < imageList.size(); i++) {
131 try {
132 Cube cube1;
133 cube1.open(imageList[i].toString());
134 PvlGroup &from1Instrument = cube1.group("INSTRUMENT");
135 int cpmmNumber = from1Instrument["CpmmNumber"];
136 ccds.push_back(cpmm2ccd[cpmmNumber]);
137
138 // In case we need to alter the order of the input list, keep a record
139 // of how the indices changed so we can rearrange the output list later
140 movedIndices.push_back(i);
141 }
142 catch (IException &e) {
143 QString msg = "The [" + imageList[i].toString() +
144 "] file is not a valid HiRise image";
145 throw IException(e, IException::User, msg, _FILEINFO_);
146 }
147 catch (...) {
148 // If any part of the above didn't work, we can safely assume the
149 // current file is not a valid HiRise image
150 QString msg = "The [" + imageList[i].toString() +
151 "] file is not a valid HiRise image";
152 throw IException(IException::User, msg, _FILEINFO_);
153 }
154 }
155
156 // Error checking to ensure CCDID types match
157 for (int i = 0; i < imageList.size() - 1; i++) {
158 int id1 = getCCDType(ccds[i]);
159 int id2 = getCCDType(ccds[i + 1]);
160
161 // CCDID types don't match
162 if (id1 != id2) {
163 string msg = "The list of input images must be all RED, all IR, or ";
164 msg += "all BG";
165 throw IException(IException::User, msg, _FILEINFO_);
166 }
167 }
168
169 // Insertion sorts a list of filenames by their CCD numbers
170 for (int i = 1; i < imageList.size(); i++) {
171 QString temp = imageList[i].toString();
172 int ccd1 = ccds[i];
173 int movedIndex = movedIndices[i];
174
175 int j = i - 1;
176 int ccd2 = ccds[j];
177
178 while (j >= 0 && ccd2 > ccd1) {
179 setInput(j + 1, imageList[j].toString());
180 ccds[j + 1] = ccds[j];
181 movedIndices[j + 1] = movedIndices[j];
182
183 j--;
184 if (j >= 0) ccd2 = ccds[j];
185 }
186
187 setInput(j + 1, temp);
188 ccds[j + 1] = ccd1;
189 movedIndices[j + 1] = movedIndex;
190 }
191
192 // Ensures BG and IR only have two files
193 if (ccds[0] == 10 || ccds[0] == 11) {
194 if (imageList.size() != 2) {
195 string msg = "A list of IR images must have exactly two ";
196 msg += "file names";
197 throw IException(IException::User, msg, _FILEINFO_);
198 }
199 }
200 else if (ccds[0] == 12 || ccds[0] == 13) {
201 if (imageList.size() != 2) {
202 string msg = "A list of BG images must have exactly two ";
203 msg += "file names";
204 throw IException(IException::User, msg, _FILEINFO_);
205 }
206 }
207 }
208
209
210 // CCD ID Type
211 int HiEqualization::getCCDType(int ccd) {
212 // Red, IR, or BG
213 return (ccd >= 0 && ccd <= 9) ? 0 : (ccd == 10 || ccd == 11) ? 1 : 2;
214 }
215
216
217 void HiEqualization::HiCalculateFunctor::addStats(Buffer &in) const {
218 Equalization::CalculateFunctor::addStats(in);
219
220 // Number of samples per line that intersect with the next and the
221 // previous images. Check if samples equal 682 or 683. If not the above
222 // case, then we perform an algorithm to account for binning. Number of
223 // intersecting samples is directly related to total number of samples in
224 // the line, with 2048 being the maximum possible.
225 unsigned int intersect = (in.size() == 682 || in.size() == 683) ?
226 18 : (48 * in.size()) / 2048;
227
228 m_statsLeft->AddData(&in[0], intersect);
229 m_statsRight->AddData(&in[in.size() - intersect], intersect);
230 }
231
232
233}
IO Handler for Isis Cubes.
Definition Cube.h:168
void open(const QString &cfile, QString access="r")
This method will open an existing isis cube for reading or reading/writing.
Definition Cube.cpp:622
Internalizes a list of files.
Definition FileList.h:54
Isis exception class.
Definition IException.h:91
Contains multiple PvlContainers.
Definition PvlGroup.h:41
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition IString.cpp:211