diff --git a/ale/base/type_sensor.py b/ale/base/type_sensor.py index 433c078169e791708398731b93918198a880d5e7..2151a2c1b5b8eb1e93ff6805d962d3a586146d07 100644 --- a/ale/base/type_sensor.py +++ b/ale/base/type_sensor.py @@ -313,3 +313,50 @@ class Radar(): left or right """ raise NotImplementedError + + +class RollingShutter(): + """ + Mix-in for sensors with a rolling shutter. + Specifically those with rolling shutter jitter. + """ + + @property + def sample_jitter_coeffs(self): + """ + Polynomial coefficients for the sample jitter. + The highest order coefficient comes first. + There is no constant coefficient, assumed 0. + + Returns + ------- + : array + """ + raise NotImplementedError + + @property + def line_jitter_coeffs(self): + """ + Polynomial coefficients for the line jitter. + The highest order coefficient comes first. + There is no constant coefficient, assumed 0. + + Returns + ------- + : array + """ + raise NotImplementedError + + @property + def line_times(self): + """ + Line exposure times for the image. + Generally this will be normalized to [-1, 1] so that the jitter coefficients + are well conditioned, but it is not necessarily required as long as the + jitter coefficients are consistent. + + Returns + ------- + : array + """ + raise NotImplementedError diff --git a/ale/drivers/clipper_drivers.py b/ale/drivers/clipper_drivers.py new file mode 100644 index 0000000000000000000000000000000000000000..4689b50f0b0a654ebbab95f06bb21175c152034c --- /dev/null +++ b/ale/drivers/clipper_drivers.py @@ -0,0 +1,673 @@ +from ale.base import Driver +from ale.base.data_naif import NaifSpice +from ale.base.data_isis import read_table_data, parse_table +from ale.base.label_isis import IsisLabel +from ale.base.type_sensor import LineScanner, Framer, RollingShutter +from ale.base.type_distortion import NoDistortion + +############################## HARD CODED VALUES ############################### +# These values are hard coded from the SIS. As the kernels mature, they will +# eventually be available in the IK. + +EIS_FOCAL_LENGTHS = { + "EUROPAM_EIS_WAC" : 46.25, + "EUROPAM_EIS_NAC" : 1002.7 +} + +# According to diagrams in the SIS, increasing lines are +Y and increasing samples are -X +# Focal to detector transforms assume 0.014 mm pixel pitch. +EIS_ITRANSL = [0.0, 0.0, 1.0 / 0.014] +EIS_ITRANSS = [0.0, -1.0 / 0.014, 0.0] + +EIS_NAC_FILTER_CODES = { + "CLEAR" : -159121, + "NUV" : -159125, + "BLU" : -159126, + "GRN" : -159127, + "RED" : -159128, + "IR1" : -159129, + "1MU" : -159130 +} + +EIS_WAC_FILTER_CODES = { + "CLEAR" : -159141, + "NUV" : -159145, + "BLU" : -159146, + "GRN" : -159147, + "RED" : -159148, + "IR1" : -159149, + "1MU" : -159150 +} + +# The CMOS can read any line in each region, so for now just take the top line +# These values differ from the SIS because the SIS takes the top left corner as +# (4095, 2047) and we take it as (0, 0). So, these values are 2047 - the value +# in the SIS +EIS_FILTER_START_LINES = { + "CLEAR" : 580, + "NUV" : 415, + "BLU" : 351, + "GRN" : 287, + "RED" : 223, + "IR1" : 159, + "1MU" : 95 +} + +# These values differ from the SIS because the SIS takes the top left corner as +# (4095, 2047) and we take it as (0, 0). So, these values are 4095 - the value +# in the SIS +EIS_FILTER_START_SAMPLES = { + "CLEAR" : 132, + "NUV" : 32, + "BLU" : 32, + "GRN" : 32, + "RED" : 32, + "IR1" : 32, + "1MU" : 32 +} + +class ClipperEISWACFCIsisLabelNaifSpiceDriver(Framer, IsisLabel, NaifSpice, NoDistortion, Driver): + @property + def instrument_id(self): + """ + The short text name for the instrument + + Returns an instrument id uniquely identifying the instrument. Used to acquire + instrument codes from Spice Lib bods2c routine. + + Returns + ------- + str + The short text name for the instrument + """ + id_lookup = { + "EIS WAC FC": "EUROPAM_EIS_WAC" + } + + return id_lookup[super().instrument_id] + + @property + def fikid(self): + """ + The NAIF ID for the filter. + + Returns + ------- + : int + The NAIF ID for the filter + """ + return EIS_WAC_FILTER_CODES[self.filter_name] + + @property + def filter_name(self): + """ + The name of the filter used to capture the image + + Returns + ------- + : string + The name of the filter + """ + return self.label['IsisCube']['BandBin']['FilterName'] + + @property + def detector_center_sample(self): + """ + The center sample of the detector in zero based detector pixels + This isn't in the IK so hardcode it to the absolute center + + Returns + ------- + float : + The center sample of the detector + """ + return 4096 / 2 + + @property + def detector_center_line(self): + """ + The center line of the detector in zero based detector pixels + This isn't in the IK so hardcode it to the absolute center + + Returns + ------- + float : + The center line of the detector + """ + return 2048 / 2 + + @property + def detector_start_line(self): + """ + The first zero based line of the detector read out + + Returns + ------- + : int + Zero based Detector line corresponding to the first image line + """ + return EIS_FILTER_START_LINES[self.filter_name] + + @property + def detector_start_sample(self): + """ + The first zero based sample of the detector read out + + Returns + ------- + : int + Zero based Detector sample corresponding to the first image sample + """ + return EIS_FILTER_START_SAMPLES[self.filter_name] + + @property + def focal_length(self): + """ + The focal length in millimeters + + Returns + ------- + : float + focal length + """ + return EIS_FOCAL_LENGTHS[self.instrument_id] + + @property + def focal2pixel_lines(self): + """ + The transformation from focal plan coordinates to detector lines. + To transform the coordinate (x,y) to detector lines do the following: + + lines = focal2pixel_lines[0] + x * focal2pixel_lines[1] + y * focal2pixel_lines[2] + + Returns + ------- + : list<double> + focal plane to detector lines transform + """ + return EIS_ITRANSL + + @property + def focal2pixel_samples(self): + """ + The transformation from focal plan coordinates to detector samples. + To transform the coordinate (x,y) to detector samples do the following: + + samples = focal2pixel_samples[0] + x * focal2pixel_samples[1] + y * focal2pixel_samples[2] + + Returns + ------- + : list<double> + focal plane to detector samples transform + """ + return EIS_ITRANSS + + +class ClipperEISWACPBIsisLabelNaifSpiceDriver(LineScanner, IsisLabel, NaifSpice, NoDistortion, Driver): + @property + def instrument_id(self): + """ + The short text name for the instrument + + Returns an instrument id uniquely identifying the instrument. Used to acquire + instrument codes from Spice Lib bods2c routine. + + Returns + ------- + str + The short text name for the instrument + """ + id_lookup = { + "EIS WAC PB": "EUROPAM_EIS_WAC" + } + + return id_lookup[super().instrument_id] + + @property + def fikid(self): + """ + The NAIF ID for the filter. + + Returns + ------- + : int + The NAIF ID for the filter + """ + return EIS_WAC_FILTER_CODES[self.filter_name] + + @property + def filter_name(self): + """ + The name of the filter used to capture the image + + Returns + ------- + : string + The name of the filter + """ + return self.label['IsisCube']['BandBin']['FilterName'] + + @property + def detector_center_sample(self): + """ + The center sample of the detector in zero based detector pixels + This isn't in the IK so hardcode it to the absolute center + + Returns + ------- + float : + The center sample of the detector + """ + return 4096 / 2 + + @property + def detector_center_line(self): + """ + The center line of the detector in zero based detector pixels + This isn't in the IK so hardcode it to the absolute center + + Returns + ------- + float : + The center line of the detector + """ + return 2048 / 2 + + @property + def detector_start_line(self): + """ + The first zero based line of the detector read out + + Returns + ------- + : int + Zero based Detector line corresponding to the first image line + """ + return EIS_FILTER_START_LINES[self.filter_name] + + @property + def detector_start_sample(self): + """ + The first zero based sample of the detector read out + + Returns + ------- + : int + Zero based Detector sample corresponding to the first image sample + """ + return EIS_FILTER_START_SAMPLES[self.filter_name] + + @property + def focal_length(self): + """ + The focal length in millimeters + + Returns + ------- + : float + focal length + """ + return EIS_FOCAL_LENGTHS[self.instrument_id] + + @property + def focal2pixel_lines(self): + """ + The transformation from focal plan coordinates to detector lines. + To transform the coordinate (x,y) to detector lines do the following: + + lines = focal2pixel_lines[0] + x * focal2pixel_lines[1] + y * focal2pixel_lines[2] + + Returns + ------- + : list<double> + focal plane to detector lines transform + """ + return EIS_ITRANSL + + @property + def focal2pixel_samples(self): + """ + The transformation from focal plan coordinates to detector samples. + To transform the coordinate (x,y) to detector samples do the following: + + samples = focal2pixel_samples[0] + x * focal2pixel_samples[1] + y * focal2pixel_samples[2] + + Returns + ------- + : list<double> + focal plane to detector samples transform + """ + return EIS_ITRANSS + + +class ClipperEISNACFCIsisLabelNaifSpiceDriver(Framer, IsisLabel, NaifSpice, NoDistortion, RollingShutter, Driver): + @property + def instrument_id(self): + """ + The short text name for the instrument + + Returns an instrument id uniquely identifying the instrument. Used to acquire + instrument codes from Spice Lib bods2c routine. + + Returns + ------- + str + The short text name for the instrument + """ + id_lookup = { + "EIS NAC FC": "EUROPAM_EIS_NAC" + } + + return id_lookup[super().instrument_id] + + @property + def fikid(self): + """ + The NAIF ID for the filter. + + Returns + ------- + : int + The NAIF ID for the filter + """ + return EIS_NAC_FILTER_CODES[self.filter_name] + + @property + def filter_name(self): + """ + The name of the filter used to capture the image + + Returns + ------- + : string + The name of the filter + """ + return self.label['IsisCube']['BandBin']['FilterName'] + + @property + def detector_center_sample(self): + """ + The center sample of the detector in zero based detector pixels + This isn't in the IK so hardcode it to the absolute center + + Returns + ------- + float : + The center sample of the detector + """ + return 4096 / 2 + + @property + def detector_center_line(self): + """ + The center line of the detector in zero based detector pixels + This isn't in the IK so hardcode it to the absolute center + + Returns + ------- + float : + The center line of the detector + """ + return 2048 / 2 + + @property + def detector_start_line(self): + """ + The first zero based line of the detector read out + + Returns + ------- + : int + Zero based Detector line corresponding to the first image line + """ + return EIS_FILTER_START_LINES[self.filter_name] + + @property + def detector_start_sample(self): + """ + The first zero based sample of the detector read out + + Returns + ------- + : int + Zero based Detector sample corresponding to the first image sample + """ + return EIS_FILTER_START_SAMPLES[self.filter_name] + + @property + def focal_length(self): + """ + The focal length in millimeters + + Returns + ------- + : float + focal length + """ + return EIS_FOCAL_LENGTHS[self.instrument_id] + + @property + def focal2pixel_lines(self): + """ + The transformation from focal plan coordinates to detector lines. + To transform the coordinate (x,y) to detector lines do the following: + + lines = focal2pixel_lines[0] + x * focal2pixel_lines[1] + y * focal2pixel_lines[2] + + Returns + ------- + : list<double> + focal plane to detector lines transform + """ + return EIS_ITRANSL + + @property + def focal2pixel_samples(self): + """ + The transformation from focal plan coordinates to detector samples. + To transform the coordinate (x,y) to detector samples do the following: + + samples = focal2pixel_samples[0] + x * focal2pixel_samples[1] + y * focal2pixel_samples[2] + + Returns + ------- + : list<double> + focal plane to detector samples transform + """ + return EIS_ITRANSS + + @property + def sample_jitter_coeffs(self): + """ + Polynomial coefficients for the sample jitter. + The highest order coefficient comes first. + There is no constant coefficient, assumed 0. + + Returns + ------- + : array + """ + return self.label['IsisCube']['Instrument']['JitterSampleCoefficients'] + + @property + def line_jitter_coeffs(self): + """ + Polynomial coefficients for the line jitter. + The highest order coefficient comes first. + There is no constant coefficient, assumed 0. + + Returns + ------- + : array + """ + return self.label['IsisCube']['Instrument']['JitterLineCoefficients'] + + @property + def normalized_readout_times_table(self): + """ + The table of normalized readout times for the lines in the image. + + Returns + ------- + : dict + Normlized readout times and lines table + """ + if not hasattr(self, "_normalized_readout_times_table"): + for table in self.label.getlist('Table'): + if table['Name'] == 'Normalized Main Readout Line Times': + binary_data = read_table_data(table, self._file) + self._normalized_readout_times_table = parse_table(table, binary_data) + return self._normalized_readout_times_table + raise ValueError(f'Could not find Normalized Main Readout Line Times table in file {self._file}') + return self._normalized_readout_times_table + + @property + def line_times(self): + """ + Line exposure times for the image. + Generally this will be normalized to [-1, 1] so that the jitter coefficients + are well conditioned, but it is not necessarily required as long as the + jitter coefficients are consistent. + + Returns + ------- + : array + """ + return self.normalized_readout_times_table["time"] + + +class ClipperEISNACPBIsisLabelNaifSpiceDriver(LineScanner, IsisLabel, NaifSpice, NoDistortion, Driver): + @property + def instrument_id(self): + """ + The short text name for the instrument + + Returns an instrument id uniquely identifying the instrument. Used to acquire + instrument codes from Spice Lib bods2c routine. + + Returns + ------- + str + The short text name for the instrument + """ + id_lookup = { + "EIS NAC PB": "EUROPAM_EIS_NAC" + } + + return id_lookup[super().instrument_id] + + @property + def fikid(self): + """ + The NAIF ID for the filter. + + Returns + ------- + : int + The NAIF ID for the filter + """ + return EIS_NAC_FILTER_CODES[self.filter_name] + + @property + def filter_name(self): + """ + The name of the filter used to capture the image + + Returns + ------- + : string + The name of the filter + """ + return self.label['IsisCube']['BandBin']['FilterName'] + + @property + def detector_center_sample(self): + """ + The center sample of the detector in zero based detector pixels + This isn't in the IK so hardcode it to the absolute center + + Returns + ------- + float : + The center sample of the detector + """ + return 4096 / 2 + + @property + def detector_center_line(self): + """ + The center line of the detector in zero based detector pixels + This isn't in the IK so hardcode it to the absolute center + + Returns + ------- + float : + The center line of the detector + """ + return 2048 / 2 + + @property + def detector_start_line(self): + """ + The first zero based line of the detector read out + + Returns + ------- + : int + Zero based Detector line corresponding to the first image line + """ + return EIS_FILTER_START_LINES[self.filter_name] + + @property + def detector_start_sample(self): + """ + The first zero based sample of the detector read out + + Returns + ------- + : int + Zero based Detector sample corresponding to the first image sample + """ + return EIS_FILTER_START_SAMPLES[self.filter_name] + + @property + def focal_length(self): + """ + The focal length in millimeters + + Returns + ------- + : float + focal length + """ + return EIS_FOCAL_LENGTHS[self.instrument_id] + + @property + def focal2pixel_lines(self): + """ + The transformation from focal plan coordinates to detector lines. + To transform the coordinate (x,y) to detector lines do the following: + + lines = focal2pixel_lines[0] + x * focal2pixel_lines[1] + y * focal2pixel_lines[2] + + Returns + ------- + : list<double> + focal plane to detector lines transform + """ + return EIS_ITRANSL + + @property + def focal2pixel_samples(self): + """ + The transformation from focal plan coordinates to detector samples. + To transform the coordinate (x,y) to detector samples do the following: + + samples = focal2pixel_samples[0] + x * focal2pixel_samples[1] + y * focal2pixel_samples[2] + + Returns + ------- + : list<double> + focal plane to detector samples transform + """ + return EIS_ITRANSS \ No newline at end of file diff --git a/ale/drivers/mess_drivers.py b/ale/drivers/mess_drivers.py index b514711b2c18d26ffc803c00e581095dff5a125d..e537351c3da643a71373203bfa07dd2e5f9062d4 100644 --- a/ale/drivers/mess_drivers.py +++ b/ale/drivers/mess_drivers.py @@ -15,7 +15,7 @@ from ale.base.data_isis import IsisSpice ID_LOOKUP = { 'MDIS-WAC': 'MSGR_MDIS_WAC', - 'MDIS-NAC':'MSGR_MDIS_NAC', + 'MDIS-NAC': 'MSGR_MDIS_NAC', } diff --git a/tests/pytests/data/eis_nac_fc/eis_nac_fc_isis3.lbl b/tests/pytests/data/eis_nac_fc/eis_nac_fc_isis3.lbl new file mode 100644 index 0000000000000000000000000000000000000000..ec4db42bcb25ecd156257f0c2486ad59a34fd6e1 --- /dev/null +++ b/tests/pytests/data/eis_nac_fc/eis_nac_fc_isis3.lbl @@ -0,0 +1,79 @@ +Object = IsisCube + Object = Core + StartByte = 65537 + Format = Tile + TileSamples = 445 + TileLines = 958 + + Group = Dimensions + Samples = 1335 + Lines = 3832 + Bands = 1 + End_Group + + Group = Pixels + Type = SignedWord + ByteOrder = Lsb + Base = 0.0 + Multiplier = 1.0 + End_Group + End_Object + + Group = Instrument + SpacecraftName = "Europa Clipper" + InstrumentId = "EIS NAC FC" + TargetName = Didymos + StartTime = 2021-03-06T04:05:27.77 + ExposureDuration = 1.0 <seconds> + JitterSampleCoefficients = (0.1, 0.2, 0.3) + JitterLineCoefficients = (0.01, 0.02, 0.03) + End_Group + + Group = BandBin + FilterName = CLEAR + Center = 702.5 <nm> + Width = 695 <nm> + End_Group + + Group = Kernels + NaifFrameCode = -159103 + End_Group +End_Object + +Object = Label + Bytes = 65536 +End_Object + +Object = Table + Name = "Normalized Main Readout Line Times" + StartByte = 10353894 + Bytes = 657 + Records = 3832 + ByteOrder = Lsb + + Group = Field + Name = "line number" + Type = Integer + Size = 1 + End_Group + + Group = Field + Name = time + Type = Double + Size = 1 + End_Group +End_Object + +Object = History + Name = IsisCube + StartByte = 10296977 + Bytes = 657 +End_Object + +Object = OriginalXmlLabel + Name = IsisCube + StartByte = 10297634 + Bytes = 13238 + ByteOrder = Lsb +End_Object +End \ No newline at end of file diff --git a/tests/pytests/data/eis_nac_pb/eis_nac_pb_isis3.lbl b/tests/pytests/data/eis_nac_pb/eis_nac_pb_isis3.lbl new file mode 100644 index 0000000000000000000000000000000000000000..8b1a0c2e5aa0f6e404be7a9097b6f73e7eef509f --- /dev/null +++ b/tests/pytests/data/eis_nac_pb/eis_nac_pb_isis3.lbl @@ -0,0 +1,57 @@ +Object = IsisCube + Object = Core + StartByte = 65537 + Format = Tile + TileSamples = 445 + TileLines = 958 + + Group = Dimensions + Samples = 1335 + Lines = 4096 + Bands = 1 + End_Group + + Group = Pixels + Type = SignedWord + ByteOrder = Lsb + Base = 0.0 + Multiplier = 1.0 + End_Group + End_Object + + Group = Instrument + SpacecraftName = "Europa Clipper" + InstrumentId = "EIS NAC PB" + TargetName = Didymos + StartTime = 2021-03-06T04:05:27.77 + ExposureDuration = 1.0 <seconds> + End_Group + + Group = BandBin + FilterName = NUV + Center = 377.5 <nm> + Width = 45 <nm> + End_Group + + Group = Kernels + NaifFrameCode = -159103 + End_Group +End_Object + +Object = Label + Bytes = 65536 +End_Object + +Object = History + Name = IsisCube + StartByte = 10296977 + Bytes = 659 +End_Object + +Object = OriginalXmlLabel + Name = IsisCube + StartByte = 10297636 + Bytes = 13244 + ByteOrder = Lsb +End_Object +End \ No newline at end of file diff --git a/tests/pytests/data/eis_wac_fc/eis_wac_fc_isis3.lbl b/tests/pytests/data/eis_wac_fc/eis_wac_fc_isis3.lbl new file mode 100644 index 0000000000000000000000000000000000000000..d1ac57c24f936ebbe90e71c6da212ed6670fe848 --- /dev/null +++ b/tests/pytests/data/eis_wac_fc/eis_wac_fc_isis3.lbl @@ -0,0 +1,57 @@ +Object = IsisCube + Object = Core + StartByte = 65537 + Format = Tile + TileSamples = 445 + TileLines = 958 + + Group = Dimensions + Samples = 1335 + Lines = 3832 + Bands = 1 + End_Group + + Group = Pixels + Type = SignedWord + ByteOrder = Lsb + Base = 0.0 + Multiplier = 1.0 + End_Group + End_Object + + Group = Instrument + SpacecraftName = "Europa Clipper" + InstrumentId = "EIS WAC FC" + TargetName = Didymos + StartTime = 2021-03-06T04:05:27.77 + ExposureDuration = 1.0 <seconds> + End_Group + + Group = BandBin + FilterName = CLEAR + Center = 712.5 <nm> + Width = 675 <nm> + End_Group + + Group = Kernels + NaifFrameCode = -159104 + End_Group +End_Object + +Object = Label + Bytes = 65536 +End_Object + +Object = History + Name = IsisCube + StartByte = 10296977 + Bytes = 654 +End_Object + +Object = OriginalXmlLabel + Name = IsisCube + StartByte = 10297631 + Bytes = 13164 + ByteOrder = Lsb +End_Object +End \ No newline at end of file diff --git a/tests/pytests/data/eis_wac_pb/eis_wac_pb_isis3.lbl b/tests/pytests/data/eis_wac_pb/eis_wac_pb_isis3.lbl new file mode 100644 index 0000000000000000000000000000000000000000..ac0cbc9b4b2f938077ef30f099851f88273ed509 --- /dev/null +++ b/tests/pytests/data/eis_wac_pb/eis_wac_pb_isis3.lbl @@ -0,0 +1,57 @@ +Object = IsisCube + Object = Core + StartByte = 65537 + Format = Tile + TileSamples = 1024 + TileLines = 1024 + + Group = Dimensions + Samples = 1335 + Lines = 4096 + Bands = 1 + End_Group + + Group = Pixels + Type = SignedWord + ByteOrder = Lsb + Base = 0.0 + Multiplier = 1.0 + End_Group + End_Object + + Group = Instrument + SpacecraftName = "Europa Clipper" + InstrumentId = "EIS WAC PB" + TargetName = Didymos + StartTime = 2021-03-06T04:05:27.77 + ExposureDuration = 1.0 <seconds> + End_Group + + Group = BandBin + FilterName = BLU + Center = 427.5 <nm> + Width = 95 <nm> + End_Group + + Group = Kernels + NaifFrameCode = -159104 + End_Group +End_Object + +Object = Label + Bytes = 65536 +End_Object + +Object = History + Name = IsisCube + StartByte = 33619969 + Bytes = 583 +End_Object + +Object = OriginalXmlLabel + Name = IsisCube + StartByte = 33620552 + Bytes = 11704 + ByteOrder = Lsb +End_Object +End \ No newline at end of file diff --git a/tests/pytests/test_clipper_drivers.py b/tests/pytests/test_clipper_drivers.py new file mode 100644 index 0000000000000000000000000000000000000000..16cfd8a4dfd728952bdf257d75f7a970e5df168f --- /dev/null +++ b/tests/pytests/test_clipper_drivers.py @@ -0,0 +1,182 @@ +import pytest +import ale +import struct +import numpy as np +import unittest +from unittest.mock import patch + +from conftest import get_image, get_image_label + +from ale.drivers.clipper_drivers import ClipperEISWACFCIsisLabelNaifSpiceDriver, ClipperEISWACPBIsisLabelNaifSpiceDriver, ClipperEISNACFCIsisLabelNaifSpiceDriver, ClipperEISNACPBIsisLabelNaifSpiceDriver + + +# ========= Test EIS WAC FC isislabel and naifspice driver ========= +class test_EIS_WAC_FC_isis_naif(unittest.TestCase): + + def setUp(self): + label = get_image_label("eis_wac_fc", "isis3") + self.driver = ClipperEISWACFCIsisLabelNaifSpiceDriver(label) + + def test_instrument_id(self): + assert self.driver.instrument_id == "EUROPAM_EIS_WAC" + + def test_fikid(self): + assert self.driver.fikid == -159141 + + def test_filter_name(self): + assert self.driver.filter_name == "CLEAR" + + def test_detector_center_sample(self): + assert self.driver.detector_center_sample == 2048 + + def test_detector_center_line(self): + assert self.driver.detector_center_line == 1024 + + def test_detector_start_line(self): + assert self.driver.detector_start_line == 580 + + def test_detector_start_sample(self): + assert self.driver.detector_start_sample == 132 + + def test_focal_length(self): + assert self.driver.focal_length == 46.25 + + def test_focal2pixel_lines(self): + np.testing.assert_array_equal(self.driver.focal2pixel_lines, [0.0, 0.0, 1.0 / 0.014]) + + def test_focal2pixel_samples(self): + np.testing.assert_array_equal(self.driver.focal2pixel_samples, [0.0, -1.0 / 0.014, 0.0]) + + +# ========= Test EIS WAC PB isislabel and naifspice driver ========= +class test_EIS_WAC_PB_isis_naif(unittest.TestCase): + + def setUp(self): + label = get_image_label("eis_wac_pb", "isis3") + self.driver = ClipperEISWACPBIsisLabelNaifSpiceDriver(label) + + def test_instrument_id(self): + assert self.driver.instrument_id == "EUROPAM_EIS_WAC" + + def test_fikid(self): + assert self.driver.fikid == -159146 + + def test_filter_name(self): + assert self.driver.filter_name == "BLU" + + def test_detector_center_sample(self): + assert self.driver.detector_center_sample == 2048 + + def test_detector_center_line(self): + assert self.driver.detector_center_line == 1024 + + def test_detector_start_line(self): + assert self.driver.detector_start_line == 351 + + def test_detector_start_sample(self): + assert self.driver.detector_start_sample == 32 + + def test_focal_length(self): + assert self.driver.focal_length == 46.25 + + def test_focal2pixel_lines(self): + np.testing.assert_array_equal(self.driver.focal2pixel_lines, [0.0, 0.0, 1.0 / 0.014]) + + def test_focal2pixel_samples(self): + np.testing.assert_array_equal(self.driver.focal2pixel_samples, [0.0, -1.0 / 0.014, 0.0]) + + +# ========= Test EIS NAC FC isislabel and naifspice driver ========= +class test_EIS_NAC_FC_isis_naif(unittest.TestCase): + + def setUp(self): + label = get_image_label("eis_nac_fc", "isis3") + self.driver = ClipperEISNACFCIsisLabelNaifSpiceDriver(label) + self._file = "dummy" + + def test_instrument_id(self): + assert self.driver.instrument_id == "EUROPAM_EIS_NAC" + + def test_fikid(self): + assert self.driver.fikid == -159121 + + def test_filter_name(self): + assert self.driver.filter_name == "CLEAR" + + def test_detector_center_sample(self): + assert self.driver.detector_center_sample == 2048 + + def test_detector_center_line(self): + assert self.driver.detector_center_line == 1024 + + def test_detector_start_line(self): + assert self.driver.detector_start_line == 580 + + def test_detector_start_sample(self): + assert self.driver.detector_start_sample == 132 + + def test_focal_length(self): + assert self.driver.focal_length == 1002.7 + + def test_sample_jitter_coeffs(self): + assert self.driver.sample_jitter_coeffs == [0.1, 0.2, 0.3] + + def test_line_jitter_coeffs(self): + assert self.driver.line_jitter_coeffs == [0.01, 0.02, 0.03] + + def test_line_times(self): + test_table_data = bytearray() + test_times = np.linspace(-1.0, 1.0, 3832, dtype=np.double) + test_lines = np.arange(3832, dtype=np.intc) + for line, time in zip(test_lines, test_times): + # These have to be packed separately otherwise struct will pad the int to 8 bytes + test_table_data.extend(struct.pack("i", line)) + test_table_data.extend(struct.pack("d", time)) + test_table_data = bytes(test_table_data) + with patch('ale.drivers.clipper_drivers.read_table_data', return_value=test_table_data) as table_mock: + np.testing.assert_array_equal(self.driver.line_times, test_times) + table_mock.assert_called() + + def test_focal2pixel_lines(self): + np.testing.assert_array_equal(self.driver.focal2pixel_lines, [0.0, 0.0, 1.0 / 0.014]) + + def test_focal2pixel_samples(self): + np.testing.assert_array_equal(self.driver.focal2pixel_samples, [0.0, -1.0 / 0.014, 0.0]) + + +# ========= Test EIS NAC PB isislabel and naifspice driver ========= +class test_EIS_NAC_PB_isis_naif(unittest.TestCase): + + def setUp(self): + label = get_image_label("eis_nac_pb", "isis3") + self.driver = ClipperEISNACPBIsisLabelNaifSpiceDriver(label) + + def test_instrument_id(self): + assert self.driver.instrument_id == "EUROPAM_EIS_NAC" + + def test_fikid(self): + assert self.driver.fikid == -159125 + + def test_filter_name(self): + assert self.driver.filter_name == "NUV" + + def test_detector_center_sample(self): + assert self.driver.detector_center_sample == 2048 + + def test_detector_center_line(self): + assert self.driver.detector_center_line == 1024 + + def test_detector_start_line(self): + assert self.driver.detector_start_line == 415 + + def test_detector_start_sample(self): + assert self.driver.detector_start_sample == 32 + + def test_focal_length(self): + assert self.driver.focal_length == 1002.7 + + def test_focal2pixel_lines(self): + np.testing.assert_array_equal(self.driver.focal2pixel_lines, [0.0, 0.0, 1.0 / 0.014]) + + def test_focal2pixel_samples(self): + np.testing.assert_array_equal(self.driver.focal2pixel_samples, [0.0, -1.0 / 0.014, 0.0])