Isis 3 Programmer Reference
MdisCamera.cpp
Go to the documentation of this file.
1 
23 #include <cmath>
24 
25 #include <QString>
26 #include <QVariant>
27 
28 #include "MdisCamera.h"
30 
31 #include "CameraDetectorMap.h"
32 #include "CameraDistortionMap.h"
33 #include "CameraFocalPlaneMap.h"
34 #include "CameraGroundMap.h"
35 #include "CameraSkyMap.h"
36 #include "IException.h"
37 #include "IString.h"
38 #include "iTime.h"
39 #include "NaifStatus.h"
40 
41 using namespace std;
42 
43 namespace Isis {
64  MdisCamera::MdisCamera(Cube &cube) : FramingCamera(cube) {
65  m_spacecraftNameLong = "Messenger";
66  m_spacecraftNameShort = "Messenger";
67 
69 
70  // Set up detector constants
71  // Note that Wac has filters, -236800 through -236812
72  // http://naif.jpl.nasa.gov/pub/naif/pds/data/mess-e_v_h-spice-6-v1.0/messsp_1000/data/ik/msgr_mdis_v160.ti
73  const int MdisWac(-236800);
74  const int MdisNac(-236820);
75 
76  if (naifIkCode() == MdisNac) {
77  m_instrumentNameLong = "Mercury Dual Imaging System Narrow Angle Camera";
78  m_instrumentNameShort = "MDIS-NAC";
79  }
80  else if (naifIkCode() <= MdisWac && naifIkCode() >= -236812) {
81  m_instrumentNameLong = "Mercury Dual Imaging System Wide Angle Camera";
82  m_instrumentNameShort = "MDIS-WAC";
83  }
84  else {
85  QString msg = QString::number(naifIkCode());
86  msg += " is not a supported instrument kernel code for Messenger.";
88  }
89 
90  Pvl &lab = *cube.label();
91  PvlGroup &inst = lab.findGroup("Instrument", Pvl::Traverse);
92 
93  // Clarification on MDIS subframe image mode provides us the ability to
94  // support this mode now. The entire MDIS frame is geometrically valid
95  // but only portions of the full frame actually contain image data. The
96  // portions outside subframes should be NULL and not interfere in
97  // downstream processing, such as mosaics.
98 #if defined(MDIS_SUBFRAMES_UNSUPPORTED)
99  int subFrameMode = inst["SubFrameMode"];
100  if(subFrameMode != 0) {
101  string msg = "Subframe imaging mode is not supported!";
102  throw iException::Message(iException::User, msg, _FILEINFO_);
103  }
104 #endif
105 
106  // According to the MDIS team, this is nothing to be concerned with and
107  // should be treated as other normal observations. So the test to
108  // disallow it has been effectively removed 2007-09-05 (KJB).
109 #if defined(MDIS_JAILBARS_UNSUPPORTED)
110  int jailBars = inst["JailBars"];
111  if(jailBars != 0) {
112  string msg = "Jail bar observations are not currently supported!";
113  throw iException::Message(iException::Programmer, msg, _FILEINFO_);
114  }
115 #endif
116 
117  // Determine filter number. Only conditional code required for
118  // NAC and WAC support!
119  int filterNumber(0); // Default appropriate for MDIS-NAC
120  if(naifIkCode() == MdisWac) {
121  PvlGroup &bandBin = lab.findGroup("BandBin", Pvl::Traverse);
122  filterNumber = bandBin["Number"];
123  }
124 
125  // Set up instrument and filter code strings
126  QString ikCode = toString(naifIkCode());
127  int fnCode(naifIkCode() - filterNumber);
128  QString filterCode = toString(fnCode);
129  QString ikernKey;
130 
131  // Fetch the frame translations from the instrument kernels
132  ikernKey = "INS" + ikCode + "_REFERENCE_FRAME";
133  QString baseFrame = getString(ikernKey);
134 
135  ikernKey = "INS" + filterCode + "_FRAME";
136  QString ikFrame = getString(ikernKey);
137 
138  // Set up the camera info from ik/iak kernels
139 
140  // Turns out (2008-01-17) the WAC has different focal lengths for
141  // each filter. Added to the instrument kernel (IAK) on this date.
142  // Add temperature dependant focal length
143  SetFocalLength(computeFocalLength(filterCode, lab));
144 
145  SetPixelPitch();
146 
147  // Removed by Jeff Anderson. The refactor of the SPICE class
148  // uses frames always so this is no longer needed
149  // LoadFrameMounting(baseFrame, ikFrame, false);
150 
151  // Get the start time from labels as the starting image time plus half
152  // the exposure duration (in <MS>) to get pointing attitude.
153  // !!NOTE: The ephemeris time MUST be set prior to creating the
154  // cache (CreateCache) because the kernels are all unloaded
155  // after the cache is done and this operation will fail!!
156  QString stime = inst["SpacecraftClockCount"];
157  double exposureDuration = ((double) inst["ExposureDuration"]) / 1000.0;// divide by 1000 to convert to seconds
158 
159  iTime etStart = getClockTime(stime);
160 
161  // Setup camera detector map
162  CameraDetectorMap *detMap = new CameraDetectorMap(this);
163 
164  // Setup focal plane map, and detector origin for the instrument that
165  // may have a filter (WAC only!).
166  CameraFocalPlaneMap *focalMap = new CameraFocalPlaneMap(this, fnCode);
167 
168  // Retrieve boresight location from instrument kernel (IK) (addendum?)
169  ikernKey = "INS" + ikCode + "_BORESIGHT_SAMPLE";
170  double sampleBoreSight = getDouble(ikernKey);
171 
172  ikernKey = "INS" + ikCode + "_BORESIGHT_LINE";
173  double lineBoreSight = getDouble(ikernKey);
174 
175  // Apply the boresight
176  focalMap->SetDetectorOrigin(sampleBoreSight, lineBoreSight);
177 
178  // Determine summing. MDIS has two sources of summing or binning.
179  // One is performed in the FPU and the in the MP, post-observation,
180  // on-board after coming out of the FPGAs, where the FPU binning is
181  // performed. The FPU binning was programmed incorrectly and the
182  // actual pixels from the detector are peculiar. Hence, I have
183  // designed this camera model such that the offsets can be managed
184  // external to the code. See the MDIS instrument kernel addendum
185  // in $ISIS3DATA/messenger/kernels/iak/mdisAddendum???.ti for the
186  // offsets for *each* detector. Note that an offset is only applied
187  // when FPU binning is performed.
188  int fpuBinMode = inst["FpuBinningMode"];
189  int pixelBinMode = inst["PixelBinningMode"];
190 
191  int summing = ((pixelBinMode == 0) ? 1 : pixelBinMode);
192  // FPU binning was performed, retrieve the FPU binning offsets and
193  // apply them to the focal plane mapping.
194  if(fpuBinMode == 1) {
195 #if defined(USE_FPU_BINNING_OFFSETS)
196  ikernKey = "INS" + ikCode + "_FPUBIN_START_SAMPLE";
197  double fpuStartingSample = getDouble(ikernKey);
198  detMap->SetStartingDetectorSample(fpuStartingSample);
199 
200  ikernKey = "INS" + ikCode + "_FPUBIN_START_LINE";
201  double fpuStartingLine = getDouble(ikernKey);
202  detMap->SetStartingDetectorLine(fpuStartingLine);
203 #endif
204  summing *= 2;
205  }
206 
207  // Set summing/binning modes as an accumulation of FPU and MP binning.
208  detMap->SetDetectorLineSumming(summing);
209  detMap->SetDetectorSampleSumming(summing);
210 
211  // Setup distortion map. As of 2007/12/06, we now have an actual model.
212  // Note that this model supports distinct distortion for each WAC filter.
213  // See $ISIS3DATA/messenger/kernels/iak/mdisAddendumXXX.ti or possibly
214  // $ISIS3DATA/messenger/kernels/ik/msgr_mdis_vXXX.ti for the *_OD_K
215  // parameters.
216  // NAC has a new implementation of its distortion contributed by
217  // Scott Turner and Lillian Nguyen at JHUAPL.
218  // (2010/10/06) The WAC now uses the same disortion model implementation.
219  // Valid Taylor Series parameters are in versions msgr_mdis_v120.ti IK
220  // and above. Note fnCode works for NAC as well as long as
221  // filterNumber stays at 0 for the NAC only!
222  try {
223  TaylorCameraDistortionMap *distortionMap = new TaylorCameraDistortionMap(this);
224  distortionMap->SetDistortion(fnCode);
225  }
226  catch(IException &ie) {
227  string msg = "New MDIS NAC/WAC distortion models will invalidate previous "
228  "SPICE - you may need to rerun spiceinit to get new kernels";
229  throw IException(ie, IException::User, msg, _FILEINFO_);
230  }
231 
232  // Setup the ground and sky map
233  new CameraGroundMap(this);
234  new CameraSkyMap(this);
235 
236  // Create a cache and grab spice info since it does not change for
237  // a framing camera (fixed spacecraft position and pointing) after,
238  // of course applying the gimble offset which is handled in the SPICE
239  // kernels (thank you!). Note this was done automagically in the
240  // SetEpheremisTime call above. IMPORTANT that it be done prior to
241  // creating the cache since all kernels are unloaded, essentially
242  // clearing the pool and whacking the frames definitions, required to
243  iTime centerTime = etStart + (exposureDuration / 2.0);
244  setTime(centerTime);
245  LoadCache();
247  }
248 
249 
271  pair <iTime, iTime> MdisCamera::ShutterOpenCloseTimes(double time,
272  double exposureDuration) {
274  }
275 
276 
306  double MdisCamera::computeFocalLength(const QString &filterCode,
307  Pvl &label) {
308 
309  double focalLength(0.0);
310  QString tdflKey("TempDependentFocalLength");
311 
312  // Determine if the desired value is already computed. We are interested
313  // in the temperature dependent value firstly. Backward compatibility is
314  // considered below.
315  QVariant my_tdfl = readStoredValue(tdflKey, SpiceStringType, 0);
316  if (my_tdfl.isValid()) {
317  focalLength = IString(my_tdfl.toString()).ToDouble();
318  }
319  else {
320  // Hasn't been computed yet (in spiceinit now - maybe) or the proper
321  // IK containing polynomial parameters is not in use.
322 
323  // Original Code ensures backward compatibility
324  focalLength = getDouble("INS" + filterCode + "_FOCAL_LENGTH");
325 
326  // Check for disabling of temperature dependent focal length
327  bool tdfl_disabled(false);
328 #ifndef DISABLE_TDFL_DISABLING
329  try {
330  IString tdfl_state = getString("DISABLE_MDIS_TD_FOCAL_LENGTH");
331  tdfl_disabled = ( "TRUE" == tdfl_state.UpCase() );
332  }
333  catch (IException &ie) {
334  tdfl_disabled = false;
335  }
336 #endif
337 
338  // Attempt to retrieve parameters necessary for temperature-dependent focal
339  // length and computed it
340  if ( !tdfl_disabled ) {
341  // Wrap a try clause all around this so that if it fails, will return
342  // default
343  try {
344  PvlGroup &inst = label.findGroup("Instrument", Pvl::Traverse);
345  double fpTemp = inst["FocalPlaneTemperature"];
346  double fl(0.0);
347  QString fptCoeffs = "INS" + filterCode + "_FL_TEMP_COEFFS";
348  // Compute 5th order polynomial
349  for (int i = 0 ; i < 6 ; i++) {
350  fl += getDouble(fptCoeffs, i) * pow(fpTemp, (double) i);
351  }
352 
353  // Store computed focal length
354  focalLength = fl;
355  storeValue(tdflKey, 0, SpiceStringType, QVariant(focalLength));
356  }
357  catch (IException &ie) {
358  // Noop when supporting old IKs
360  "Failed to compute temperature-dependent focal length",
361  _FILEINFO_);
362  }
363  }
364  }
365  return (focalLength);
366  }
367 }
368 
378  return new Isis::MdisCamera(cube);
379 }
void SetFocalLength()
Reads the focal length from the instrument kernel.
Definition: Camera.cpp:1430
PvlGroupIterator findGroup(const QString &name, PvlGroupIterator beg, PvlGroupIterator end)
Find a group with the specified name, within these indexes.
Definition: PvlObject.h:141
Parse and return pieces of a time string.
Definition: iTime.h:78
QString m_instrumentNameLong
Full instrument name.
Definition: Camera.h:507
void SetDetectorSampleSumming(const double summing)
Set sample summing mode.
Distort/undistort focal plane coordinates.
void SetPixelPitch()
Reads the Pixel Pitch from the instrument kernel.
Definition: Camera.cpp:1437
Namespace for the standard library.
double computeFocalLength(const QString &filterCode, Pvl &label)
Computes temperature-dependent focal length.
Definition: MdisCamera.cpp:306
Search child objects.
Definition: PvlObject.h:170
MESSENGER MDIS NAC and WAC Camera Model.
Definition: MdisCamera.h:109
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:226
void SetDetectorOrigin(const double sample, const double line)
Set the detector origin.
This error is for when a programmer made an API call that was illegal.
Definition: IException.h:162
void SetDetectorLineSumming(const double summing)
Set line summing mode.
void SetStartingDetectorLine(const double line)
Set the starting detector line.
virtual std::pair< iTime, iTime > ShutterOpenCloseTimes(double time, double exposureDuration)=0
Returns the shutter open and close times.
Convert between parent image coordinates and detector coordinates.
Convert between undistorted focal plane and ground coordinates.
Convert between distorted focal plane and detector coordinates.
QString m_instrumentNameShort
Shortened instrument name.
Definition: Camera.h:508
Contains multiple PvlContainers.
Definition: PvlGroup.h:57
SpiceInt naifIkCode() const
This returns the NAIF IK code to use when reading from instrument kernels.
Definition: Spice.cpp:893
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
A type of error that could only have occurred due to a mistake on the user&#39;s part (e...
Definition: IException.h:142
Isis::Camera * MdisCameraPlugin(Isis::Cube &cube)
This is the function that is called in order to instantiate a MdisCamera object.
Definition: MdisCamera.cpp:377
virtual std::pair< iTime, iTime > ShutterOpenCloseTimes(double time, double exposureDuration)
Returns the shutter open and close times.
Definition: MdisCamera.cpp:271
iTime getClockTime(QString clockValue, int sclkCode=-1, bool clockTicks=false)
This converts the spacecraft clock ticks value (clockValue) to an iTime.
Definition: Spice.cpp:977
void setTime(const iTime &time)
By setting the time you essential set the position of the spacecraft and body as indicated in the cla...
Definition: Sensor.cpp:112
Container for cube-like labels.
Definition: Pvl.h:135
double ToDouble(const T &value)
Helper function to convert values to doubles.
Definition: HiCalUtil.h:248
void LoadCache()
This loads the spice cache big enough for this image.
Definition: Camera.cpp:2432
QString getString(const QString &key, int index=0)
This returns a value from the NAIF text pool.
Definition: Spice.cpp:1185
QString m_spacecraftNameLong
Full spacecraft name.
Definition: Camera.h:509
Pvl * label() const
Returns a pointer to the IsisLabel object associated with the cube.
Definition: Cube.cpp:1346
void SetStartingDetectorSample(const double sample)
Set the starting detector sample.
SpiceString type.
Definition: Spice.h:359
static void CheckErrors(bool resetNaif=true)
This method looks for any naif errors that might have occurred.
Definition: NaifStatus.cpp:43
Isis exception class.
Definition: IException.h:107
Adds specific functionality to C++ strings.
Definition: IString.h:181
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
void SetDistortion(const int naifIkCode)
Load distortion coefficients.
Convert between undistorted focal plane and ra/dec coordinates.
Definition: CameraSkyMap.h:48
QString m_spacecraftNameShort
Shortened spacecraft name.
Definition: Camera.h:510
virtual double exposureDuration() const
Return the exposure duration for the pixel that the camera is set to.
Definition: Camera.cpp:3075
Generic class for Framing Cameras.
Definition: FramingCamera.h:48
IString UpCase()
Converst any lower case characters in the object IString with uppercase characters.
Definition: IString.cpp:632
SpiceDouble getDouble(const QString &key, int index=0)
This returns a value from the NAIF text pool.
Definition: Spice.cpp:963
IO Handler for Isis Cubes.
Definition: Cube.h:170
iTime time() const
Returns the ephemeris time in seconds which was used to obtain the spacecraft and sun positions...
Definition: Spice.cpp:809