Isis 3 Programmer Reference
SpectralDefinition2D.cpp
1
6/* SPDX-License-Identifier: CC0-1.0 */
7
8#include "SpectralDefinition2D.h"
9
10#include <cassert>
11#include <QList>
12
13#include "ProcessBySample.h"
14#include "Spectel.h"
15
16namespace Isis {
17
27 ProcessBySample importCube;
29 m_spectelList = NULL;
30 m_sectionList = NULL;
31 Cube *smileCube = importCube.SetInputCube(smileDefFilename.expanded(), cai);
32
33 try {
34 // Check to see if input definition has the correct format
35 if (smileCube->lineCount() != 2) {
36 QString msg = QObject::tr("Input calibration file [%1] must have 2 lines: "
37 "one containing wavelength centers and one containing widths").
38 arg(smileDefFilename.toString());
39 throw IException(IException::User, msg, _FILEINFO_);
40 }
41
42 m_spectelList = new QList< QList<Spectel> *>;
43 m_sectionList = new QList<int>;
44
45 m_ns = smileCube->sampleCount();
46 m_nl = 0;
47 m_nb = smileCube->bandCount();
48
49 m_sectionList->append(1); //first section will always be band 1
50 importCube.SetProcessingDirection(ProcessByBrick::BandsFirst);
51 importCube.Progress()->SetText("Importing Spectral Definition Cube");
52 importCube.ProcessCubeInPlace(*this, false);
53 importCube.Finalize();
54
55 m_numSections = m_sectionList->length();
56
57 } catch (IException &e) {
58 //delete dynamically allocated memory, since destructor won't be called.
59 if (m_spectelList != NULL) {
60 delete m_spectelList;
61 }
62 if (m_sectionList != NULL) {
63 delete m_sectionList;
64 }
65 QString msg = QObject::tr("Unable to open input cube [%1] and read it into a spectral "
66 "definition.").arg(smileDefFilename.toString());
67 throw IException(e, IException::Unknown, msg, _FILEINFO_);
68 }
69 }
70
74
75
77 int SpectralDefinition2D::sectionNumber(int s, int l, int b) const {
78 if (m_sectionList->contains(b)) {
79 return m_sectionList->indexOf(b);
80 }
81 else if (m_sectionList->size() == 1) {
82 return 0;
83 }
84 else {
85 for (int i=0; i<m_sectionList->size()-1; i++ ) {
86 if ( (b > m_sectionList->at(i)) && (b < m_sectionList->at(i+1)) ) {
87 return i;
88 }
89 }
90 return m_sectionList->size() - 1;
91 }
92 }
93
94
100
101
113 Spectel SpectralDefinition2D::findSpectel(const int sample, const int line,
114 const int band) const {
115 // There is no DN, since the imported image's DNs are centers and widths
116
117 // TODO:
118 // Test the QList bounds ourselves and throw an ISIS exception if not valid. QList.at does
119 // not throw if invalid. It aborts using assert
120 return m_spectelList->at(sample - 1)->at(band - 1);
121 }
122
123
124 Spectel SpectralDefinition2D::findSpectelByWavelength(const double wavelength,
125 const int sectionNumber) const {
126 // Can not search a 2D definistion with only one value (i.e. wavelength), so abort
127 // NOTE: This is ignored for code coverage until a good way to test it is found
128 // May not want to use the assert, but this function should not be called
129
130 assert(0);
131 return Spectel();
132 }
133
134 // TODO: If the requested wavelength is outside all the definitioin wavelength we should do something
135 Spectel SpectralDefinition2D::findSpectel(const Spectel &inSpectel,
136 const int sectionNumber) const {
137 double diff;
138 double bestdiff = DBL_MAX;
139 double bestband = 0;
140 double wavelength = inSpectel.centerWavelength();
141 QList<Spectel> *spectrum = m_spectelList->at(inSpectel.sample()-1);
142
143 //only search in correct section
144 int start = m_sectionList->at(sectionNumber) - 1; //bands are 1-indexed, but are stored as 0-indexed
145 int end;
146 if (sectionNumber == m_sectionList->size()-1) { //we're in the last section
147 end = spectrum->length();
148 }
149 else {
150 end = m_sectionList->at(sectionNumber + 1) - 1;
151 }
152
153 for (int i=start; i<end; i++) {
154 diff = spectrum->at(i).centerWavelength() - wavelength;
155 if (std::abs(diff) < std::abs(bestdiff)) {
156 bestdiff = diff;
157 bestband = i;
158 }
159 }
160
161 // TODO: QList aborts if at(arg) is out of bounds do the necessary error check and throw if needed
162 return spectrum->at(bestband);
163 }
164
173 QString temp;
174 for (int samp=0; samp<m_spectelList->size(); samp++) {
175 for(int band=0; band<m_spectelList->at(samp)->size(); band++){
176 Spectel spec = m_spectelList->at(samp)->at(band);
177 temp+="Spectel at (s,b) (";
178 temp+= QString::number(samp);
179 temp+= ", ";
180 temp+= QString::number(band);
181 temp+=") : Wavelength=";
182 temp+=QString::number(spec.centerWavelength());
183 temp+=" Width=";
184 temp+=QString::number(spec.filterWidth());
185 temp+="\n";
186 }
187 }
188 return temp;
189 }
190
191
192 // TODO: Test for equal wavelengths within a single section (currently ignored)
196
197 // Each time we come back to the first band allocate space for this new spectrum of spectels
198 if (in.Band() == 1) {
199 QList<Spectel> *tempList = new QList<Spectel>;
200 m_spectelList->append(tempList);
201 }
202
203 // Store the spectel
204 Spectel temp(in.Sample(), Isis::NULL8, in.Band(), Isis::NULL8, in[0], in[1]);
205 m_spectelList->at(in.Sample()-1)->append(temp);
206
207 // Check for sections (change in wavelength direction) in the first spectrum only
208 // TODO: Consider doing this for all spectrums as a saftey check
209 // The first two spectels define the initial wavelength direction.
210 if (in.Sample() == 1) {
211
212 QList<Spectel> *spectrum = m_spectelList->at(in.Sample()-1);
213 int index = in.Band() - 1;
214
215 if ((index > 1) && // We now have at least 3 saved
216 (index != m_sectionList->last()) && // Don't look for a switch until one after the most recent
217 (((spectrum->at(index-2).centerWavelength() <
218 spectrum->at(index-1).centerWavelength()) && // previous 2 are ascending
219 (spectrum->at(index-1).centerWavelength() >
220 spectrum->at(index).centerWavelength())) || // previous and this are descending
221 ((spectrum->at(index-2).centerWavelength() >
222 spectrum->at(index-1).centerWavelength()) && // previous 2 are descending
223 (spectrum->at(index-1).centerWavelength() <
224 spectrum->at(index).centerWavelength())))) { // previous and this are ascending
225
226 m_sectionList->append(in.Band());
227 }
228 }
229 }
230}
Buffer for reading and writing cube data.
Definition Buffer.h:53
Manipulate and parse attributes of input cube filenames.
IO Handler for Isis Cubes.
Definition Cube.h:168
File name manipulation and expansion.
Definition FileName.h:100
Isis exception class.
Definition IException.h:91
@ Unknown
A type of error that cannot be classified as any of the other error types.
Definition IException.h:118
@ User
A type of error that could only have occurred due to a mistake on the user's part (e....
Definition IException.h:126
Process cubes by sample.
Stores information about a "Spectral pixel" or spectel.
Definition Spectel.h:26
double centerWavelength() const
Gets central wavelength of spectel.
Definition Spectel.cpp:95
int sectionNumber(int s, int l, int b) const
returns section number given (s,l,b)
int m_numSections
The number of sections of this Spectral Definition.
SpectralDefinition2D(FileName smileDefFilename)
Construct a SpectralDefinition2D object using a filename.
QList< int > * m_sectionList
The list of sections.
QList< QList< Spectel > * > * m_spectelList
Internally represent the samples x 2 lines x n bands calibration file Outside list is the sample inde...
void operator()(Buffer &in) const
Internal function used to help read-in a calibration cube.
QString toString()
Returns QString representation of SpectralDefinition2D.
virtual int sectionCount() const
Returns the number of sections in the calibration image.
Spectel findSpectel(const int sample, const int line, const int band) const
Get the Spectel at some sample, line, band (associated with your input/calibration file)
int m_nl
Number of lines in input Cube.
int m_ns
Number of samples in input Cube.
int m_nb
Number of bands in input Cube.
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16