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