Unverified Commit 64f8c6ac authored by Austin Sanders's avatar Austin Sanders Committed by GitHub
Browse files

Initial ApolloPanIsisLabelIsisSpiceDriver (#616)

* Initial ApolloPanIsisLabelIsisSpiceDriver

* Added apollopan tests

* Added data for apollopan tests

* Updated docstrings
parent 55ee6e40
Loading
Loading
Loading
Loading
+206 −1
Original line number Diff line number Diff line
@@ -3,9 +3,10 @@ import pvl

from ale.base import Driver
from ale.base.data_naif import NaifSpice
from ale.base.data_isis import IsisSpice, read_table_data, parse_table
from ale.base.label_isis import IsisLabel
from ale.base.type_distortion import NoDistortion
from ale.base.type_sensor import Framer
from ale.base.type_sensor import Framer, LineScanner

class ApolloMetricIsisLabelNaifSpiceDriver(Framer, IsisLabel, NaifSpice, NoDistortion, Driver):

@@ -136,3 +137,207 @@ class ApolloMetricIsisLabelNaifSpiceDriver(Framer, IsisLabel, NaifSpice, NoDisto
            The center of the CCD formatted as line, sample
        """
        return float(spice.gdpool('INS{}_BORESIGHT'.format(self.ikid), 0, 3)[1])


class ApolloPanIsisLabelIsisSpiceDriver(LineScanner, IsisLabel, IsisSpice, NoDistortion, Driver):

    @property
    def instrument_name(self):
        """
        The name of the instrument.

        Returns
        -------
        str
          The short text name for the instrument
        """
        id_lookup = {
            "APOLLO_PAN": "APOLLO PANORAMIC CAMERA"
        }

        return id_lookup[super().instrument_id]


    @property
    def sensor_model_version(self):
        """
        The ISIS Sensor model number for ApolloPanCamera in ISIS.
        
        Returns
        -------
        : int
          ISIS sensor model version
        """
        return 1


    @property
    def focal2pixel_lines(self):
        """
        The line component of the affine transformation
        from focal plane coordinates to centered ccd pixels.

        This information is not contained in the label, so it is
        hard-coded to match apollo kernels.

        Returns
        -------
        list :
            The coefficients of the affine transformation
            formatted as constant, x, y
        """
        return (0.0, 0.0, 200.0)

    @property
    def focal2pixel_samples(self):
        """
        The sample component of the affine transformation
        from focal plane coordinates to centered ccd pixels

        This information is not contained in the label, so it is
        hard-coded to match apollo kernels.

        Returns
        -------
        list :
            The coefficients of the affine transformation
            formatted as constant, x, y
        """
        return (0.0, 200.0, 0.0)

    @property
    def pixel2focal_x(self):
        """
        Returns detector to focal plane x.

        This information is not contained in the label, so it is
        hard-coded to match apollo kernels.

        Returns
        -------
        : list<double>
          detector to focal plane x
        """
        return (0.0, 0.005, 0.0)


    @property
    def pixel2focal_y(self):
        """
        Returns detector to focal plane y.

        This information is not contained in the label, so it is
        hard-coded to match apollo kernels.

        Returns
        -------
        : list<double>
        detector to focal plane y
        """
        return (0.0, 0.0, 0.0)


    @property
    def focal_length(self):
        """
        The focal length of the instrument
        Hard-coded to return the same value as Isis::ApolloPanoramicCamera.cpp

        Returns
        -------
        float :
            The focal length in millimeters
        """
        return 610.0


    @property
    def ephemeris_start_time(self):
        """
        The image start time in ephemeris time
        The only time information written to the label by apollopaninit is UTC time,
        so this pulls from tables.
        
        Returns
        -------
        float :
            The image start ephemeris time
        """
        isis_bytes = read_table_data(self.label['Table'], self._file)
        return parse_table(self.label['Table'], isis_bytes)['ET'][0]


    @property
    def target_body_radii(self):
        
        """
        The triaxial radii of the target body
        This information is not added to the label by apollopaninit, so it
        is pulled from kernels.
        
        Returns
        -------
        list :
            The body radii in kilometers. For most bodies,
            this is formatted as semimajor, semimajor,
            semiminor
        """
        return (1737.4, 1737.4, 1737.4)


    @property
    def detector_center_line(self):
        """
        The center line of the CCD in detector pixels
        This information is not recorded in the label by apollopaninit, so this is
        hard-coded to match the apollo kernels.

        Returns
        -------
        list :
            The center line of the CCD
        """
        if self.spacecraft_name == "APOLLO16":
            return 11503.5
        else:
            return  11450.5 


    @property
    def detector_center_sample(self):
        """
        The center sample of the CCD in detector pixels
        This information is not recorded in the label by apollopaninit, so this is
        hard-coded to match the apollo kernels.

        Returns
        -------
        list :
            The center sample of the CCD
        """
        if self.spacecraft_name == "APOLLO16":
            return 115537.5
        else:
            return 11450.5
        

    @property
    def naif_keywords(self):
        """
        Apollopaninit doesn't create naif keywords section, so populate it manually here.
        Only includes the NAIF keywords that are necessary for the ALE formatter.
        -------
        : dict
          Dictionary of NAIF keywords that are normally attached to the label
        """
        return {"BODY301_RADII": self.target_body_radii,
                "BODY_FRAME_CODE": self.target_frame_id,
                f"INS{self.ikid}_CONSTANT_TIME_OFFSET": 0,
                f"INS{self.ikid}_ADDITIONAL_PREROLL": 0,
                f"INS{self.ikid}_ADDITIVE_LINE_ERROR": 0,
                f"INS{self.ikid}_MULTIPLI_LINE_ERROR": 0,
                f"INS{self.ikid}_TRANSX": self.pixel2focal_x,
                f"INS{self.ikid}_TRANSY": self.pixel2focal_y,
                f"INS{self.ikid}_ITRANSS": self.focal2pixel_samples,
                f"INS{self.ikid}_ITRANSL": self.focal2pixel_lines,
                "BODY_CODE": 301}
 No newline at end of file
+282 −0
Original line number Diff line number Diff line
Object = IsisCube
  Object = Core
    StartByte   = 65537
    Format      = Tile
    TileSamples = 479
    TileLines   = 319

    Group = Dimensions
      Samples = 23950
      Lines   = 2552
      Bands   = 1
    End_Group

    Group = Pixels
      Type       = Real
      ByteOrder  = Lsb
      Base       = 0.0
      Multiplier = 1.0
    End_Group
  End_Object

  Group = Instrument
    SpacecraftName       = APOLLO15
    InstrumentName       = "APOLLO PANORAMIC CAMERA"
    InstrumentId         = APOLLO_PAN
    TargetName           = MOON
    StartTime            = 1971-08-04T16:28:24.9159358
    StopTime             = 1971-08-04T16:28:26.7420639
    LineExposureDuration = -0.0015893195483426 <sec/mm>
  End_Group

  Group = Kernels
    NaifFrameCode       = -915230
    LeapSecond          = $base/kernels/lsk/naif0010.tls
    TargetAttitudeShape = ($base/kernels/pck/pck00009.tpc,
                           $apollo15/kernels/pck/moon_080317.tf,
                           $apollo15/kernels/pck/moon_assoc_me.tf)
    TargetPosition      = (Table,
                           $apollo15/kernels/tspk/moon_pa_de421_1900-2050.bpc,
                           $apollo15/kernels/tspk/de421.bsp)
    ShapeModel          = $base/dems/ldem_128ppd_Mar2011_clon180_radius_pad.c-
                          ub
    InstrumentPointing  = Table
    InstrumentPosition  = Table
    InstrumentAddendum  = $apollo15/kernels/iak/apolloPanAddendum001.ti
    CameraVersion       = 1
  End_Group
End_Object

Object = Label
  Bytes = 65536
End_Object

Object = Table
  Name                = BodyRotation
  StartByte           = 244547137
  Bytes               = 5568
  Records             = 87
  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    = -896556653.92828
  CkTableEndTime      = -896556652.04736
  CkTableOriginalSize = 87
  FrameTypeCode       = 6
  Description         = "Created by apollopaninit"

  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            = 244552705
  Bytes                = 4872
  Records              = 87
  ByteOrder            = Lsb
  CacheType            = Linear
  SpkTableStartTime    = -896556653.92828
  SpkTableEndTime      = -896556652.04736
  SpkTableOriginalSize = 87.0
  Description          = "Created by apollopaninit"

  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              = InstrumentPosition
  StartByte         = 244557577
  Bytes             = 64
  Records           = 2
  ByteOrder         = Lsb
  SpkTableStartTime = -896556653.91001
  SpkTableEndTime   = -896556652.04736
  CacheType         = Linear
  Description       = "Created by apollopaninit"

  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 = ET
    Type = Double
    Size = 1
  End_Group
End_Object

Object = Table
  Name                = InstrumentPointing
  StartByte           = 244557641
  Bytes               = 3480
  Records             = 87
  ByteOrder           = Lsb
  CkTableStartTime    = -896556653.92828
  CkTableEndTime      = -896556652.04736
  Description         = "Created by appollopan2isis"
  TimeDependentFrames = (-915000, 1)
  ConstantFrames      = (-915230, -915000)
  ConstantRotation    = (1, 0, 0, 0, 1, 0, 0, 0, 1)

  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 = ET
    Type = Double
    Size = 1
  End_Group
End_Object

Object = Table
  Name      = "Fiducial Measurement"
  StartByte = 244561121
  Bytes     = 1780
  Records   = 89
  ByteOrder = Lsb

  Group = Field
    Name = FID_INEX
    Type = Integer
    Size = 1
  End_Group

  Group = Field
    Name = X_COORD
    Type = Double
    Size = 1
  End_Group

  Group = Field
    Name = Y_COORD
    Type = Double
    Size = 1
  End_Group
End_Object
End
+2808 −0

File added.

Preview size limit exceeded, changes collapsed.

+57 −2
Original line number Diff line number Diff line
@@ -8,7 +8,7 @@ import json

from conftest import get_image, get_image_label, get_isd, get_image_kernels, convert_kernels, compare_dicts
import ale
from ale.drivers.apollo_drivers import ApolloMetricIsisLabelNaifSpiceDriver
from ale.drivers.apollo_drivers import ApolloMetricIsisLabelNaifSpiceDriver, ApolloPanIsisLabelIsisSpiceDriver
from ale import util


@@ -65,3 +65,58 @@ class test_isis3_naif(unittest.TestCase):
  
    def test_ikid(self):
        assert self.driver.ikid == -915240


class test_apollo_isis_isis(unittest.TestCase):
    def setUp(self):
        label = get_image_label("apolloPanImage", "isis3")
        self.driver = ApolloPanIsisLabelIsisSpiceDriver(label)

    def test_instrument_name(self):
        assert self.driver.instrument_name == "APOLLO PANORAMIC CAMERA"

    def test_sensor_model_version(self):
        assert self.driver.sensor_model_version == 1

    def test_focal2pixel_lines(self):
        assert self.driver.focal2pixel_lines == (0.0, 0.0, 200.0)
    
    def test_focal2pixel_samples(self):
        assert self.driver.focal2pixel_samples == (0.0, 200.0, 0.0)

    def test_pixel2focal_x(self):
        assert self.driver.pixel2focal_x == (0.0, 0.005, 0.0)

    def test_pixel2focal_y(self):
        assert self.driver.pixel2focal_y == (0.0, 0.0, 0.0)

    def test_focal_length(self):
        assert self.driver.focal_length == 610.0

    def test_ephemeris_start_time(self):
        with patch('ale.drivers.apollo_drivers.read_table_data', return_value=1234), \
            patch('ale.drivers.apollo_drivers.parse_table', return_value={'ET':[5678]}) :
            assert self.driver.ephemeris_start_time == 5678

    def test_target_body_radii(self):
        assert self.driver.target_body_radii == (1737.4, 1737.4, 1737.4)

    def test_detector_center_line(self):
        assert self.driver.detector_center_line == 11450.5

    def test_detector_center_sample(self):
        assert self.driver.detector_center_sample == 11450.5

    def test_naif_keywords(self):
        with patch('ale.drivers.apollo_drivers.IsisSpice.target_frame_id', 31006):
            assert compare_dicts(self.driver.naif_keywords, {"BODY301_RADII": (1737.4, 1737.4, 1737.4),
                    "BODY_FRAME_CODE": 31006,
                    "INS-915230_CONSTANT_TIME_OFFSET": 0,
                    "INS-915230_ADDITIONAL_PREROLL": 0,
                    "INS-915230_ADDITIVE_LINE_ERROR": 0,
                    "INS-915230_MULTIPLI_LINE_ERROR": 0,
                    "INS-915230_TRANSX": (0.0, 0.005, 0.0),
                    "INS-915230_TRANSY": (0.0, 0.0, 0.0),
                    "INS-915230_ITRANSS": (0.0, 200.0, 0.0),
                    "INS-915230_ITRANSL": (0.0, 0.0, 200.0),
                    "BODY_CODE": 301}) == []
 No newline at end of file