USGS

Isis 3.0 Object Programmers' Reference

Home

LroWideAngleCamera.cpp
Go to the documentation of this file.
1 
21 #include "LroWideAngleCamera.h"
24 
25 #include <sstream>
26 #include <iomanip>
27 
28 #include <QString>
29 #include <QVector>
30 
31 #include "CameraFocalPlaneMap.h"
32 #include "CameraSkyMap.h"
33 #include "CollectorMap.h"
34 #include "IException.h"
35 #include "IString.h"
36 #include "iTime.h"
37 #include "NaifStatus.h"
40 
41 using namespace std;
42 namespace Isis {
53  LroWideAngleCamera::LroWideAngleCamera(Cube &cube) :
54  PushFrameCamera(cube) {
55 
57  // Set up the camera characteristics
60  SetPixelPitch();
61 
62  Pvl &lab = *cube.label();
63 
64  // Get the ephemeris time from the labels
65  double et;
66  PvlGroup &inst = lab.findGroup("Instrument", Pvl::Traverse);
67  QString stime = inst["SpacecraftClockStartCount"];
68  et = getClockTime(stime).Et();
69 
70  p_exposureDur = toDouble(inst["ExposureDuration"]);
71  // TODO: Changed et - exposure to et + exposure.
72  // Think about if this is correct
73  p_etStart = et + ((p_exposureDur / 1000.0) / 2.0);
74 
75  // Compute the framelet size and number of framelets
76  QString instId = inst["InstrumentId"][0].toUpper();
77 
78  int frameletSize = 14;
79  int sumMode = 1;
80  int filterIKBase = 10;
81 
82  if (instId == "WAC-UV") {
83  sumMode = 4;
84  frameletSize = 16;
85  filterIKBase = 15 - 1; // New UV IK code = filterIKBase + BANDID
86  }
87  else if (instId == "WAC-VIS") {
88  sumMode = 1;
89  frameletSize = 14;
90  filterIKBase = 10 - 3; // New VIS IK code = filterIKBase + BANDID
91  }
92  else {
93  QString msg = "Invalid value [" + instId
94  + "] for keyword [InstrumentId]";
96  }
97 
98  p_nframelets = (int) (ParentLines() / (frameletSize / sumMode));
99 
100  // Setup the line detector offset map for each filter
101  int nbands = (int) lab.findKeyword("Bands", PvlObject::Traverse);
102  const PvlGroup &bandBin = lab.findGroup("BandBin", Pvl::Traverse);
103  const PvlKeyword &filtNames = bandBin["Center"];
104 
105  // Sanity check
106  if (nbands != filtNames.size()) {
107  ostringstream mess;
108  mess << "Number bands in (file) label (" << nbands
109  << ") do not match number of values in BandBin/Center keyword ("
110  << filtNames.size() << ") - required for band-dependent geoemtry";
111  throw IException(IException::User, mess.str(), _FILEINFO_);
112  }
113 
114  // Is the data flipped?
115  bool dataflipped = (inst["DataFlipped"][0].toUpper() == "YES");
116 
117  // Now create detector offsets
118  QString instCode = "INS" + QString::number(naifIkCode());
119 
120  QString ikernKey = instCode + "_FILTER_BANDCENTER";
121  IntParameterList fbc = GetVector(ikernKey);
122 
123  ikernKey = instCode + "_FILTER_OFFSET";
124  IntParameterList foffset = GetVector(ikernKey);
125 
126  // Get band ID to determine new filter dependent IK codes
127  ikernKey = instCode + "_FILTER_BANDID";
128  IntParameterList fbandid = GetVector(ikernKey);
129 
130 
131  // Create a map of filter wavelength to offset. Also needs a reverse
132  // lookup to order the offset into the CCD (ascending sort provided
133  // automagically be CollectorMap).
134  CollectorMap<int, int> filterToDetectorOffset, wavel,filterIKCode;
135  for (int i = 0 ; i < foffset.size() ; i++) {
136  filterToDetectorOffset.add(fbc[i], foffset[i]);
137  wavel.add(foffset[i], fbc[i]);
138  filterIKCode.add(fbc[i], naifIkCode() - (filterIKBase + fbandid[i])); // New IK code
139  }
140 
141  // Construct special format for framelet offsets into CCD. Uses the above
142  // reverse map. Need only get the value (wavelength) of the map as the
143  // key (offset) is sorted above.
144  int frameletOffsetFactor = inst["ColorOffset"];
145  if ( dataflipped ) frameletOffsetFactor *= -1;
146  CollectorMap<int, int> filterToFrameletOffset;
147  for (int j = 0 ; j < wavel.size() ; j++) {
148  int wavelen = wavel.getNth(j);
149  filterToFrameletOffset.add(wavelen, j * frameletOffsetFactor);
150  }
151 
152  // Now map the actual filters that exist in cube to camera components or
153  // storage vectors for later band selection (see SetBand(vband))
154  for (int i = 0; i < filtNames.size(); i++) {
155  if (!filterToDetectorOffset.exists(filtNames[i].toInt())) {
156  QString msg = "Unrecognized filter name [" + filtNames[i] + "]";
158  }
159 
160  p_detectorStartLines.push_back(filterToDetectorOffset.get(filtNames[i].toInt()));
161  p_frameletOffsets.push_back(filterToFrameletOffset.get(filtNames[i].toInt()));
162 
163  QString kBase = "INS" + QString::number(filterIKCode.get(filtNames[i].toInt()));
164  p_focalLength.push_back(getDouble(kBase+"_FOCAL_LENGTH"));
165  p_boreSightSample.push_back(getDouble(kBase+"_BORESIGHT_SAMPLE"));
166  p_boreSightLine.push_back(getDouble(kBase+"_BORESIGHT_LINE"));
167  }
168 
169  // Setup detector map
170  double frameletRate = (double) inst["InterframeDelay"] / 1000.0;
172  p_etStart, frameletRate, frameletSize);
173  dmap->SetDetectorSampleSumming(sumMode);
174  dmap->SetDetectorLineSumming(sumMode);
175 
176  // flipping disabled if already flipped
177  bool flippedFramelets = dataflipped;
178  dmap->SetFrameletOrderReversed(flippedFramelets, p_nframelets);
180 
181  // get instrument-specific sample offset
182  QString instModeId = inst["InstrumentModeId"][0].toUpper();
183  // For BW mode, add the mode (0,1 (non-polar) or 2,3 (polar)) used to
184  // acquire image
185  if (instModeId == "BW") {
186  instModeId += inst["Mode"][0];
187  // There are no offsets for BW mode.. there can only be 1 filter
188  // and there must be 1 filter.
189  p_frameletOffsets[0] = 0;
190  }
191 
192  ikernKey = instCode + "_" + instModeId + "_SAMPLE_OFFSET";
193  int sampOffset = getInteger(ikernKey);
194  dmap->SetStartingDetectorSample(sampOffset+1);
195 
196  // Setup focal plane and distortion maps
199  for ( int i = 0 ; i < filtNames.size() ; i++ ) {
200  fplane->addFilter(filterIKCode.get(filtNames[i].toInt()));
201  distort->addFilter(filterIKCode.get(filtNames[i].toInt()));
202  }
203 
204  // Setup the ground and sky map
205  bool evenFramelets = (inst["Framelets"][0].toUpper() == "EVEN");
206  new PushFrameCameraGroundMap(this, evenFramelets);
207  new CameraSkyMap(this);
208 
209  SetBand(1);
210  LoadCache();
212 
213  if(instId == "WAC-UV") {
214  // geometric tiling is not worth trying for 4-line framelets
216  }
217  else {
219  }
220  }
221 
222 
223 
226  }
227 
228 
229 
235  void LroWideAngleCamera::SetBand(const int vband) {
236 
237  // Sanity check on requested band
238  int maxbands = min(p_detectorStartLines.size(), p_frameletOffsets.size());
239  if ((vband <= 0) || (vband > maxbands)) {
240  ostringstream mess;
241  mess << "Requested virtual band (" << vband
242  << ") outside valid (BandBin/Center) limits (1 - " << maxbands
243  << ")";
244  throw IException(IException::Programmer, mess.str(), _FILEINFO_);
245  }
246 
247  // Set up valid band access
248  Camera::SetBand(vband);
249  PushFrameCameraDetectorMap *dmap = NULL;
251  dmap->SetBandFirstDetectorLine(p_detectorStartLines[vband - 1]);
252  dmap->SetFrameletOffset(p_frameletOffsets[vband - 1]);
253 
254  SetFocalLength(p_focalLength[vband-1]);
255 
257  fplane->setBand(vband);
258  fplane->SetDetectorOrigin(p_boreSightSample[vband-1] + 1.0,
259  p_boreSightLine[vband-1] + 1.0);
260 
262  distort->setBand(vband);
263  return;
264  }
265 
266 
267 
272  int LroWideAngleCamera::PoolKeySize(const QString &key) const {
273  SpiceBoolean found;
274  SpiceInt n;
275  SpiceChar ctype[1];
276  dtpool_c(key.toAscii().data(), &found, &n, ctype);
277  if (!found) n = 0;
278  return (n);
279  }
280 
281 
282 
288  QVariant poolKeySize = getStoredResult(key + "_SIZE", SpiceIntType);
289 
290  int nvals = poolKeySize.toInt();
291 
292  if (nvals == 0) {
293  nvals = PoolKeySize(key);
294  storeResult(key + "_SIZE", SpiceIntType, nvals);
295  }
296 
297  if (nvals <= 0) {
298  QString mess = "Kernel pool keyword " + key + " not found!";
300  }
301 
302  IntParameterList parms;
303  for (int i = 0 ; i < nvals ; i++) {
304  parms.push_back(getInteger(key, i));
305  }
306 
307  return (parms);
308  }
309 
310 
311 
318  return false;
319  }
320 
321 
322 
330  return (-85000);
331  }
332 
333 
334 
342  return (1);
343  }
344 
345 
346 
354  return (1);
355  }
356 
357 }
358 
359 
360 // Plugin
372  return new Isis::LroWideAngleCamera(cube);
373 }