コード例 #1
0
    def __init__(self) :

        self.emission_altitude  = 0.0
        self.time_offset        = 0.0
        self.iref               = 'J2000'
        self.abcorr             = 'LT'        
        self.data               = {}
        self.constants()
        
        self.sc_id              = spice.bodn2c(self.spacecraft)
        self.target_id          = spice.bodn2c(self.target)
        self.framestring        = 'IAU_' + self.target

        self.set_emission_altitude(self.emission_altitude)

        # The angle from the centre of the pixel to the edge
        self.xpxoffset = 0.5 * self.pxscale / 1000.0
        self.ypxoffset = 0.5 * self.pyscale / 1000.0

        # Generate a key mapping, so that we know which index is what. 
        self.keys = ['lat', 'lon', 'limb_lat', 'limb_lon', 'lat_graphic', 'lon_graphic','phase', 'emission', 'incidence', 'localtime', 'losdist', 'limb_distance', 'bodyintercept']

        self.map = {}
        for key, value in enumerate(self.keys) : self.map[value] = key

        self.angles = ['lat', 'lon', 'limb_lat', 'limb_lon', 'lat_graphic', 'lon_graphic','phase', 'emission', 'incidence']
コード例 #2
0
    def computeDataFrameGeometries(self, data_frames, greg_format_string,
                                   julian_format_string):

        for data_frame in data_frames:
            self.greg_format_string = greg_format_string
            self.julian_format_string = julian_format_string
            greg_split_string = self.greg_format_string.split(' ')
            data_frame.greg_time_system_string = [
                i for i in greg_split_string if '::' in i
            ][0][2:]
            julian_split_string = self.julian_format_string.split(' ')
            data_frame.julian_time_system_string = [
                i for i in julian_split_string if '::' in i
            ][0][2:]
            current_epoch = data_frame.start_epoch
            current_epoch = spice.str2et(current_epoch)
            stop_epoch = spice.str2et(data_frame.stop_epoch)
            time_remaining = stop_epoch - current_epoch

            while time_remaining >= 0.0:
                greg_date_string = spice.timout(current_epoch,
                                                self.greg_format_string)
                JD_date = spice.timout(current_epoch,
                                       self.julian_format_string)
                for body_pair in data_frame.body_pairs:
                    # get target body state
                    body_state, light_times = spice.spkez(
                        spice.bodn2c(body_pair[1]), current_epoch,
                        data_frame.frame, 'NONE', spice.bodn2c(body_pair[0]))
                    distance_km = self.np.linalg.norm(body_state[0:3])
                    distance_AU = distance_km / self.AU
                    data_frame.data[body_pair[0]][body_pair[1]].append([
                        greg_date_string, JD_date, body_state, distance_km,
                        distance_AU
                    ])

                # compute solar geometries
                SEP_angle, SPE_angle = self.computeSEPandSPEangles(
                    current_epoch, data_frame.spacecraft_SPICE_ID)
                data_frame.data['SEP'].append(
                    [greg_date_string, JD_date, SEP_angle])
                data_frame.data['SPE'].append(
                    [greg_date_string, JD_date, SPE_angle])

                # compute any eclipses
                self.computeCircleCircleOccultations(current_epoch,
                                                     greg_date_string, JD_date,
                                                     data_frame)

                if time_remaining == 0.0:
                    break
                else:
                    if time_remaining >= data_frame.time_step:
                        current_epoch += data_frame.time_step
                        time_remaining -= data_frame.time_step
                    else:
                        time_remaining -= stop_epoch - current_epoch
                        current_epoch += stop_epoch - current_epoch
コード例 #3
0
    def __init__(self, **kwargs):
        from spiceypy.utils.support_types import SpiceyError

        super(PSP, self).__init__("psp", body_name="SPP", **kwargs)

        try:
            spiceypy.bodn2c("SPP_SPACECRAFT")
        except SpiceyError:
            # kernel fix that is required due to PSP having different names
            spiceypy.boddef("SPP_SPACECRAFT", spiceypy.bodn2c("SPP"))
コード例 #4
0
ファイル: Pyprika.py プロジェクト: BeshBashBosh/SolBirthday
 def naifID(bodyStr):
     try:
         naifID = spice.bodn2c(bodyStr.upper())
         return naifID
     except spice.stypes.SpiceyError as e:
         print("ERROR: INVALID SPICE NAIF NAME ENTERED")
         raise e
コード例 #5
0
ファイル: test_spiceypy.py プロジェクト: skulumani/astro
 def test_eros_spk2_coverage(self):
     code = spice.bodn2c('EROS')
     cover = spice.stypes.SPICEDOUBLE_CELL(1000)
     spice.spkcov(self.near.SpkEros2, code, cover)
     result = [x for x in cover]
     expected_result = [-31334400.0, 81432000.0] 
     np.testing.assert_array_almost_equal(result, expected_result)
コード例 #6
0
ファイル: test_spiceypy.py プロジェクト: skulumani/astro
 def test_near_spk_orbit_coverage(self):
     code = spice.bodn2c('NEAR')
     cover = spice.stypes.SPICEDOUBLE_CELL(1000)
     spice.spkcov(self.near.SpkNearOrbit, code, cover)
     result = [x for x in cover]
     expected_result = [-43200.0, 35279120.0] 
     np.testing.assert_array_almost_equal(result, expected_result)
コード例 #7
0
ファイル: spicer.py プロジェクト: MukendiMputu/Tic-Tac-Toe
    def srfrec(self, surfcoord, body=None):
        """Convert lon/lat to rectangular coordinates.

        Convert planetocentric longitude and latitude of a surface point on a
        specified body to rectangular coordinates.

        self.target needs to be set for this!

        Parameters
        ----------
        surfcoord : SurfaceCoords
            Instance of SurfaceCoords.
        body : str or int, optional
            SPICE body str (will be converted) or SPICE body id. Default: self.body

        Examples
        --------

        >>> mspice = MarsSpicer()
        >>> print('{0:g} {1:g} {2:g}'.format(*mspice.srfrec(0,85)))
        294.268 0 3363.5
        """
        if body is None:
            body = self.target_id
        if not str(body).isdigit():
            body = spice.bodn2c(body)
        return spice.srfrec(body, surfcoord.lon.value, surfcoord.lat.value)
コード例 #8
0
    def __init__(self, sensor, host=object(), target=object(), time=object()):

        if isinstance(sensor, str):
            name = sensor
            id = cspice.bodn2c(sensor)
        else:
            id = sensor
            name = cspice.bodc2n(sensor)

        room = 99
        shapelen = 1000
        framelen = 1000

        fov_shape, frame, bsight, n, fov_bounds = cspice.getfov(
            id, room, shapelen, framelen)

        self.host = host
        self.target = target

        self.time = time
        self.name = name
        self.id = id
        self.fov_shape = fov_shape
        self.frame = frame
        self.bsight_ins = bsight
        self.fov_bounds = fov_bounds
        self.bsight_obs = []
        self.spoint = []
コード例 #9
0
ファイル: test_spiceypy.py プロジェクト: skulumani/astro
 def test_eros_spk1_coverage(self):
     spice.furnsh(self.near.metakernel)
     code = spice.bodn2c('EROS')
     cover = spice.stypes.SPICEDOUBLE_CELL(1000)
     spice.spkcov(self.near.SpkEros, code, cover)
     result = [x for x in cover]
     expected_result = [-126273600.0, 37886400.0]
     np.testing.assert_array_almost_equal(result, expected_result)
     spice.kclear()
コード例 #10
0
    def reference_frame(self):
        """
        Returns a string containing the name of the target reference frame
        Expects target_name to be defined. This must be a string containing the name
        of the target body

        Returns
        -------
        : str
        String name of the target reference frame
        """
        try:
            return spice.cidfrm(spice.bodn2c(self.target_name))[1]
        except:
            return 'IAU_{}'.format(self.target_name)
コード例 #11
0
def definition(sensor):

    #
    # We check if the resolution of the camera has been provided as an input
    # if not we try to obtain the resolution of the camera from the IK
    #
    sensor_id = spiceypy.bodn2c(sensor)

    pixel_samples = spiceypy.gdpool(f'INS{sensor_id}_PIXEL_SAMPLES', 0, 1)[0]
    pixel_lines = spiceypy.gdpool(f'INS{sensor_id}_PIXEL_LINES', 0, 1)[0]
    ccd_center = spiceypy.gdpool(f'INS{sensor_id}_CCD_CENTER', 0, 2)

    print(f'{sensor} pixel_samples (x)   = {pixel_samples}')
    print(f'{sensor} pixel_lines   (y)   = {pixel_lines}')
    print(f'{sensor} ccd_sensor    (x,y) = {ccd_center[0]},{ccd_center[1]}')

    return
コード例 #12
0
ファイル: kmaspice.py プロジェクト: michaelaye/pymars
    def srfrec(self, lon, lat, body=None):
        """Convert lon/lat to rectangular coordinates.

        Convert planetocentric longitude and latitude of a surface point on a
        specified body to rectangular coordinates.

        Input of angles in degrees, conversion is done here.
        If the body is not a SPICE ID, it will be converted.
        >>> mspice = MarsSpicer()
        >>> print('{0:g} {1:g} {2:g}'.format(*mspice.srfrec(0,85)))
        294.268 0 3363.5
        """
        if body is None:
            body = self.target_id
        if not str(body).isdigit():
            body = spice.bodn2c(body)
        return spice.srfrec(body, np.deg2rad(lon), np.deg2rad(lat))
コード例 #13
0
ファイル: hk.py プロジェクト: michaelaye/iuvs
def calc_utc_from_sclk(coarse, fine):
    """Requires to have SPICE kernels loaded (use load_kernels()).

    I'm not doing the loading of SPICE kernels in here so that I can
    run this function in a loop without using up kernel space.
    The caller should load and unload kernels as required.
    """
    # load_kernels()  # load SPICE kernels
    timestamp_ = coarse
    ss = fine
    mavenid, _ = spice.bodn2c('MAVEN')
    timestamp = timestamp_ + ss / 65536  # timestamp_ and ss are already float
    sec = np.uint64(timestamp)
    subsec = np.uint64((timestamp - sec) * 65536)
    sclkch = np.vectorize(format_times)(sec, subsec)
    sclkdp = np.vectorize(spice.scencd)(mavenid, sclkch)
    et = np.vectorize(spice.sct2e)(mavenid, sclkdp)
    utc = np.vectorize(spice.et2utc)(et, 'ISOC', 50, 100)
    return pd.to_datetime(utc)
コード例 #14
0
ファイル: hk.py プロジェクト: michaelaye/iuvs
def calc_utc_from_sclk(coarse, fine):
    """Requires to have SPICE kernels loaded (use load_kernels()).

    I'm not doing the loading of SPICE kernels in here so that I can
    run this function in a loop without using up kernel space.
    The caller should load and unload kernels as required.
    """
    # load_kernels()  # load SPICE kernels
    timestamp_ = coarse
    ss = fine
    mavenid, _ = spice.bodn2c('MAVEN')
    timestamp = timestamp_ + ss / 65536  # timestamp_ and ss are already float
    sec = np.uint64(timestamp)
    subsec = np.uint64((timestamp - sec) * 65536)
    sclkch = np.vectorize(format_times)(sec, subsec)
    sclkdp = np.vectorize(spice.scencd)(mavenid, sclkch)
    et = np.vectorize(spice.sct2e)(mavenid, sclkdp)
    utc = np.vectorize(spice.et2utc)(et, 'ISOC', 50, 100)
    return pd.to_datetime(utc)
コード例 #15
0
    def __init__(self, body, time=object(), target=None):

        if isinstance(body, str):
            name = body
            id = spiceypy.bodn2c(body)
        else:
            id = body
            name = spiceypy.bodc2n(body)

        if target:
            self.target = target

        self.name = name
        self.id = id
        self.time = time

        #
        # Parameters for the Geometry Computation
        #
        self.previous_tw = []
        self.geometry_flag = False
コード例 #16
0
    def __init__(self, ut, kernel_path, target='JUPITER'):
        '''
            `Projector` class initializer

            Parameters
            ----------
            ut : string
                Observation time in the UTC ISO format: 
                yyyy-mm-dd hh:mm:ss
            kernel_path : string
                Path to the NAIF generic_kernels folder
            target : string, [default=Jupiter]
                Name of the observing body
        '''
        ## find and load the kernels
        find_spice_kernels(kernel_path)

        ## convert the times
        self.ut = ut
        self.et = spiceypy.utc2et(ut)

        ## calculate target information
        self.target=target
        self.target_frame = 'IAU_'+target
        self.radii = spiceypy.bodvar(spiceypy.bodn2c(target), "RADII", 3)
        self.flattening = (self.radii[0] - self.radii[2])/self.radii[0]

        ## get the target state in J2000
        self.tstate, self.lt = \
            spiceypy.spkezr(target, self.et, 'J2000', 'CN', "EARTH")

        self.tRA, self.tDEC = \
            spiceypy.recrad(self.tstate[:3])[1:]

        self.find_sub_pt()
        self.find_limb()
        
        self.platecal = PlateCalibration(self.RADec0, self.RArotang)
コード例 #17
0
def pixel_boresight(sensor, i, j):

    #
    # We check if the resolution of the camera has been provided as an input
    # if not we try to obtain the resolution of the camera from the IK
    #

    sensor_id = spiceypy.bodn2c(sensor)
    (shape, sensor_frame, bsight, vectors,
     bounds) = spiceypy.getfov(sensor_id, 100)

    pixel_samples = spiceypy.gdpool(f'INS{sensor_id}_PIXEL_SAMPLES', 0, 1)
    pixel_lines = spiceypy.gdpool(f'INS{sensor_id}_PIXEL_LINES', 0, 1)

    #
    # We generate a matrix using the resolution of the framing camera as the
    # dimensions of the matrix
    #
    nx, ny = (int(pixel_lines[0]), int(pixel_samples[0]))
    x = np.linspace(bounds[0][0], bounds[2][0], nx)
    y = np.linspace(bounds[0][1], bounds[2][1], ny)

    return [x[int(i)], y[int(j)], bsight[2]]
コード例 #18
0
    def __init__(self, inst, et, abcorr, obsrvr, width, height, mag_limit):
        # input parameter
        self.inst = inst
        self.et = et
        self.abcorr = abcorr
        self.obsrvr = obsrvr
        self.width = width
        self.height = height

        # parameters equivalent to input parameter
        self.date = spice.et2utc(et, "ISOC", 3)
        self.inst_id = spice.bodn2c(inst)

        # Instrument FOV
        self.fov = Fov(self.inst_id)
        self.fov_in_degrees = self.fov.fovmax * 2.0 * spice.dpr()

        # geometry information
        self.pos, _ = spice.spkpos(obsrvr, et, self.fov.frame, abcorr, "SUN")
        self.obs2refmtx = spice.pxform(self.fov.frame, "J2000", et)
        self.ref2obsmtx = spice.pxform("J2000", self.fov.frame, et)

        # screen information
        pos_angle, angle_res, ra, dec = get_geometry_info(
            self.obs2refmtx, self.fov, width, height
        )

        self.center = self.fov.bounds_rect.center_vec
        self.pos_angle = pos_angle
        self.angle_res = angle_res
        self.ra = ra
        self.dec = dec

        # searched objects
        self.solar_objects = search_solar_objects(self)
        self.stars = search_stars(self, mag_limit)
コード例 #19
0
ファイル: vgCenter.py プロジェクト: bburns/PyVoyager
def getTargetPosition(target, craft, camera, time):
    """
    get position of target in world coordinates relative to the observing craft.
    """
    
    # get target code
    targetId = spice.bodn2c(target) # eg 'Jupiter'->599

    # get spacecraft instrument        
    spacecraft = -31 if craft=='Voyager1' else -32
    spacecraftBus = spacecraft * 1000
    spacecraftScanPlatform = spacecraftBus - 100
    spacecraftNarrowCamera = spacecraftScanPlatform - 1
    spacecraftWideCamera = spacecraftScanPlatform - 2
    # instrument = spacecraftBus # use for NAIF continuous kernels
    instrument = spacecraftScanPlatform # use for PDS discrete kernels

    # get ephemeris time
    # note: target and spacecraft locations are stored relative to J2000
    # time is utc time as string
    ephemerisTime = spice.str2et(time) # seconds since J2000 (will be negative)
    # sclkch = spice.sce2s(spacecraft, ephemerisTime) # spacecraft clock ticks, string
    # sclkdp = spice.sce2c(spacecraft, ephemerisTime) # spacecraft clock ticks, double
    clockTicks = spice.sce2c(spacecraft, ephemerisTime) # spacecraft clock ticks, double
    # print 'clockTicks',clockTicks

    # get position of target relative to spacecraft
    # this is the direction from craft to target in ECLIPB1950 frame
    observer = 'Voyager ' + craft[-1] # eg 'Voyager 1'
    frame = 'ECLIPB1950' # coordinate frame
    abberationCorrection = 'NONE'
    position, lightTime = spice.spkpos(target, ephemerisTime, frame,
                                       abberationCorrection, observer)
    # print 'target position relative to observer', position

    return position
コード例 #20
0
def target2frame(target):

    if target == '67P/C-G':
        target_frame = '67P/C-G_CK'
    elif target == '21 LUTETIA':
        target_frame = 'LUTETIA_FIXED'
    elif target == 'DIDYMOS' or target == 'DIDYMOON':
        target_frame = '{}_FIXED'.format(target)
    else:
        try:
            target_frame = 'IAU_' + target.upper()
            target_frame_id = spiceypy.namfrm(target_frame)
            if target_frame_id == 0:
                raise Exception
        except:
            try:
                target_id = str(spiceypy.bodn2c(target))
                target_frame = spiceypy.frmnam(int(target_id))
            except:
                target_id += '000'
                target_frame = spiceypy.frmnam(int(target_id))


    return target_frame
コード例 #21
0
    def __init__(self, kernels_folder=None):
        """
		Parameters:
			kernels_folder (string): If not provided, the path stored in the environment
				variable ``TESSPHOT_SPICE_KERNELS`` is used, and if that is not set, the
				``data/spice`` directory is used.
		"""

        logger = logging.getLogger(__name__)

        # If no kernel folder is given, used the one stored in env.var. or the default location:
        if kernels_folder is None:
            kernels_folder = os.environ.get(
                'TESSPHOT_SPICE_KERNELS',
                os.path.join(os.path.dirname(__file__), 'data', 'spice'))

        # Create list of kernels that should be loaded:
        files = (
            # Planetary ephemeris and TESS clock kernels:
            'tess2018338154046-41240_naif0012.tls',
            'tess2018338154429-41241_de430.bsp',
            'tess2019113195500-41374_sclk.tsc',

            # Predictive kernels of TESS's expected position:
            #'TESS_EPH_PRE_2YEAR_2018171_01.bsp',
            'TESS_EPH_PRE_LONG_2018109_02.bsp',
            'TESS_EPH_PRE_LONG_2019045_01.bsp',

            # Definite kernels of TESS's actual position:
            #'TESS_EPH_DEF_2018004_01.bsp', # Does not contain any information
            'TESS_EPH_DEF_2018080_01.bsp',
            #'TESS_EPH_DEF_2018108_01.bsp', # Surpassed by never version below
            'TESS_EPH_DEF_2018108_02.bsp',
            'TESS_EPH_DEF_2018115_01.bsp',
            'TESS_EPH_DEF_2018124_01.bsp',
            'TESS_EPH_DEF_2018133_01.bsp',
            'TESS_EPH_DEF_2018150_01.bsp',
            'TESS_EPH_DEF_2018183_01.bsp',
            'TESS_EPH_DEF_2018186_01.bsp',
            'TESS_EPH_DEF_2018190_01.bsp',
            'TESS_EPH_DEF_2018193_01.bsp',
            'TESS_EPH_DEF_2018197_01.bsp',
            'TESS_EPH_DEF_2018200_01.bsp',
            'TESS_EPH_DEF_2018204_01.bsp',
            'TESS_EPH_DEF_2018207_01.bsp',
            'TESS_EPH_DEF_2018211_01.bsp',
            'TESS_EPH_DEF_2018214_01.bsp',
            'TESS_EPH_DEF_2018218_01.bsp',
            'TESS_EPH_DEF_2018221_01.bsp',
            'TESS_EPH_DEF_2018225_01.bsp',
            'TESS_EPH_DEF_2018228_01.bsp',
            'TESS_EPH_DEF_2018232_01.bsp',
            'TESS_EPH_DEF_2018235_01.bsp',
            'TESS_EPH_DEF_2018239_01.bsp',
            'TESS_EPH_DEF_2018242_01.bsp',
            'TESS_EPH_DEF_2018246_01.bsp',
            'TESS_EPH_DEF_2018249_01.bsp',
            'TESS_EPH_DEF_2018253_01.bsp',
            'TESS_EPH_DEF_2018256_01.bsp',
            'TESS_EPH_DEF_2018260_01.bsp',
            'TESS_EPH_DEF_2018263_01.bsp',
            'TESS_EPH_DEF_2018268_01.bsp',
            'TESS_EPH_DEF_2018270_01.bsp',
            'TESS_EPH_DEF_2018274_01.bsp',
            'TESS_EPH_DEF_2018277_01.bsp',
            'TESS_EPH_DEF_2018282_01.bsp',
            'TESS_EPH_DEF_2018285_01.bsp',
            'TESS_EPH_DEF_2018288_01.bsp',
            'TESS_EPH_DEF_2018291_01.bsp',
            'TESS_EPH_DEF_2018295_01.bsp',
            'TESS_EPH_DEF_2018298_01.bsp',
            'TESS_EPH_DEF_2018302_01.bsp',
            'TESS_EPH_DEF_2018305_01.bsp',
            'TESS_EPH_DEF_2018309_01.bsp',
            'TESS_EPH_DEF_2018312_01.bsp',
            'TESS_EPH_DEF_2018316_01.bsp',
            'TESS_EPH_DEF_2018319_01.bsp',
            'TESS_EPH_DEF_2018323_01.bsp',
            'TESS_EPH_DEF_2018327_01.bsp',
            'TESS_EPH_DEF_2018330_01.bsp',
            'TESS_EPH_DEF_2018333_01.bsp',
            'TESS_EPH_DEF_2018337_01.bsp',
            'TESS_EPH_DEF_2018340_01.bsp',
            'TESS_EPH_DEF_2018344_01.bsp',
            'TESS_EPH_DEF_2018347_01.bsp',
            'TESS_EPH_DEF_2018351_01.bsp',
            'TESS_EPH_DEF_2018354_01.bsp',
            'TESS_EPH_DEF_2018358_01.bsp',
            'TESS_EPH_DEF_2018361_01.bsp',
            'TESS_EPH_DEF_2018365_01.bsp',
            'TESS_EPH_DEF_2019003_01.bsp',
            'TESS_EPH_DEF_2019007_01.bsp',
            'TESS_EPH_DEF_2019010_01.bsp',
            'TESS_EPH_DEF_2019014_01.bsp',
            'TESS_EPH_DEF_2019017_01.bsp',
            'TESS_EPH_DEF_2019021_01.bsp',
            'TESS_EPH_DEF_2019024_01.bsp',
            'TESS_EPH_DEF_2019028_01.bsp',
            'TESS_EPH_DEF_2019031_01.bsp',
            'TESS_EPH_DEF_2019035_01.bsp',
            'TESS_EPH_DEF_2019038_01.bsp',
            'TESS_EPH_DEF_2019042_01.bsp',
            'TESS_EPH_DEF_2019045_01.bsp',
            'TESS_EPH_DEF_2019049_01.bsp',
            'TESS_EPH_DEF_2019052_01.bsp',
            'TESS_EPH_DEF_2019056_01.bsp',
            'TESS_EPH_DEF_2019059_01.bsp',
            'TESS_EPH_DEF_2019063_01.bsp',
            'TESS_EPH_DEF_2019066_01.bsp',
            'TESS_EPH_DEF_2019070_01.bsp',
            'TESS_EPH_DEF_2019073_01.bsp',
            'TESS_EPH_DEF_2019077_01.bsp',
            'TESS_EPH_DEF_2019080_01.bsp',
            'TESS_EPH_DEF_2019084_01.bsp',
            'TESS_EPH_DEF_2019087_01.bsp',
            'TESS_EPH_DEF_2019091_01.bsp',
            'TESS_EPH_DEF_2019094_01.bsp',
            'TESS_EPH_DEF_2019098_01.bsp',
            'TESS_EPH_DEF_2019102_01.bsp',
            'TESS_EPH_DEF_2019105_01.bsp',
            'TESS_EPH_DEF_2019108_01.bsp',
            'TESS_EPH_DEF_2019112_01.bsp',
            'TESS_EPH_DEF_2019115_01.bsp',
            'TESS_EPH_DEF_2019119_01.bsp',
            'TESS_EPH_DEF_2019122_01.bsp',
            'TESS_EPH_DEF_2019126_01.bsp')

        # Make sure the kernel directory exists:
        if not os.path.exists(kernels_folder):
            os.makedirs(kernels_folder)

        # Automatically download kernels from TASOC, if they don't already exist?
        #urlbase = 'https://archive.stsci.edu/missions/tess/models/'
        urlbase = 'https://tasoc.dk/pipeline/spice/'
        for fname in files:
            fpath = os.path.join(kernels_folder, fname)
            if not os.path.exists(fpath):
                download_file(urlbase + fname, fpath)

        # Path where meta-kernel will be saved:
        fileshash = hashlib.md5(','.join(files).encode()).hexdigest()
        self.METAKERNEL = os.path.abspath(
            os.path.join(kernels_folder, 'metakernel-' + fileshash + '.txt'))

        # Write meta-kernel to file:
        if not os.path.exists(self.METAKERNEL):
            with open(self.METAKERNEL, 'w') as fid:
                fid.write("KPL/MK\n")
                fid.write(r"\begindata" + "\n")
                fid.write("PATH_VALUES = ('" +
                          os.path.abspath(kernels_folder) + "')\n")
                fid.write("PATH_SYMBOLS = ('KERNELS')\n")
                fid.write("KERNELS_TO_LOAD = (\n")
                fid.write(",\n".join(
                    ["'$KERNELS/" + fname + "'" for fname in files]))
                fid.write(")\n")
                fid.write(r"\begintext" + "\n")
                fid.write("End of MK file.\n")

        # Because SpiceyPy loads kernels into a global memory scope (BAAAAADDDD SpiceyPy!!!),
        # we first check if we have already loaded this into the global scope:
        # This is to attempt to avoid loading in the same kernels again and again when
        # running things in parallel.
        already_loaded = False
        for k in range(spiceypy.ktotal('META')):
            if os.path.abspath(spiceypy.kdata(k,
                                              'META')[0]) == self.METAKERNEL:
                logger.debug("SPICE Meta-kernel already loaded.")
                already_loaded = True
                break

        # Define TESS object if it doesn't already exist:
        try:
            spiceypy.bodn2c('TESS')
        except SpiceyError:
            logger.debug("Defining TESS name in SPICE")
            spiceypy.boddef('TESS', -95)

        # Load kernels if needed:
        if not already_loaded:
            logger.debug("Loading SPICE Meta-kernel: %s", self.METAKERNEL)
            spiceypy.furnsh(self.METAKERNEL)

        # Let's make sure astropy is using the de430 kernels as well:
        # Default is to use the same as is being used by SPOC (de430).
        # If using astropy 4.0+, we can load the local one directly. Before this,
        # it needs to be downloaded and cached:
        # NOTE: https://github.com/astropy/astropy/pull/8767
        #self.planetary_ephemeris = 'de430'
        if astropy_major_version >= 4:
            self.planetary_ephemeris = os.path.abspath(
                os.path.join(kernels_folder,
                             'tess2018338154429-41241_de430.bsp'))
        else:
            self.planetary_ephemeris = 'https://tasoc.dk/pipeline/spice/tess2018338154429-41241_de430.bsp'
        self._old_solar_system_ephemeris = coord.solar_system_ephemeris.get()
        coord.solar_system_ephemeris.set(self.planetary_ephemeris)
コード例 #22
0
def geometry(et, bsight, target, frame, sensor, observer=''):

    if not observer:
        observer = sensor

    # Time tag [UTC]
    # pixel id [(x,y)]
    # corner id [(x,y)]

    # Requested geometry

    # lat lon intersection (planetocentric)
    # lat lon subspacecraft
    # lat lon subsolar
    # target distance intersection
    # target angular diameter
    # local solar time intersection
    # phase angle intersection
    # emission angle intersection
    # incidence angle intersection

    #
    # We retrieve the camera information using GETFOV. More info available:
    #
    #   https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/getfov_c.html
    #
    sensor_id = spiceypy.bodn2c(sensor)
    (shape, sensor_frame, ibsight, vectors,
     bounds) = spiceypy.getfov(sensor_id, 100)

    visible = spiceypy.fovtrg(sensor, target, 'ELLIPSOID', frame, 'LT+S',
                              observer, et)

    if not visible:
        return 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0

    tarid = spiceypy.bodn2c(target)

    n, radii = spiceypy.bodvrd(target, 'RADII', 3)
    re = radii[0]
    rp = radii[2]
    f = (re - rp) / re

    try:
        #
        # https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/sincpt_c.html
        #
        # For each pixel we compute the possible intersection with the target, if
        # the target is intersected we then compute the illumination angles. We
        # use the following SPICE APIs: SINCPT and ILLUMF
        #
        #   https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/sincpt_c.html
        #   https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/illumf_c.html
        #
        (spoint, trgepc, srfvec) = \
            spiceypy.sincpt('ELLIPSOID', target, et, frame, 'LT+S', observer, sensor_frame, bsight)

        (tarlon, tarlat, taralt) = spiceypy.recgeo(spoint, re, f)
        tardis = spiceypy.vnorm(srfvec)

        #
        # Angular diameter
        #
        tarang = np.degrees(
            2 * np.arctan(max(radii) / spiceypy.vnorm(spoint + srfvec)))

        #
        # https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/illumf_c.html
        #
        (trgenpc, srfvec, phase, incdnc, emissn, visiblef, iluminatedf) = \
             spiceypy.illumf('ELLIPSOID', target, 'SUN', et, frame, 'LT+S', observer, spoint)

        phase *= spiceypy.dpr()
        incdnc *= spiceypy.dpr()
        emissn *= spiceypy.dpr()

        #
        # https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/et2lst_c.html
        #
        #    VARIABLE  I/O  DESCRIPTION
        #    --------  ---  --------------------------------------------------
        #    et         I   Epoch in seconds past J2000 epoch.
        #    body       I   ID-code of the body of interest.
        #    lon        I   Longitude of surface point (RADIANS).
        #    type       I   Type of longitude "PLANETOCENTRIC", etc.
        #    timlen     I   Available room in output time string.
        #    ampmlen    I   Available room in output `ampm' string.
        #    hr         O   Local hour on a "24 hour" clock.
        #    mn         O   Minutes past the hour.
        #    sc         O   Seconds past the minute.
        #    time       O   String giving local time on 24 hour clock.
        #    ampm       O   String giving time on A.M./ P.M. scale.
        (hr, mn, sc, ltime, ampm) = \
            spiceypy.et2lst(et, tarid, tarlon, 'PLANETOCENTRIC', 80, 80)

        #
        # https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/subpnt_c.html
        #
        #    Variable  I/O  Description
        #    --------  ---  --------------------------------------------------
        #    method     I   Computation method.
        #    target     I   Name of target body.
        #    et         I   Epoch in TDB seconds past J2000 TDB.
        #    fixref     I   Body-fixed, body-centered target body frame.
        #    abcorr     I   Aberration correction flag.
        #    obsrvr     I   Name of observing body.
        #    spoint     O   Sub-observer point on the target body.
        #    trgepc     O   Sub-observer point epoch.
        #    srfvec     O   Vector from observer to sub-observer point
        #
        (spoint, trgepc, srfev) = \
            spiceypy.subpnt('INTERCEPT/ELLIPSOID', target, et, frame, 'LT+S', observer)

        (sublon, sublat, subalt) = spiceypy.recgeo(spoint, re, f)

        #
        # https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/subslr_c.html
        #
        #    Variable  I/O  Description
        #    --------  ---  --------------------------------------------------
        #    method     I   Computation method.
        #    target     I   Name of target body.
        #    et         I   Epoch in ephemeris seconds past J2000 TDB.
        #    fixref     I   Body-fixed, body-centered target body frame.
        #    abcorr     I   Aberration correction.
        #    obsrvr     I   Name of observing body.
        #    spoint     O   Sub-solar point on the target body.
        #    trgepc     O   Sub-solar point epoch.
        #    srfvec     O   Vector from observer to sub-solar point.
        #
        (spoint, trgepc, srfev) = \
            spiceypy.subslr('INTERCEPT/ELLIPSOID', target, et, frame, 'LT+S', observer)

        (sunlon, sunlat, sunalt) = spiceypy.recgeo(spoint, re, f)

        return tarlon, tarlat, sublon, sublat, sunlon, sunlat, tardis, tarang, ltime, phase, emissn, incdnc

    except:
        return 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
コード例 #23
0
ファイル: kmaspice.py プロジェクト: michaelaye/pymars
 def _get_target_id(self):
     return spice.bodn2c(self.target)
コード例 #24
0
ファイル: egu_movie.py プロジェクト: zhaomingxian/3DCORE
        90 - 90,  # Inclination
        0.24,  # Diameter (1AU)
        -1,  # Handedness
        12,  # Strength (1AU)
        10,  # Turns
        1.5e-7,  # Drag parameter
        400,  # Solar wind speed
        5  # Solar wind strength
    )

    # load spice kernels
    mfr3dcore.spice.load_kernels("generic")
    mfr3dcore.spice.load_kernels("SPP")

    # required because of two separate names for PSP
    spiceypy.boddef("SPP_SPACECRAFT", spiceypy.bodn2c("SPP"))

    # crossing times (hours after t0, these values were found manually)
    t1 = t0 + datetime.timedelta(hours=3)
    t2 = t0 + datetime.timedelta(hours=28)

    # ========== 3D PLOTS ==========

    # define time series for simulation
    ts = [
        t0 + datetime.timedelta(minutes=i) for i in range(-1 * 60, 50 * 60, 5)
    ]
    #ts_step1 = [t0 + datetime.timedelta(hours=i) for i in range(-1, 1 + 1)]
    #ts_step2 = [t1 + datetime.timedelta(hours=i) for i in range(-1, 1 + 1)]
    #ts_step3 = [t2 + datetime.timedelta(hours=i) for i in range(-1, 1 + 1)]
コード例 #25
0
def simulate_image(utc,
                   metakernel,
                   camera,
                   target,
                   target_frame,
                   pixel_lines=False,
                   pixel_samples=False,
                   dsk=False,
                   generate_image=False,
                   plot_image=False,
                   report=False,
                   name=False):
    '''

    :param utc: Image acquisition time in UTC format e.g.: 2016-01-01T00:00:00
    :type utc: str
    :param metakernel: SPICE Kernel Dataset Meta-Kernel
    :type metakernel: str
    :param camera: Name of the camera to be used. Usually found in the
    instrument kernel (IK) e.g.: 'ROS_NAVCAM-A'
    :type camera: str
    :param target: Target of the observation, e.g.:'67P/C-G'
    :type target: str
    :param target_frame: SPICE reference frame of the target. Usually found in
    the frames kernel (FK)
    :type target_frame: str
    :param pixel_lines: Number of pixel lines usually provided by the IK.
    :type pixel_lines: int
    :param pixel_samples: Number of pixel samples per line usually provided by
    the IK.
    :type pixel_samples: int
    :param dsk: Digital Shape Model to be used for the computation. Not required
    of included in the Meta-Kernel.
    :type dsk: str
    :param generate_image: Flag to determine whether if the image is saved or
    plotted.
    :type generate_image: bool
    :param plot_image: Flag to determine whether if the image is to be plotted or
    plotted.
    :type generate_image: bool
    :param report: Flag for processing report.
    :type generate_image: bool
    :param name: Name to be provided to the image
    :type generate_image: str
    :return: Name of the output image
    :rtype: str
    '''

    spiceypy.furnsh(metakernel)

    if dsk:
        spiceypy.furnsh(dsk)
        method = 'DSK/UNPRIORITIZED'
    else:
        method = 'ELLIPSOID'

    et = spiceypy.utc2et(utc)

    #
    # We retrieve the camera information using GETFOV. More info available:
    #
    #   https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/getfov_c.html
    #
    camera_name = camera
    camera_id = spiceypy.bodn2c(camera_name)
    (shape, frame, bsight, vectors, bounds) = spiceypy.getfov(camera_id, 100)

    #
    # TODO: In the future all the sensors should be epehmeris objects, see
    # https://issues.cosmos.esa.int/socci/browse/SPICEMNGT-77
    #
    if camera.split('_')[0] == 'ROS':
        observer = 'ROSETTA'
    elif camera.split('_')[0] == 'MEX':
        observer = 'MEX'
    elif camera.split('_')[0] == 'VEX':
        observer = 'VEX'
    elif camera.split('_')[0] == 'JUICE':
        observer = 'JUICE'
    else:
        observer = camera

    #
    # We check if the resolution of the camera has been provided as an input
    # if not we try to obtain the resolution of the camera from the IK
    #
    if not pixel_lines or not pixel_samples:
        try:
            pixel_samples = int(
                spiceypy.gdpool('INS' + str(camera_id) + '_PIXEL_SAMPLES', 0,
                                1))
            pixel_lines = int(
                spiceypy.gdpool('INS' + str(camera_id) + '_PIXEL_LINES', 0, 1))
        except:
            pass
            print("PIXEL_SAMPLES and/or PIXEL_LINES not defined for "
                  "{}".format(camera))
            return

    #
    # We generate a matrix using the resolution of the framing camera as the
    # dimensions of the matrix
    #
    nx, ny = (pixel_samples, pixel_lines)
    x = np.linspace(bounds[0][0], bounds[2][0], nx)
    y = np.linspace(bounds[0][1], bounds[2][1], ny)
    xv, yv = np.meshgrid(x, y)

    #
    # We define the matrices that will be used as outputs and the
    #
    phase_matrix = np.zeros((nx, ny))
    emissn_matrix = np.zeros((nx, ny))
    solar_matrix = np.zeros((nx, ny))

    #
    # For each pixel we compute the possible intersection with the target, if
    # the target is intersected we then compute the illumination angles. We
    # use the following SPICE APIs: SINCPT and ILLUMF
    #
    #   https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/sincpt_c.html
    #   https://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/illumf_c.html
    #
    isvisible, isiluminated = [], []
    for i, x in enumerate(xv):
        for j, y in enumerate(yv):

            #
            # List of pixel's boresight
            #
            ibsight = [x[i], y[j], bsight[2]]

            try:
                (spoint, trgepc,
                 srfvec) = spiceypy.sincpt(method, target, et, target_frame,
                                           'NONE', observer, frame, ibsight)
                (trgepc, srfvec, phase, solar, emissn, visiblef,
                 iluminatedf) = spiceypy.illumf(method, target, 'SUN', et,
                                                target_frame, 'LT+S', observer,
                                                spoint)

                emissn_matrix[i, j] = emissn
                phase_matrix[i, j] = phase

                #
                # Add to list if the point is visible to the camera
                #
                if visiblef == True:
                    isvisible.append(visiblef)
                #
                # Add to list if the point is illuminated and seen by the camera
                #
                if iluminatedf == True:

                    isiluminated.append(iluminatedf)
                    solar_matrix[i, j] = solar

                else:
                    #
                    # And we set the not illuminated pixels with np.pi/2
                    #
                    solar_matrix[i, j] = np.pi / 2

            except:
                pass

                #
                # If SINCPT raises an error, we set that we see nothing in
                # the pixel.
                #
                emissn_matrix[i, j] = 0
                phase_matrix[i, j] = np.pi
                solar_matrix[i, j] = np.pi / 2

    if report:
        print('Pixel report for {} w.r.t {} @ {}'.format(camera, target, utc))
        print('   Total number of pixels: ', pixel_samples * pixel_lines)
        print('   Illuminated pixels:     ', len(isvisible))
        print('   Hidden pixels:          ',
              pixel_samples * pixel_lines - len(isvisible))
        print('   Shadowed points:        ',
              pixel_samples * pixel_lines - len(isiluminated))

    #
    # We transform the matrix from illumination angles to greyscale [0-255]
    #
    rescaled = (255 / (solar_matrix.max() - solar_matrix.min()) *
                (solar_matrix - solar_matrix.min())).astype(np.uint8)
    rescaled = -np.flip(rescaled, 0) + 255

    #
    # We generate the plot
    #
    if generate_image:
        if not name:

            name = '{}_{}_{}.png'.format(camera.lower(), name, utc.lower())

        imageio.imwrite(name, rescaled)

    if plot_image:
        plt.imshow(rescaled, cmap='gray')
        plt.axis('off')
        plt.show()

    return name
コード例 #26
0
ファイル: spice_calcs_v03b.py プロジェクト: irthomas/work
    utctime_start = sp.str2et(utcstring_start)
    utctime_end = sp.str2et(utcstring_end)

    total_seconds = utctime_end - utctime_start
    nsteps = int(np.floor(total_seconds / step))
    times = np.arange(nsteps) * step + utctime_start
    time_strings = [
        sp.et2utc(time_in, formatstr, prec) for time_in in list(times)
    ]

    tgo_pos = np.asfarray([
        sp.spkpos(target, time, ref, abcorr, observer)[0]
        for time in list(times)
    ])
    tgo_dist = la.norm(tgo_pos, axis=1)
    code = sp.bodn2c(target)
    pradii = sp.bodvcd(code, 'RADII', 3)  # 10 = Sun
    sun_radius = pradii[1][0]
    sun_diameter_arcmins = np.arctan(
        sun_radius / tgo_dist) * sp.dpr() * 60.0 * 2.0

    fig1 = plt.figure(figsize=(figx - 6, figy - 5))
    plt.plot(sun_diameter_arcmins)
    plt.xlabel("UTC time")
    plt.ylabel("Solar diameter as seen from TGO (arcminutes)")
    title = "Apparent diameter of Sun over 1 Martian year"
    plt.title(title)
    x_tick_indices = range(0, len(times), 24 * 183)
    x_tick_names = [
        time_strings[x_tick_index] for x_tick_index in x_tick_indices
    ]
コード例 #27
0
ファイル: kmaspice.py プロジェクト: michaelaye/pymars
 def _get_instrument_id(self):
     if not self.instrument:
         print("Instrument is not set yet.")
         return
     return spice.bodn2c(self.instrument)
コード例 #28
0
def pixel_samples(sensor):
    sensor_id = spiceypy.bodn2c(sensor)
    return spiceypy.gdpool(f'INS{sensor_id}_PIXEL_SAMPLES', 0, 1)[0]
コード例 #29
0
def pixel_lines(sensor):
    sensor_id = spiceypy.bodn2c(sensor)
    return spiceypy.gdpool(f'INS{sensor_id}_PIXEL_LINES', 0, 1)[0]
コード例 #30
0
def ccd_center(sensor):
    sensor_id = spiceypy.bodn2c(sensor)
    return spiceypy.gdpool(f'INS{sensor_id}_CCD_CENTER', 0, 2)
コード例 #31
0
ファイル: vgMap.py プロジェクト: bburns/PyVoyager
def vgMap(filterVolumes=None, optionOverwrite=False, directCall=True):

    "Build up 2d color map"

    # # cmd = "echo $ISISROOT"
    # cmd = "env | ag ^ISIS"
    # s = lib.system(cmd)
    # print s


    # load SPICE kernels (data files) with camera and target positions, etc
    libspice.loadKernels()

    # read small dbs into memory
    # centeringInfo = lib.readCsv(config.dbCentering) # when to turn centering on/off
    retargetingInfo = lib.readCsv(config.dbRetargeting) # remapping listed targets
    csvPositions, fPositions = lib.openCsvReader(config.dbPositions) # for target size

    # # dictionary to keep track of last image file in target sequence (eg for Ariel flyby)
    # lastImageInTargetSequence = {}

    # size of 2d map
    mymax = 800
    mxmax = 2 * mymax
    mxcenter = mxmax/2
    mycenter = mymax/2

    # set up blank mapping arrays: h(x,y) = (hx(x,y), hy(x,y))
    # h tells map where to pull its pixels from - ie map(mx,my) = im(h(mx,my))
    hx = np.zeros((mymax,mxmax),np.float32)
    hy = np.zeros((mymax,mxmax),np.float32)

    # make blank maps for each color channel
    #. each system-craft-target-camera-channel will need its own png map file to write to and colorize from
    # store in a map folder
    # bluemap = np.zeros((mymax,mxmax),np.float32)
    bluemap = np.zeros((mymax,mxmax),np.uint8)
    # each might also need a count map, if wind up averaging things together to smooth things out
    # would prefer to avoid it if possible though - adds more complexity and i/o
    countmap = np.zeros((mymax,mxmax),np.uint8)

    # iterate through all available images, filter on desired volume or image
    csvFiles, fFiles = lib.openCsvReader(config.dbFiles)
    nfile = 1
    for rowFiles in csvFiles:
        volume = rowFiles[config.colFilesVolume]
        fileId = rowFiles[config.colFilesFileId]

        # filter to given volume
        # if volume!=filterVolume: continue

        # get image properties
        filter = rowFiles[config.colFilesFilter]
        system = rowFiles[config.colFilesSystem]
        craft = rowFiles[config.colFilesCraft]
        target = rowFiles[config.colFilesTarget]
        camera = rowFiles[config.colFilesCamera]
        time = rowFiles[config.colFilesTime]
        note = rowFiles[config.colFilesNote]

        # relabel target field if necessary
        target = lib.retarget(retargetingInfo, fileId, target)

        #. skip others
        if fileId!='C1465335': continue

        # get cube filename
        cubefile = lib.getFilepath('import', volume, fileId)
        if not os.path.isfile(cubefile):
            # print 'warning file not found', cubefile
            continue #. for now


        # get folders
        importSubfolder = lib.getSubfolder('import', volume)
        jpegSubfolder = importSubfolder + 'jpegs/'
        # mapSubfolder = importSubfolder + 'maps/'
        mapSubfolder = importSubfolder #. for now
        lib.mkdir(jpegSubfolder)
        lib.mkdir(mapSubfolder)

        # export as jpeg
        imagefile = jpegSubfolder + fileId + '.jpg'
        # if not os.path.isfile(imagefile):
        if 1:
            cmd = "isis2std from=%s to=%s format=jpeg" % (cubefile, imagefile)
            print cmd
            lib.system(cmd)

        # print 'Volume %s mapping %d: %s      \r' % (volume,nfile,infile),
        # print 'Volume %s mapping %d: %s' % (volume,nfile,infile)
        nfile += 1


        # get target code, eg Jupiter
        targetId = spice.bodn2c(target) # eg 'Jupiter'->599
        # print target, targetId

        # get instrument
        spacecraft = -31 if craft=='Voyager1' else -32
        spacecraftBus = spacecraft * 1000 # eg -31000
        spacecraftScanPlatform = spacecraftBus - 100 # eg -31100
        spacecraftNarrowCamera = spacecraftScanPlatform - 1 # eg -31101
        spacecraftWideCamera = spacecraftScanPlatform - 2 # eg -31102
        # instrument = spacecraftBus # eg -31000, use for NAIF continuous kernels
        instrument = spacecraftScanPlatform # eg -31100, use for PDS discrete kernels

        # get ephemeris time
        ephemerisTime = spice.str2et(time) # seconds since J2000 (will be negative)

        # world coordinate frame to use
        # (ECLIPB1950 is how the voyager and planet positions are encoded)
        frame = 'ECLIPB1950'

        # get world-to-camera matrix (camera pointing matrix)
        # C is a transformation matrix from ELIPB1950 to the instrument-fixed frame
        # at the given time
        C = getCameraMatrix(frame, spacecraft, instrument, ephemerisTime)
        print 'C=camera pointing matrix - transform world to camera coords'
        print C

        # get world-to-body matrix
        # B = getBodyMatrix(frame, targetId, ephemerisTime)
        B = spice.tipbod(frame, targetId, ephemerisTime)
        print 'B=world to body/target frame matrix'
        print B


        # get boresight vector
        # this is just the third row of the C-matrix, *per spice docs*
        boresight = C[2]
        print 'boresight pointing vector',boresight

        # get location of prime meridian
        rotationRate = 870.5366420 # deg/day for great red spot
        primeMeridian = rotationRate /24/60/60 * ephemerisTime # deg
        print 'primeMeridian (deg)', primeMeridian % 360
        primeMeridianRadians = primeMeridian * math.pi/180

        # get target position in world coordinates
        # ie vector from craft to target
        # and distance
        observer = 'Voyager ' + craft[-1] # eg Voyager 1
        abberationCorrection = 'NONE'
        position, lightTime = spice.spkpos(target, ephemerisTime, frame,
                                           abberationCorrection, observer)
        # position = getObserverToTargetVector(frame, observer, target, ephemerisTime)
        distance = libspice.getDistance(position)
        posnormal = position / distance
        print 'target position relative to observer',position
        print 'distance in km',distance
        print 'position normalized', posnormal

        # see how different boresight and position vector are
        dot = np.dot(boresight, posnormal)
        theta = math.acos(dot) * 180/math.pi
        print 'angle between boresight and position vector', theta


        # what longitudes are visible?
        #.. get from position of craft
        visibleLongitudesMin = 0
        visibleLongitudesMax = math.pi

        # get tilt of north pole relative to image y-axis
        npRadians = getNorthPoleAngle(target, position, C, B, camera)

        # get axial tilt rotation matrix
        cc = math.cos(npRadians)
        ss = math.sin(npRadians)
        mTilt = np.array([[cc,-ss],[ss,cc]])

        # get expected angular size (as fraction of frame) and radius
        imageFraction = lib.getImageFraction(csvPositions, fileId)
        targetRadiusPx = int(400*imageFraction) #.param

        # read the (centered) image
        im = cv2.imread(imagefile)

        # draw the target's north pole on image
        # im = drawNorthPole(im)

        # build hx,hy arrays, which tell map where to pull pixels from in source image
        # m: map (0 to mxmax, 0 to mymax)
        r = targetRadiusPx # pixels
        for mx in xrange(mxmax): # eg 0 to 1600
            for my in xrange(mymax): # eg 0 to 800

                # q: map (0 to 2pi, -1 to 1)
                qx = float(mx) / mxmax * 2 * math.pi + primeMeridianRadians
                qx = qx % (2 * math.pi) # 0 to 2pi
                qy = -float(my-mycenter)/mycenter # 1 to -1

                # s: image (-1 to 1, -1 to 1)
                sx = -math.sqrt(1 - qy**2) * math.cos(qx) # -1 to 1
                sy = qy # 1 to -1

                # rotate s to account for axial tilt relative to camera up axis
                # ie s = mTilt * s
                s = np.array([sx,sy])
                s = np.dot(mTilt,s)
                sx,sy = s

                # p: image (0 to 800, 0 to 800)
                px = sx * r + 400 # 0 to 800
                py = -sy * r + 400 # 0 to 800

                # hx[my][mx] = px
                # hy[my][mx] = py
                visible = (qx >= visibleLongitudesMin) and (qx <= visibleLongitudesMax)
                if visible:
                    hx[my][mx] = px
                    hy[my][mx] = py
                else:
                    hx[my][mx] = 0
                    hy[my][mx] = 0

        # do map projection
        map = cv2.remap(im, hx, hy, cv2.INTER_LINEAR)
        map = map[:,:,0]
        # map = np.array(map, np.float32)
        libimg.show(map)

        # save map as png file
        mapfile = mapSubfolder + fileId + '-map.png'
        cv2.imwrite(mapfile, map)

        sys.exit(0)


        # #. now need to blend this into the main map for this filter

        # # print type(map[0][0])
        # # print type(bluemap[0][0])

        # # bluemap = cv2.addWeighted(bluemap, 0.5, map, 0.5, 0)

        # # ret, countzero = cv2.threshold(countmap, 0,255, cv2.THRESH_BINARY)
        # # ret, countone = cv2.threshold(countmap, 0,255, cv2.THRESH_BINARY)
        # # countzero = 255-countone
        # # ret, mapMask = cv2.threshold(map, 1, 255, cv2.THRESH_BINARY)
        # # mapMask = cv2.bitwise_and(countzero, mapMask)
        # # c = mapMask & 1
        # # countmap += c

        # # libimg.show(countmap)

        # # ret, mapnonzero = cv2.threshold(map, 0,1, cv2.THRESH_BINARY)
        # ret, mapnonzero = cv2.threshold(map, 1,1, cv2.THRESH_BINARY)

        # countmapPlusOne = countmap + 1
        # countmap2 = countmap + 1-mapnonzero
        # base = np.array(bluemap, np.float32)
        # # base = base * countmap / countmapPlusOne
        # base = base * countmap2 / countmapPlusOne
        # newmap = np.array(map, np.float32)
        # newmap = newmap / countmapPlusOne
        # newbase = base + newmap
        # newbase = np.array(newbase, np.uint8)

        # # increment countmap where map image data exists
        # countmap += mapnonzero
        # # countmap = cv2.bitwise_and(countmap, mapnonzero)
        # countmap = np.clip(countmap, 0, 4)

        # bluemap = newbase
        # libimg.show(bluemap)



        # # # libimg.show(mapMask)
        # # mapMaskInv = 255-mapMask
        # # # libimg.show(mapMaskInv)

        # # bluemapSame = cv2.bitwise_and(bluemap, mapMaskInv)
        # # bluemapChange = cv2.bitwise_and(bluemap, mapMask)
        # # bluemapChange = cv2.addWeighted(bluemapChange, 0.5, map, 0.5, 0)
        # # # bluemapNew = cv2.bitwise_and(map, mapMask)

        # # bluemap = bluemapSame + bluemapChange
        # # # bluemap = bluemapSame + bluemapNew
        # # libimg.show(bluemap)


        # # bluemap = cv2.bitwise_and(bluemap, mapMaskInv)
        # # libimg.show(bluemap)
        # # bluemap = bluemap + map
        # # libimg.show(bluemap)


        # # if nfile>0:
        # # if nfile>3:
        # # if nfile>5:
        # if nfile>8:
        #     sys.exit(0)


    fPositions.close()
    fFiles.close()

    print
コード例 #32
0
    def __Geometry(self, boresight=''):

        #if self.geometry_flag is True and \
        #                self.time.window.all() == self.previous_tw.all():
        #    return

        distance = []
        altitude = []
        boresight_latitude = []
        boresight_longitude = []
        latitude = []
        longitude = []
        subpoint_xyz = []
        subpoint_pgc = []
        subpoint_pcc = []
        zaxis_target_angle = []
        myaxis_target_angle = []
        yaxis_target_angle = []
        xaxis_target_angle = []
        beta_angle = []

        qs, qx, qy, qz = [], [], [] ,[]
        x, y, z = [],[],[]


        tar = self.target
        time = self.time

        for et in time.window:

            try:
                #
                # Compute the distance
                #
                ptarg, lt = spiceypy.spkpos(tar.name, et, tar.frame, time.abcorr,
                                          self.name)
                x.append(ptarg[0])
                y.append(ptarg[1])
                z.append(ptarg[2])

                vout, vmag = spiceypy.unorm(ptarg)
                distance.append(vmag)


                #
                # Compute the geometric sub-observer point.
                #
                if tar.frame == 'MARSIAU':
                    tar_frame = 'IAU_MARS'
                else:
                    tar_frame = tar.frame
                spoint, trgepc, srfvec = spiceypy.subpnt(tar.method, tar.name, et,
                                                       tar_frame, time.abcorr,
                                                       self.name)
                subpoint_xyz.append(spoint)

                #
                # Compute the observer's altitude from SPOINT.
                #
                dist = spiceypy.vnorm(srfvec)
                altitude.append(dist)


                #
                # Convert the sub-observer point's rectangular coordinates to
                # planetographic longitude, latitude and altitude.
                #
                spglon, spglat, spgalt = spiceypy.recpgr(tar.name, spoint,
                                                       tar.radii_equ, tar.flat)

                #
                # Convert radians to degrees.
                #
                spglon *= spiceypy.dpr()
                spglat *= spiceypy.dpr()

                subpoint_pgc.append([spglon, spglat, spgalt])

                #
                #  Convert sub-observer point's rectangular coordinates to
                #  planetocentric radius, longitude, and latitude.
                #
                spcrad, spclon, spclat = spiceypy.reclat(spoint)


                #
                # Convert radians to degrees.
                #
                spclon *= spiceypy.dpr()
                spclat *= spiceypy.dpr()

                subpoint_pcc.append([spclon, spclat, spcrad])
                latitude.append(spclat) #TODO: Remove with list extraction
                longitude.append(spclon)  # TODO: Remove with list extraction

                #
                # Compute the geometric sub-boresight point.
                #
                if tar.frame == 'MARSIAU':
                    tar_frame = 'IAU_MARS'
                else:
                    tar_frame = tar.frame


                if boresight:
                    try:
                        id = spiceypy.bodn2c(boresight)
                        (shape,framen, bsight, n, bounds) = spiceypy.getfov(id, 80)
                        mat = spiceypy.pxform(framen,tar_frame,et)
                    except:
                        framen = boresight
                        bsight = 0,0,1
                else:
                    bsight = self.name

                try:
                    if tar.method == 'INTERCEPT/ELLIPSOID':
                        method = 'ELLIPSOID'
                    else:
                        method = tar.method
                    spoint, trgepc, srfvec = spiceypy.sincpt(method, tar.name, et,
                                                           tar_frame, time.abcorr,
                                                           self.name, framen,
                                                           bsight)

                    #
                    # Convert the sub-observer point's rectangular coordinates to
                    # planetographic longitude, latitude and altitude.
                    #
                    spglon, spglat, spgalt = spiceypy.recpgr(tar.name, spoint,
                                                           tar.radii_equ, tar.flat)

                    #
                    # Convert radians to degrees.
                    #
                    spglon *= spiceypy.dpr()
                    spglat *= spiceypy.dpr()


                    #
                    #  Convert sub-observer point's rectangular coordinates to
                    #  planetocentric radius, longitude, and latitude.
                    #
                    spcrad, spclon, spclat = spiceypy.reclat(spoint)


                    #
                    # Convert radians to degrees.
                    #
                    spclon *= spiceypy.dpr()
                    spclat *= spiceypy.dpr()

                    boresight_latitude.append(spclat)
                    boresight_longitude.append(spclon)

                except:
                    pass

                #
                # Compute the angle between the observer's S/C axis and the
                # geometric sub-observer point
                #
                obs_tar, ltime = spiceypy.spkpos(tar.name, et,
                                                       'J2000', time.abcorr,
                                                       self.name)
                obs_zaxis  = [0,  0, 1]
                obs_myaxis = [0, -1, 0]
                obs_yaxis = [0, 1, 0]
                obs_xaxis = [1, 0, 0]

                #
                # We need to account for when there is no CK attitude available.
                #
                try:
                    matrix = spiceypy.pxform(self.frame, 'J2000', et)

                    z_vecout = spiceypy.mxv(matrix, obs_zaxis)
                    zax_target_angle = spiceypy.vsep(z_vecout, obs_tar)
                    zax_target_angle *= spiceypy.dpr()
                    zaxis_target_angle.append(zax_target_angle)

                    my_vecout = spiceypy.mxv(matrix, obs_myaxis)
                    myax_target_angle = spiceypy.vsep(my_vecout, obs_tar)
                    myax_target_angle *= spiceypy.dpr()
                    myaxis_target_angle.append(myax_target_angle)

                    y_vecout = spiceypy.mxv(matrix, obs_myaxis)
                    yax_target_angle = spiceypy.vsep(y_vecout, obs_tar)
                    yax_target_angle *= spiceypy.dpr()
                    yaxis_target_angle.append(yax_target_angle)

                    x_vecout = spiceypy.mxv(matrix, obs_myaxis)
                    xax_target_angle = spiceypy.vsep(x_vecout, obs_tar)
                    xax_target_angle *= spiceypy.dpr()
                    xaxis_target_angle.append(xax_target_angle)


                    quat = spiceypy.m2q(spiceypy.invert(matrix))
                    qs.append(quat[0])
                    qx.append(-1*quat[1])
                    qy.append(-1*quat[2])
                    qz.append(-1*quat[3])

                except:
                    zaxis_target_angle.append(0.0)
                    myaxis_target_angle.append(0.0)
                    yaxis_target_angle.append(0.0)
                    xaxis_target_angle.append(0.0)
                    qs.append(0.0)
                    qx.append(0.0)
                    qy.append(0.0)
                    qz.append(0.0)

                beta_angle.append(spiops.beta_angle(self.name, self.target.name,
                                                    et))
            except:
                boresight_latitude = 0
                boresight_longitude = 0
                distance = 0
                altitude = 0
                latitude = 0
                longitude = 0
                subpoint_xyz = [0,0,0]
                subpoint_pgc =  [0,0,0]
                subpoint_pcc =  [0,0,0]
                zaxis_target_angle = 0
                myaxis_target_angle = 0
                yaxis_target_angle = 0
                xaxis_target_angle = 0
                beta_angle = 0
                (qx, qy, qz, qs) = 0, 0, 0, 0
                (x, y, z) = 0, 0, 0

        self.boresight_latitude = boresight_latitude
        self.boresight_longitude = boresight_longitude
        self.distance = distance
        self.altitude = altitude
        self.latitude = latitude
        self.longitude = longitude
        self.subpoint_xyz = subpoint_xyz
        self.subpoint_pgc = subpoint_pgc
        self.subpoint_pcc = subpoint_pcc
        self.zaxis_target_angle = zaxis_target_angle
        self.myaxis_target_angle = myaxis_target_angle
        self.yaxis_target_angle = yaxis_target_angle
        self.xaxis_target_angle = xaxis_target_angle
        self.beta_angle = beta_angle
        self.quaternions = [qx, qy, qz, qs]
        self.trajectory = [x,y,z]

        self.geometry_flag = True
        self.previous_tw = self.time.window

        return
コード例 #33
0
    def __init__(self, kernels_folder=None):
        """
		Parameters:
			kernels_folder (string): If not provided, the path stored in the environment
				variable ``TESSPHOT_SPICE_KERNELS`` is used, and if that is not set, the
				``data/spice`` directory is used.
		"""

        logger = logging.getLogger(__name__)

        # If no kernel folder is given, used the one stored in env.var. or the default location:
        if kernels_folder is None:
            kernels_folder = os.environ.get(
                'TESSPHOT_SPICE_KERNELS',
                os.path.join(os.path.dirname(__file__), 'data', 'spice'))

        # Make sure the kernel directory exists:
        kernels_folder = os.path.abspath(kernels_folder)
        os.makedirs(kernels_folder, exist_ok=True)

        # Automatically download kernels from TASOC, if they don't already exist?
        #urlbase = 'https://archive.stsci.edu/missions/tess/models/'
        urlbase = 'https://tasoc.dk/pipeline/spice/'
        downlist = []
        for fname in self.kernel_files:
            fpath = os.path.join(kernels_folder, fname)
            if not os.path.exists(fpath):
                downlist.append([urlbase + fname, fpath])

        if downlist:
            download_parallel(downlist)

        # Path where meta-kernel will be saved:
        hashkey = kernels_folder + ',' + ','.join(self.kernel_files)
        fileshash = hashlib.md5(hashkey.encode()).hexdigest()
        self.METAKERNEL = os.path.join(kernels_folder,
                                       'metakernel-' + fileshash + '.txt')

        # Write meta-kernel to file:
        if not os.path.exists(self.METAKERNEL):
            with open(self.METAKERNEL, 'w') as fid:
                fid.write("KPL/MK\n")
                fid.write(r"\begindata" + "\n")
                fid.write("PATH_VALUES = ('" + kernels_folder + "')\n")
                fid.write("PATH_SYMBOLS = ('KERNELS')\n")
                fid.write("KERNELS_TO_LOAD = (\n")
                fid.write(",\n".join([
                    "'$KERNELS/" + fname + "'" for fname in self.kernel_files
                ]))
                fid.write(")\n")
                fid.write(r"\begintext" + "\n")
                fid.write("End of MK file.\n")

        # Because SpiceyPy loads kernels into a global memory scope (BAAAAADDDD SpiceyPy!!!),
        # we first check if we have already loaded this into the global scope:
        # This is to attempt to avoid loading in the same kernels again and again when
        # running things in parallel.
        already_loaded = False
        for k in range(spiceypy.ktotal('META')):
            if os.path.abspath(spiceypy.kdata(k,
                                              'META')[0]) == self.METAKERNEL:
                logger.debug("SPICE Meta-kernel already loaded.")
                already_loaded = True
                break

        # Define TESS object if it doesn't already exist:
        try:
            spiceypy.bodn2c('TESS')
        except SpiceyError:
            logger.debug("Defining TESS name in SPICE")
            spiceypy.boddef('TESS', -95)

        # Load kernels if needed:
        if not already_loaded:
            logger.debug("Loading SPICE Meta-kernel: %s", self.METAKERNEL)
            spiceypy.furnsh(self.METAKERNEL)

        # Let's make sure astropy is using the de430 kernels as well:
        # Default is to use the same as is being used by SPOC (de430).
        # If using astropy 4.0+, we can load the local one directly. Before this,
        # it needs to be downloaded and cached:
        # NOTE: https://github.com/astropy/astropy/pull/8767
        if astropy_major_version >= 4:
            self.planetary_ephemeris = os.path.join(
                kernels_folder, 'tess2018338154429-41241_de430.bsp')
        else:
            self.planetary_ephemeris = urlbase + 'tess2018338154429-41241_de430.bsp'
        self._old_solar_system_ephemeris = coord.solar_system_ephemeris.get()
        coord.solar_system_ephemeris.set(self.planetary_ephemeris)
コード例 #34
0
ref = "J2000"
observer = "-143"  #observer
target = "SUN"

datetime_start = datetime(year=2018, month=4, day=21)
datetimes = [datetime_start + timedelta(days=x) for x in range(365 * 4)]

date_strs = [datetime.strftime(x, "%Y-%m-%d") for x in datetimes]
date_ets = [sp.str2et(x) for x in date_strs]
tgo_pos = np.asfarray([
    sp.spkpos(target, time, ref, abcorr, observer)[0]
    for time in list(date_ets)
])

tgo_dist = la.norm(tgo_pos, axis=1)
code = sp.bodn2c(target)
pradii = sp.bodvcd(code, 'RADII', 3)  # 10 = Sun
sun_radius = pradii[1][0]
sun_diameter_arcmins = np.arctan(sun_radius / tgo_dist) * sp.dpr() * 60.0 * 2.0

fig, ax = plt.subplots(figsize=(FIG_X, FIG_Y - 1))

ax.plot_date(datetimes, sun_diameter_arcmins, linestyle="-", ms=0)

ax.set_xlabel("Date")
ax.set_ylabel("Solar diameter as seen from TGO (arcminutes)")
ax.set_title("Apparent diameter of Sun since start of TGO mission")

ax.xaxis.set_major_locator(MonthLocator(bymonth=None, interval=6, tz=None))
fig.tight_layout()
if SAVE_FIGS:
コード例 #35
0
 def name(self, name):
     self._name = name
     try:
         self._id = spiceypy.bodn2c(name)
     except spiceytypes.SpiceyError:
         raise ValueError(f'Body name "{name}" not known by SPICE')
コード例 #36
0
 def _target_id(self):
     return spice.bodn2c(self.label['TARGET_NAME'])