Isis 3.0 Programmer Reference
Back | Home
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) {
273  return FramingCamera::ShutterOpenCloseTimes(time, 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:1485
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:74
QString m_instrumentNameLong
Full instrument name.
Definition: Camera.h:494
void SetDetectorSampleSumming(const double summing)
Set sample summing mode.
Pvl * label() const
Returns a pointer to the IsisLabel object associated with the cube.
Definition: Cube.cpp:1298
Distort/undistort focal plane coordinates.
void SetPixelPitch()
Reads the Pixel Pitch from the instrument kernel.
Definition: Camera.cpp:1492
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:154
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.
virtual double exposureDuration() const
Return the exposure duration for the pixel that the camera is set to.
Definition: Camera.cpp:3113
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:495
Contains multiple PvlContainers.
Definition: PvlGroup.h:57
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:38
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:134
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
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
void LoadCache()
This loads the spice cache big enough for this image.
Definition: Camera.cpp:2489
QString getString(const QString &key, int index=0)
This returns a value from the NAIF text pool.
Definition: Spice.cpp:1172
QString m_spacecraftNameLong
Full spacecraft name.
Definition: Camera.h:496
void SetStartingDetectorSample(const double sample)
Set the starting detector sample.
SpiceString type.
Definition: Spice.h:346
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:99
SpiceInt naifIkCode() const
This returns the NAIF IK code to use when reading from instrument kernels.
Definition: Spice.cpp:888
Adds specific functionality to C++ strings.
Definition: IString.h:179
void SetDistortion(const int naifIkCode)
Load distortion coefficients.
iTime getClockTime(QString clockValue, int sclkCode=-1)
This converts the spacecraft clock ticks value (clockValue) to an iTime.
Definition: Spice.cpp:969
Convert between undistorted focal plane and ra/dec coordinates.
Definition: CameraSkyMap.h:47
QString m_spacecraftNameShort
Shortened spacecraft name.
Definition: Camera.h:497
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:958
IO Handler for Isis Cubes.
Definition: Cube.h:158

U.S. Department of the Interior | U.S. Geological Survey
ISIS | Privacy & Disclaimers | Astrogeology Research Program
To contact us, please post comments and questions on the ISIS Support Center
File Modified: 07/12/2023 23:23:17