planetarypy / planetaryimage

Python PDS and Isis Cube file parser.
BSD 3-Clause "New" or "Revised" License
39 stars 20 forks source link

PDS3 Image decodes Lunar Reconnaissance Orbiter Camera Narrow Angle Camera EDR images as signed 8-bit images instead of unsigned 8-bit images #78

Open benmoseley opened 4 years ago

benmoseley commented 4 years ago

Problem: The LROC NAC EDR images contain 8-bit unsigned raw instrument DN counts, although the PDS3Image class decodes them to signed 8-bit integers. This leads to incorrect DN values in the imported numpy image array.

Reason: This is because the EDR binary files have "SAMPLE_TYPE = LSB_INTEGER" in their PDS3 header, which is interpreted by PDS3Image class as a signed integer.

Solution: I am unsure if this is an issue with the PDS3Image class mapping from SAMPLE_TYPE values to numpy dtypes, or if the EDR file header SAMPLE_TYPE values are incorrect. Potentially the SAMPLE_TYPE mapping should be updated, or a specific exception for NAC EDR images could be made.

AndrewAnnex commented 4 years ago

Hey @benmoseley, if you need a more immediate solution (as I am aware of FDL) I would recommend trying to use gdal's pds driver via the rasterio project which should probably do the right thing and get your edr loaded to the correct numpy dtype.

Confusingly in the pds3 spec here: "https://pds.jpl.nasa.gov/datastandards/pds3/standards/sr/Chapter03.pdf" LSB_INTEGER maps to "1-, 2-, and 4-byte signed integers" so logically the data would be 4 byte signed not 8 byte unsigned. If the data really is unsigned then the pds label should say "LSB_UNSIGNED_INTEGER" instead but it would still be 4 byte according to the spec. I don't know who is correct in this situation, but I would be surprised if such a significant error in the label was present.

cmillion commented 4 years ago

SAMPLE_TYPE in PDS3 is all over the place in terms of what it maps to. This kind of issue is common.

benmoseley commented 4 years ago

Thanks both, I came up with a simple workaround for this problem below, which works fine for this particular problem.

class PDS3ImageEDR(PDS3Image):
    """EDR image class, extends PDS3Image class by fixing LROC NAC EDR images decoding bug.
    """

    # this fixes the decoding bug by overriding the class SAMPLE_TYPE and DTYPES attributes

    SAMPLE_TYPES = {
        'LSB_INTEGER': '<u',
    }

    DTYPES = {
        '<u': 'LSB_INTEGER',
    }