The following code in Camera.cpp is not working as intended:
For:
void Camera::GetLocalNormal(double normal[3]) {
The following lines are not working as intended:
QList< QPair< double, double > > surroundingPoints;
surroundingPoints.append(qMakePair(samp, line - 0.5));
surroundingPoints.append(qMakePair(samp, line + 0.5 - DBL_MIN));
surroundingPoints.append(qMakePair(samp - 0.5, line));
surroundingPoints.append(qMakePair(samp + 0.5 - DBL_MIN, line));
Currently the DBL_MIN is not operating as expected. The functionality that is intended is:
Calculate normal by grabbing elevation values at the edges of the pixel in question.
What is actually happening:
The values gathered are still not from the same pixel. It appears as though the DBL_MIN is not subtracting more than the rounding error, and this is essentially returning the same value as if the code was:
QList< QPair< double, double > > surroundingPoints;
surroundingPoints.append(qMakePair(samp, line - 0.5));
surroundingPoints.append(qMakePair(samp, line + 0.5));
surroundingPoints.append(qMakePair(samp - 0.5, line));
surroundingPoints.append(qMakePair(samp + 0.5, line));
This is detrimental when calculating photometric angles for push-broom and push-frame cameras, because 1.0 could be the pixel center, 0.5 is the edge of pixel 1, but 1.5 is the edge of pixel 2. This does not work well when a push-broom imager is flying in a reverse direction, or for frame boundaries of a push-frame camera. The calculation is using a completely wrong location on the body.
This is a high priority for almost all missions currently using ISIS.
@AaronBoyd Do you have a good example to reproduce this or is this happening in all images?
This happens noticeably in every push-frame image, but here are a couple where the photometric angle difference can be seen at the frame boundaries:
http://wms.lroc.asu.edu/lroc/view_lroc/LRO-L-LROC-2-EDR-V1.0/M1099201504ME
http://wms.lroc.asu.edu/lroc/view_lroc/LRO-L-LROC-2-EDR-V1.0/M1229850147ME
lrowac2isis from= image.IMG to=image.cub
spiceinit from= image.vis.even.cub
phocube from= image.vis.even.cub to= image.vis.even.pho.cub localemission=true localincidence=true incidence=false emission=false dn=true


Here is an example that reproduces the problem. I ran segment to speed up the process since you don't need the entire image to see the bug.
wget http://pds.lroc.asu.edu/data/LRO-L-LROC-2-EDR-V1.0/LROLRC_0013/DATA/ESM/2012303/WAC/M1106181887CE.IMG
lrowac2isis from=M1106181887CE.IMG to=WAC.cub
spiceinit from=WAC.vis.odd.cub
lrowaccal from= WAC.vis.odd.cub to= WAC.vis.odd.cal.cub
segment from=WAC.vis.odd.cal.cub nl=280 o=0
phocube from=WAC.vis.odd.cal.segment1.cub+4 to=WAC.backplane.643.cub EMISSION=no INCIDENCE=no LOCALEMISSION=yes LOCALINCIDENCE=yes
You can qview the output (WAC.backplane.643.cub) to inspect the local backplanes. If you zoom into band 2 of the image at ~400%, you can see the last line of each 14 line framelet has the incorrect photometric angles since the next surrounding pixel is in the next framelet. If 0.49 is used then the pixel boundaries are all within the framelet, then the local angles are computed correctly and this single line band pattern at the bottom of the framelet go away.
Now you have two examples that show the problem ;)
@AaronBoyd pictures show the problem we are seeing with the WAC.
@jessemapel for reference, the code works correctly if using:
QList< QPair< double, double > > surroundingPoints;
surroundingPoints.append(qMakePair(samp, line - 0.49));
surroundingPoints.append(qMakePair(samp, line + 0.49));
surroundingPoints.append(qMakePair(samp - 0.49, line));
surroundingPoints.append(qMakePair(samp + 0.49, line));
@AaronBoyd @espeyerer Thanks for the detailed examples! I'm not sure why this is happening, we use DBL_MIN like this in several places and haven't had issue before. A bit of googling turns up nexttoward from c++11. That would allow us to get the largest double that is less than line+0.5.
For future reference. This line is where the framelet is computed. The integer rounding here is working incorrectly and returning the next/previous framelet.
Okay, so if we wanted to implement a short term fix, what would you recommend @jessemapel ?
I don't quite see where the rounding issue is on Line 160.
Thank you in advance!
I would try modifying the code in Camera::GetLocalNormal to this:
QList< QPair< double, double > > surroundingPoints;
surroundingPoints.append(qMakePair(samp, line - 0.5));
surroundingPoints.append(qMakePair(samp, std::nexttoward(line + 0.5, line)));
surroundingPoints.append(qMakePair(samp - 0.5, line));
surroundingPoints.append(qMakePair(std::nexttoward(samp + 0.5, samp), line));
In the detector map, the cast to an integer is rounding:
int framelet = (int)((line - 0.5) / actualFrameletHeight) + 1;
In the pixels on the edge of the framelet, this is rounding incorrectly and mapping to the next/previous framelet.
@AaronBoyd @espeyerer Did the proposed short term fix end up working for you? If so, would you be up for putting in a PR with the change?
For testing, two ideas I came up with are
Most helpful comment
Here is an example that reproduces the problem. I ran segment to speed up the process since you don't need the entire image to see the bug.
You can qview the output (WAC.backplane.643.cub) to inspect the local backplanes. If you zoom into band 2 of the image at ~400%, you can see the last line of each 14 line framelet has the incorrect photometric angles since the next surrounding pixel is in the next framelet. If 0.49 is used then the pixel boundaries are all within the framelet, then the local angles are computed correctly and this single line band pattern at the bottom of the framelet go away.