Closed jlaura closed 2 years ago
This is expected behavior based on the module's design. Of course, that doesn't mean that it is the right behavior.
The pvl module's approach is: read everything, but write out standards-compliant PDS3 labels by default. From the README:
On the flip side, when dumping a Python object to PVL text (via pvl.dumps() and pvl.dump()), the library will default to writing PDS3-Standards-compliant PVL text, which in some ways is the most restrictive, but the most likely version of PVL text that you need if you're writing it out (this is different from pre-1.0 versions of pvl).
Don't get me wrong, these different versions of PVL-text, the lack of consistent validating software, and the permissiveness of the format structure over three decades have resulted in quite a mess. The pre-1.0 versions of pvl did not distinguish between the different "dialects" of PVL-text: strict PVL, ODL, PDS3 ODL, and ISIS PVL-text that pvl now does. The pre-1.0 pvl read as much as it could, and wrote out PVL-text which conformed to the PVL standard, but with some options. You can make pvl write out PVL-text like the pre-1.0 architecture via:
pvl.dumps(label, encoder=pvl.PVLEncoder(end_delimiter=False, newline='\r\n')).encode()
It decided to forego the optional-but-recommended end-delimiter, and opted for \r\n
newlines.
This meant that the PVL-text that pvl used to write out would not validate against the PDS3 standard, at the very least. And while we use the acronym "PVL" all the time and think about PDS3 labels as "PVL" they really aren't. In fact, almost no one really uses strict PVL. The PDS3 standard is actually a variation on ODL (neither a strict sub-set nor a super-set of ODL, because that would have been too useful), which is itself a variation on PVL.
Therefore it would be incorrect to assume that strict PVL is a superset of all possible PVL-text, and assume that it spans a wider gamut of PVL-text possibilities. No matter what "output dialect" we settled on for the "default," there exists broken PVL-text that could be read by the omnivorous parser but would not be able to be written for any particular dialect (so just as you have this example that cannot be written to PDS3 PVL-text, we could also construct examples that do the same for strict PVL PVL-text, ODL PVL-text, etc.).
Given the spread of bad options, the decision was made for the default writing-out to be PDS3 based on the presumptions described in the README. If the output would not be written out to a strict PDS3 format, what dialect would you suggest? And why?
I suppose we could rescind the "default" option, and require an output dialect choice, which might make users more "aware" of their choices, but it might not.
You talk about a "round trip" through the library, but that's not really how pvl is constructed. The "load" operation is atomic and distinct, it converts PVL-text to a Python dict-like, but that Python dict-like doesn't "remember" that it was once PVL-text. The "dump" operations are similarly distinct, they take any Python dict-like and attempt to write out the PVL-text specified by the encoder.
I suppose we could attempt to determine whether the "loaded" PVL-text conformed to a particular dialect, and hold on to that in the returned dict-like. However, that would require multiple decodings of the PVL-text to determine which dialects it conformed to (or none). And then if the "dump" operations got a dict-like that had been made by the loaders they could use that dialect-type as the "default" dialect to encode. However, we'd still error if the loaders could not determine a dialect type, or if the Python dict-like was not made by the pvl module.
Alternately, rather than pay the price on "load" we could pay it on "dump." If a Python dict-like can't be written out as PDS3-compliant PVL-text, maybe try ODL or PVL, and if those work, write them out that way, and only fail if no possible dialect can be used.
I'm not super-wild about these options, because I think it will increase the amount of non-PDS3-compliant PVL-text, but maybe that's a silly concern.
Another alternate would be if the Python dict-like couldn't be written as PDS3-compliant PVL-text, attempt the alternate encodings, and still error, but let the user know that maybe specifying a different encoding would work (and then be explicit about what the code line is that would work). This would increase the process time of the error process (but typically dict-likes processed by pvl are pretty small), would maintain the current behavior, but would provide better feedback to the user.
@rbeyer I appreciate the walk through the logic and apologize for the delay in responding. The issue got lost in a mountain of start of the year GitHub notifications.
First, this is a bummer that we do not have one consistent standard that we can depend upon. Having gotten that out of the way, I understand why the choice was made and think that trying to consistently guess what flavor of the specification in the one that is desired is not a particularly attractive solution.
I think the best approach is to close this issue and chock this up to case of RTFM for the user. Question: Are the differences between these PVL flavors documented anywhere or is this knowledge bouncing around in the maintainers heads? I ask because my tenuous, maybe helpful solution, would be to link the quoted documentation text above to some indication of what PDS3 compliant PVL supports that other formats do not. I am also very happy to see this closed with a read the docs.
I suspect I am further muddying the waters because what I really want to do is push the PVL to JSON, remap the obnoxious duplicate keys (OBJECT = TABLE anyone...), and then push this into JSONB for efficient database work. This is not pertinent to this issue, but an example where this 'standard' is meeting another 'standard' (both pejorative quotes because both are permissive enough to be problematic at the implementation level) and causing lots of friction.
@jlaura that's a fair solution. There was an existing documentation page: https://pvl.readthedocs.io/en/latest/standards.html, to which I added the third paragraph there which might be useful, but please feel free to PR any other items from our exchange above that you think a new user would find valuable.
Tell me more about this conversion to JSON that you need. I'm not sure why that would require a "round trip" through pvl. Seems like you'd want to do a pvl.load()
to get started, and then manipulate the returned dict-like in Python to eliminate duplicate keys, etc., and then just use the Python standard library json
module to write that dict out to a .json file rather than trying to write out some PVL-text, but there's clearly other stuff going on.
I'll check that and get a PR in if appropriate. Thanks!
The only reason to round trip is entirely lazy and artificial. Support I don't want to store the ISIS data or the ISIS label, but want to provide a cloud optimized geotiff with an associated ISIS label. I might: preprocess to cub -> pull the isis label into a DB (as JSONB with remapped keys) -> convert the cub to COG and delete the cub -> write ancillary data (e.g., the label). It would be 'nice' to keep the data only in a DB AND use the data in the DB for efficient queries (so JSONB is a must). In all honesty, this is asking the DB/Data to do a lot all at once for convenience and a small amount of storage savings.
^^^^^^^^^^^^nice to have but not a thing.
I'm going to close this, but feel free to re-open if needed.
Describe the bug Using the caminfo file reproduced at the end of this report,
pvl
reads the file with no issue. When I attempt to dump back to a string, pvl errors with the following ValueError.To Reproduce
Expected behavior I would expect to be able to round trip PVL data through the library.
Error logs or terminal captures
Your Environment (please complete the following information):
pvl
Version: 1.2.1Additional context
This works when I specify the encoder, but I am not confident that a newish user would read the docs and test a different encoder when they see a time precision error on a PVL file that is round tripped.
This works:
caminfo.pvl
``` Object = Caminfo Object = Parameters Program = caminfo IsisVersion = "6.0.0 | 2021-08-31" RunDate = 2021-10-02T13:49:39 IsisId = KAGUYA/TC1/2008-07-17T20:15:35.204835 From = TC1S2B0_01_03448S320E0799.cub Lines = 4656 Samples = 3496 Bands = 1 End_Object Object = IsisLabel Object = IsisCube Object = Core StartByte = 65537 Format = Tile TileSamples = 874 TileLines = 776 Group = Dimensions Samples = 3496 Lines = 4656 Bands = 1 End_Group Group = Pixels Type = SignedWord ByteOrder = Lsb Base = 0.0 Multiplier = 0.013 End_Group End_Object Group = Instrument MissionName = SELENE SpacecraftName = KAGUYA InstrumentName = "TERRAIN CAMERA 1" InstrumentId = TC1 TargetName = MOON ObservationModeId = NORMAL SensorDescription = "Imagery type:Pushbroom. ImageryMode:Mono,Stereo. ExposureTimeMode:Long,Middle,Shor- t. CompressionMode:NonComp,DCT. Q-table:32 patterns. H-table:4 patterns. SwathMode:F(Full),N(Nominal),H(Ha- lf). First pixel number:1(F),297(N),1172(H)." SensorDescription2 = "Pixel size:7x7[micron^2](TC1/TC2). Wavelength range:430-850[nm](TC1/TC2). A/D rate:10[bit](TC1/TC2). Slant angle:+/-15[degree] (from nadir to +x of S/C)(TC1/TC2). Focal length:72.45/72.63[mm](TC1/TC2). F number:3.97/3.98(TC1/TC2)." StartTime = 2008-07-17T20:15:35.204835 StopTime = 2008-07-17T20:16:05.462060 OriginalStartTime = 2008-07-17T20:15:35.206200 OriginalStopTime = 2008-07-17T20:16:05.463700 ExposureModeId = MIDDLE ExposureDuration = 3.250000" OriginalSpacecraftClockStopCount = "900360957.5290" SpacecraftClockStartCount = 900360927.270135SpacecraftClockStopCount = 900360957.527360OriginalLineSamplingInterval = 6.500000
LineSamplingInterval = 6.499941
SwathModeId = NOMINAL
IlluminationCondition = EVENING
End_Group
Group = Archive
ProductId = TC1S2B0_01_03448S320E0799
SoftwareName = RGC_TC_s_Level2B0
SoftwareVersion = 1.0.0
ProcessVersionId = L2B
ProductCreationTime = 2013-06-08T05:20:08
ProgramStartTime = 2013-06-08T05:13:02
ProducerId = LISM
ProductSetId = TC_s_Level2B0
ProductVersionId = 01
RegisteredProduct = Y
Level2AFileName = TC1S2A0_02DMN03448_002_0033.img
SpiceMetakernelFileName = RGC_INF_TCv401IK_MIv200IK_SPv105IK_RISE-
100i_05_LongCK_D_V02_de421_110706.mk
DataSetId = SLN-L-TC-3-S-LEVEL2B0-V1.0
ImageValueType = RADIANCE
ImageUnit = W/m**2/micron/sr
MinForStatisticalEvaluation = 0
MaxForStatisticalEvaluation = 32767
SceneMaximumDn = 3161
SceneMinimumDn = 0
SceneAverageDn = 345.0
SceneStdevDn = 266.9
SceneModeDn = 18
ShadowedAreaMinimum = 0
ShadowedAreaMaximum = 0
ShadowedAreaPercentage = 0
InvalidType = (SATURATION, MINUS, DUMMY_DEFECT, OTHER)
InvalidValue = (-20000, -21000, -22000, -23000)
InvalidPixels = (0, 2, 0, 0)
DarkFileName = TC1_DRK_02952_04739_M_C_b05.csv
FlatFileName = TC1_FLT_00293_04739_N_C_b05.csv
EfficFileName = TC1_EFF_PRFLT_N_N_v01.csv
NonlinFileName = TC1_NLT_PRFLT_N_N_v01.csv
RadCnvCoef = 3.790009
L2aDeadPixelThreshold = 30
L2aSaturationThreshold = 1023
DarkValidMinimum = -5
RadianceSaturationThreshold = 425.971000
UpperLeftLatitude = -32.789566
UpperLeftLongitude = 80.631630
UpperRightLatitude = -32.776189
UpperRightLongitude = 79.085159
LowerLeftLatitude = -31.266527
LowerLeftLongitude = 80.634632
LowerRightLatitude = -31.254154
LowerRightLongitude = 79.107535
End_Group
Group = BandBin
FilterName = BroadBand
Center = 640nm
Width = 420nm
End_Group
Group = Kernels
NaifCkCode = -131350
NaifFrameCode = -131351
LeapSecond = $base/kernels/lsk/naif0012.tls
TargetAttitudeShape = ($base/kernels/pck/pck00009.tpc,
$kaguya/kernels/pck/moon_080317.tf,
$kaguya/kernels/pck/moon_assoc_me.tf)
TargetPosition = (Table,
$kaguya/kernels/tspk/moon_pa_de421_1900-2-
050.bpc, $kaguya/kernels/tspk/de421.bsp)
InstrumentPointing = (Table,
$kaguya/kernels/ck/SEL_M_ALL_D_V02.BC,
$kaguya/kernels/fk/SEL_V01.TF)
Instrument = $kaguya/kernels/ik/SEL_TC_V01.TI
SpacecraftClock = $kaguya/kernels/sclk/SEL_M_V01.TSC
InstrumentPosition = (Table,
$kaguya/kernels/spk/SEL_M_071020_090610_S-
GMH_02.BSP)
InstrumentAddendum = $kaguya/kernels/iak/kaguyaTcAddendum007.ti
ShapeModel = $base/dems/ldem_128ppd_Mar2011_clon180_ra-
dius_pad.cub
InstrumentPositionQuality = Reconstructed
InstrumentPointingQuality = Reconstructed
CameraVersion = 2
Source = isis
End_Group
End_Object
Object = Label
Bytes = 65536
End_Object
Object = Table
Name = InstrumentPointing
StartByte = 32628064
Bytes = 1088
Records = 17
ByteOrder = Lsb
TimeDependentFrames = (-131000, 1)
ConstantFrames = (-131350, -131320, -131000)
ConstantRotation = (0.96621809368586, -9.13008670889038e-04,
-0.25772419725208, 7.985363329953e-04,
0.99999953055997, -5.4883472482896e-04,
0.25772457735688, 3.24491906175013e-04,
0.96621836917501)
CkTableStartTime = 269597800.33372
CkTableEndTime = 269597830.59744
CkTableOriginalSize = 4657
FrameTypeCode = 3
Description = "Created by spiceinit"
Kernels = ($kaguya/kernels/ck/SEL_M_ALL_D_V02.BC,
$kaguya/kernels/fk/SEL_V01.TF)
Group = Field
Name = J2000Q0
Type = Double
Size = 1
End_Group
Group = Field
Name = J2000Q1
Type = Double
Size = 1
End_Group
Group = Field
Name = J2000Q2
Type = Double
Size = 1
End_Group
Group = Field
Name = J2000Q3
Type = Double
Size = 1
End_Group
Group = Field
Name = AV1
Type = Double
Size = 1
End_Group
Group = Field
Name = AV2
Type = Double
Size = 1
End_Group
Group = Field
Name = AV3
Type = Double
Size = 1
End_Group
Group = Field
Name = ET
Type = Double
Size = 1
End_Group
End_Object
Object = Table
Name = InstrumentPosition
StartByte = 32629152
Bytes = 168
Records = 3
ByteOrder = Lsb
CacheType = HermiteSpline
SpkTableStartTime = 269597800.33372
SpkTableEndTime = 269597830.59744
SpkTableOriginalSize = 4657.0
Description = "Created by spiceinit"
Kernels = $kaguya/kernels/spk/SEL_M_071020_090610_SGMH_02.-
BSP
Group = Field
Name = J2000X
Type = Double
Size = 1
End_Group
Group = Field
Name = J2000Y
Type = Double
Size = 1
End_Group
Group = Field
Name = J2000Z
Type = Double
Size = 1
End_Group
Group = Field
Name = J2000XV
Type = Double
Size = 1
End_Group
Group = Field
Name = J2000YV
Type = Double
Size = 1
End_Group
Group = Field
Name = J2000ZV
Type = Double
Size = 1
End_Group
Group = Field
Name = ET
Type = Double
Size = 1
End_Group
End_Object
Object = Table
Name = BodyRotation
StartByte = 32629320
Bytes = 128
Records = 2
ByteOrder = Lsb
TimeDependentFrames = (31006, 1)
ConstantFrames = (31001, 31007, 31006)
ConstantRotation = (0.99999987325471, -3.29285422375571e-04,
3.80869618671387e-04, 3.29286000210947e-04,
0.99999994578431, -1.45444093783627e-06,
-3.80869119096078e-04, 1.57985578682691e-06,
0.99999992746811)
CkTableStartTime = 269597800.33372
CkTableEndTime = 269597830.59744
CkTableOriginalSize = 2
FrameTypeCode = 6
Description = "Created by spiceinit"
Kernels = ($kaguya/kernels/tspk/moon_pa_de421_1900-2050.bpc,
$kaguya/kernels/tspk/de421.bsp,
$base/kernels/pck/pck00009.tpc,
$kaguya/kernels/pck/moon_080317.tf,
$kaguya/kernels/pck/moon_assoc_me.tf)
SolarLongitude = 156.58130254847
Group = Field
Name = J2000Q0
Type = Double
Size = 1
End_Group
Group = Field
Name = J2000Q1
Type = Double
Size = 1
End_Group
Group = Field
Name = J2000Q2
Type = Double
Size = 1
End_Group
Group = Field
Name = J2000Q3
Type = Double
Size = 1
End_Group
Group = Field
Name = AV1
Type = Double
Size = 1
End_Group
Group = Field
Name = AV2
Type = Double
Size = 1
End_Group
Group = Field
Name = AV3
Type = Double
Size = 1
End_Group
Group = Field
Name = ET
Type = Double
Size = 1
End_Group
End_Object
Object = Table
Name = SunPosition
StartByte = 32629448
Bytes = 112
Records = 2
ByteOrder = Lsb
CacheType = Linear
SpkTableStartTime = 269597800.33372
SpkTableEndTime = 269597830.59744
SpkTableOriginalSize = 2.0
Description = "Created by spiceinit"
Kernels = ($kaguya/kernels/tspk/moon_pa_de421_1900-2050.bp-
c, $kaguya/kernels/tspk/de421.bsp)
Group = Field
Name = J2000X
Type = Double
Size = 1
End_Group
Group = Field
Name = J2000Y
Type = Double
Size = 1
End_Group
Group = Field
Name = J2000Z
Type = Double
Size = 1
End_Group
Group = Field
Name = J2000XV
Type = Double
Size = 1
End_Group
Group = Field
Name = J2000YV
Type = Double
Size = 1
End_Group
Group = Field
Name = J2000ZV
Type = Double
Size = 1
End_Group
Group = Field
Name = ET
Type = Double
Size = 1
End_Group
End_Object
Object = History
Name = IsisCube
StartByte = 32629560
Bytes = 1506
End_Object
Object = OriginalLabel
Name = IsisCube
StartByte = 32620890
Bytes = 7174
End_Object
Object = NaifKeywords
BODY_CODE = 301
BODY301_RADII = (1737.4, 1737.4, 1737.4)
BODY_FRAME_CODE = 31001
INS-131351_SWAP_OBSERVER_TARGET = TRUE
INS-131351_LIGHTTIME_CORRECTION = NONE
INS-131351_LT_SURFACE_CORRECT = FALSE
INS-131351_FOCAL_LENGTH = 72.45
INS-131351_PIXEL_PITCH = 0.007
CLOCK_ET_-131_900360927.270135_COMPUTED = 736e5568bc11b041
INS-131351_TRANSX = (0.0, 0.0, -0.007)
INS-131351_TRANSY = (0.0, -0.007, 0.0)
INS-131351_ITRANSS = (0.0, 0.0, -142.857142857)
INS-131351_ITRANSL = (0.0, -142.857142857, 0.0)
INS-131351_BORESIGHT_SAMPLE = 2048.0
INS-131351_BORESIGHT_LINE = 0.5
INS-131351_DISTORTION_COEF_X = (-9.6499e-04, 9.8441e-04,
8.5773e-06, -3.7438e-06)
INS-131351_DISTORTION_COEF_Y = (-0.0013796, 1.3502e-05,
2.7251e-06, -6.1938e-06)
INS-131351_BORESIGHT = (-0.0725, 0.0214)
End_Object
End_Object
Object = OriginalLabel
PDS_VERSION_ID = PDS3
/* ** FILE FORMAT ** */
RECORD_TYPE = UNDEFINED
FILE_NAME = TC1S2B0_01_03448S320E0799.img
/* ** POINTERS TO START BYTE OFFSET OF OBJECTS IN FILE ** */
^IMAGE = (TC1S2B0_01_03448S320E0799.img,
1 )
/* ** BASIC INFORMATION ** */
MISSION_NAME = SELENE
DATA_SET_ID = SLN-L-TC-3-S-LEVEL2B0-V1.0
DATA_SET_NAME = "SELENE MOON TC 3 MONO LEVEL2B0 V1.0"
L2DB_ORIGINAL_ID = TC_s_Level2B0
PRODUCT_ID = TC1S2B0_01_03448S320E0799
INSTRUMENT_TYPE = IMAGER
INSTRUMENT_ID = TC1
INSTRUMENT_NAME = "TERRAIN CAMERA 1"
INSTRUMENT_HOST_NAME = "SELENE MAIN ORBITER"
TARGET_TYPE = SATELLITE
TARGET_NAME = MOON
START_TIME = 2008-07-17T20:15:35.206200
STOP_TIME = 2008-07-17T20:16:05.463700
/* ** GENERAL DATA DESCRIPTION PARAMETERS ** */
SOFTWARE_NAME = RGC_TC_s_Level2B0
SOFTWARE_VERSION = 1.0.0
PROCESS_VERSION_ID = L2B
PRODUCT_CREATION_TIME = 2013-06-08T05:20:08
PROGRAM_START_TIME = 2013-06-08T05:13:02
PRODUCER_ID = LISM
PRODUCT_SET_ID = TC_s_Level2B0
PRODUCT_VERSION_ID = 01
REGISTERED_PRODUCT = Y
ILLUMINATION_CONDITION = EVENING
LEVEL2A_FILE_NAME = TC1S2A0_02DMN03448_002_0033.img
SPICE_METAKERNEL_FILE_NAME = RGC_INF_TCv401IK_MIv200IK_SPv105IK_RISE1-
00i_05_LongCK_D_V02_de421_110706.mk
/* ** SCENE RELATED PARAMETERS ** */
MISSION_PHASE_NAME = Nominal
REVOLUTION_NUMBER = 3448
STRIP_SEQUENCE_NUMBER = 2
SCENE_SEQUENCE_NUMBER = 33
UPPER_LEFT_DAYTIME_FLAG = Day
UPPER_RIGHT_DAYTIME_FLAG = Day
LOWER_LEFT_DAYTIME_FLAG = Day
LOWER_RIGHT_DAYTIME_FLAG = Day
OBSERVATION_MODE_ID = NORMAL
SENSOR_DESCRIPTION = "Imagery type:Pushbroom.
ImageryMode:Mono,Stereo.
ExposureTimeMode:Long,Middle,Short.
CompressionMode:NonComp,DCT. Q-table:32
patterns. H-table:4 patterns.
SwathMode:F(Full),N(Nominal),H(Half).
First pixel number:1(F),297(N),1172(H)."
SENSOR_DESCRIPTION2 = "Pixel size:7x7[micron^2](TC1/TC2).
Wavelength range:430-850[nm](TC1/TC2).
A/D rate:10[bit](TC1/TC2). Slant
angle:+/-15[degree] (from nadir to +x of
S/C)(TC1/TC2). Focal
length:72.45/72.63[mm](TC1/TC2). F
number:3.97/3.98(TC1/TC2)."
DETECTOR_STATUS = (TC1:ON, TC2:OFF, MV:OFF, MN:OFF, SP:ON)
EXPOSURE_MODE_ID = MIDDLE
LINE_EXPOSURE_DURATION = 3.250000
SPACECRAFT_CLOCK_START_COUNT = "900360927.2715 " SPACECRAFT_CLOCK_STOP_COUNT = "900360957.5290" CORRECTED_SC_CLOCK_START_COUNT = 900360927.270135CORRECTED_SC_CLOCK_STOP_COUNT = 900360957.527360CORRECTED_START_TIME = 2008-07-17T20:15:35.204835 CORRECTED_STOP_TIME = 2008-07-17T20:16:05.462060 LINE_SAMPLING_INTERVAL = 6.500000
CORRECTED_SAMPLING_INTERVAL = 6.499941
UPPER_LEFT_LATITUDE = -32.789566
UPPER_LEFT_LONGITUDE = 80.631630
UPPER_RIGHT_LATITUDE = -32.776189
UPPER_RIGHT_LONGITUDE = 79.085159
LOWER_LEFT_LATITUDE = -31.266527
LOWER_LEFT_LONGITUDE = 80.634632
LOWER_RIGHT_LATITUDE = -31.254154
LOWER_RIGHT_LONGITUDE = 79.107535
LOCATION_FLAG = A
ROLL_CANT = NO
SCENE_CENTER_LATITUDE = -32.025538
SCENE_CENTER_LONGITUDE = 79.866101
INCIDENCE_ANGLE = 79.791
EMISSION_ANGLE = 14.859
PHASE_ANGLE = 81.838
SOLAR_AZIMUTH_ANGLE = 277.284
FOCAL_PLANE_TEMPERATURE = 17.48
TELESCOPE_TEMPERATURE = 17.22
SATELLITE_MOVING_DIRECTION = +1
FIRST_SAMPLED_LINE_POSITION = UPPERMOST
FIRST_DETECTOR_ELEM_POSITION = LEFT
A_AXIS_RADIUS = 1737.400
B_AXIS_RADIUS = 1737.400
C_AXIS_RADIUS = 1737.400
DEFECT_PIXEL_POSITION = N/A
/* ** CAMERA RELATED PARAMETERS ** */
SWATH_MODE_ID = NOMINAL
FIRST_PIXEL_NUMBER = 297
LAST_PIXEL_NUMBER = 3788
SPACECRAFT_ALTITUDE = 113.081
SPACECRAFT_GROUND_SPEED = 1.523
TC1_TELESCOPE_TEMPERATURE = 17.33
TC2_TELESCOPE_TEMPERATURE = 16.99
DPU_TEMPERATURE = 11.35
TM_TEMPERATURE = 16.30
TM_RADIATOR_TEMPERATURE = 11.67
Q_TABLE_ID = SF008S_A
HUFFMAN_TABLE_ID = DCTNML_A
DATA_COMPRESSION_PERCENT_MEAN = 17.6
DATA_COMPRESSION_PERCENT_MAX = 20.4
DATA_COMPRESSION_PERCENT_MIN = 15.6
/* ** DESCRIPTION OF OBJECTS CONTAINED IN THE FILE ** */
Object = IMAGE
COMPRESSION_TYPE = DCT_DECOMPRESSED
COMPRESSION_PERCENT = 14.7
NOMINAL_LINE_NUMBER = 4088
NOMINAL_OVERLAP_LINE_NUMBER = 568
OVERLAP_LINE_NUMBER = 568
LINES = 4656
LINE_SAMPLES = 3496
SAMPLE_TYPE = MSB_INTEGER
SAMPLE_BITS = 16
IMAGE_VALUE_TYPE = RADIANCE
UNIT = W/m**2/micron/sr
SCALING_FACTOR = 1.30000e-02
OFFSET = 0.00000e+00
MIN_FOR_STATISTICAL_EVALUATION = 0
MAX_FOR_STATISTICAL_EVALUATION = 32767
SCENE_MAXIMUM_DN = 3161
SCENE_MINIMUM_DN = 0
SCENE_AVERAGE_DN = 345.0
SCENE_STDEV_DN = 266.9
SCENE_MODE_DN = 18
SHADOWED_AREA_MINIMUM = 0
SHADOWED_AREA_MAXIMUM = 0
SHADOWED_AREA_PERCENTAGE = 0
INVALID_TYPE = (SATURATION, MINUS, DUMMY_DEFECT,
OTHER)
INVALID_VALUE = (-20000, -21000, -22000, -23000)
INVALID_PIXELS = (0, 2, 0, 0)
End_Object
Object = PROCESSING_PARAMETERS
DARK_FILE_NAME = TC1_DRK_02952_04739_M_C_b05.csv
FLAT_FILE_NAME = TC1_FLT_00293_04739_N_C_b05.csv
EFFIC_FILE_NAME = TC1_EFF_PRFLT_N_N_v01.csv
NONLIN_FILE_NAME = TC1_NLT_PRFLT_N_N_v01.csv
RAD_CNV_COEF = 3.790009
L2A_DEAD_PIXEL_THRESHOLD = 30
L2A_SATURATION_THRESHOLD = 1023
DARK_VALID_MINIMUM = -5
RADIANCE_SATURATION_THRESHOLD = 425.971000
End_Object
End_Object
Object = Statistics
MeanValue = 4.4850017705493
StandardDeviation = 3.470610515188
MinimumValue = -273.0
MaximumValue = 41.093
PercentHIS = 0.0
PercentHRS = 0.0
PercentLIS = 0.0
PercentLRS = 0.0
PercentNull = 0.0
TotalPixels = 16277376.0
End_Object
Object = Geometry
BandsUsed = 1
ReferenceBand = 1
OriginalBand = 1
Target = MOON
StartTime = 2008-07-17T20:15:35.1500815
EndTime = 2008-07-17T20:16:05.4138068
CenterLine = 2328.0
CenterSample = 1748.0
CenterLatitude = -32.029549234266
CenterLongitude = 79.870272020315
CenterRadius = 1736712.5376081
RightAscension = 349.02345687877
Declination = 46.096711215966
UpperLeftLongitude = 80.643259700944
UpperLeftLatitude = -32.788902616188
LowerLeftLongitude = 80.644802406807
LowerLeftLatitude = -31.267405030743
LowerRightLongitude = 79.109187973418
LowerRightLatitude = -31.262355856091
UpperRightLongitude = 79.088461118662
UpperRightLatitude = -32.786412418797
PhaseAngle = 81.765924928992
EmissionAngle = 14.733877019508
IncidenceAngle = 79.794593365301
NorthAzimuth = 89.342277203456
OffNadir = 13.80783306372
SolarLongitude = 156.57991225668
LocalTime = 17.166849212264
TargetCenterDistance = 1850.6924455296
SlantDistance = 117.60534009361
SampleResolution = 11.362834791653
LineResolution = 11.362834791653
PixelResolution = 11.362834791653
MeanGroundResolution = 11.475306207817
SubSolarAzimuth = 7.8194246341667
SubSolarGroundAzimuth = 277.28214288415
SubSolarLatitude = 0.67533584007578
SubSolarLongitude = 2.3675338363511
SubSpacecraftAzimuth = 270.06602477645
SubSpacecraftGroundAzimuth = 180.82854483258
SubSpacecraftLatitude = -32.955495369011
SubSpacecraftLongitude = 79.854313939634
ParallaxX = 0.26294965050378
ParallaxY = -0.0038027366701225
ShadowX = -0.70409602118271
ShadowY = -5.5099540668607
HasLongitudeBoundary = FALSE
HasNorthPole = FALSE
HasSouthPole = FALSE
ObliqueSampleResolution = 11.749176556564
ObliqueLineResolution = 11.749176556564
ObliquePixelResolution = 11.749176556564
ObliqueDetectorResolution = 11.749176556564
End_Object
Object = Polygon
CentroidLine = 2337.9009837535
CentroidSample = 1745.8680213956
CentroidLatitude = -32.026364452424
CentroidLongitude = 79.871264024716
CentroidRadius = 1736718.5941665
SurfaceArea = 1833.2272708465
GlobalCoverage = 0.004837
SampleIncrement = 350
LineIncrement = 466
GisFootprint = "MULTIPOLYGON (((80.6434876663541473
-32.7890226016897728, 80.4867149622814537
-32.7889790178580185, 80.3300818155634602
-32.7889241901795998, 80.1743499766139109
-32.7863924359174561, 80.0177113335634829
-32.7850985578128089, 79.8609096144315771
-32.7848234399050114, 79.7046308149245135
-32.7856481738699159, 79.5493563354836795
-32.7870226859914453, 79.3958767772271159
-32.7899330186778215, 79.2408702054832617
-32.7880206664435292, 79.0882347398693355
-32.7865258350765103, 79.0884663323392374
-32.6327625597091711, 79.0889927321426143
-32.4792344194404308, 79.0928195529679527
-32.3287999953625871, 79.0984765240582703
-32.1793966642782578, 79.1007396266613370
-32.0251917303287073, 79.0999637067579329
-31.8674461676154479, 79.1000653863259657
-31.7118329729199147, 79.1036595396319200
-31.5618330875657200, 79.1080300073396927
-31.4135071179673488, 79.1089655294199048
-31.2622233587428546, 79.2640915501579002
-31.2664668168857993, 79.4173506391043844
-31.2689408031720930, 79.5699828473166093
-31.2701481282308009, 79.7214985199506998
-31.2628554037968804, 79.8757661395609517
-31.2647752169161173, 80.0298944873273825
-31.2661989417618464, 80.1835397744880396
-31.2683823818172222, 80.3371488315513034
-31.2694860909033281, 80.4921107196288688
-31.2680841915774828, 80.6450270328969481
-31.2672789832655802, 80.6466247230461448
-31.4182090005113928, 80.6477766393020659
-31.5703328473075899, 80.6460430612381600
-31.7257264129554599, 80.6473981726540075
-31.8763274616077510, 80.6461211118626693
-32.0288063924445083, 80.6444702720300910
-32.1809419224140285, 80.6412301860177934
-32.3351498799972461, 80.6419329580510151
-32.4858593622135245, 80.6426892951403858
-32.6378194898311520, 80.6434876663541473
-32.7890226016897728)))"
Group = Mapping
TargetName = MOON
EquatorialRadius = 1737400.0
PolarRadius = 1737400.0
LatitudeType = Planetocentric
LongitudeDirection = PositiveEast
LongitudeDomain = 360
MinimumLatitude = -32.790632362852
MaximumLatitude = -31.262183375965
MinimumLongitude = 79.087451383936
MaximumLongitude = 80.64832541182
PixelResolution = 11.329319211842
ProjectionName = Sinusoidal
CenterLongitude = 79.870272020315
End_Group
End_Object
End_Object
End
```