Exemple #1
0
    def point_towards_sun(self, pixel_res=0.5):
        """
        Compute the solar azimuth.

        Pixel resolution is required to stay within one pixel of the origin
        point
        """
        # Check if surface point spoint was set
        if not self.spoint_set:
            raise SPointNotSetError
        # Get the difference vector poB=subsolar-origin with its tail at origin
        # and its head at the subsolar point
        poB = spice.vsub(self.subsolar, self.spoint)

        # get pixel scale in km/pixel and then divide by 2 to insure to stay
        # within a pixel of the origin point
        scale = (pixel_res / 1000.0) / 2.0

        # the difference vector cuts through the body,
        # we need the tangent vector
        # to the surface at the origin point. vperp receives the perpendicular
        # component of the poB towards the spoint vector
        hpoB = spice.vperp(poB, self.spoint)
        # unitize the tangent vector and then scale it to within a pixel of the
        # origin point
        upoB = spice.vhat(hpoB)
        spoB = spice.vscl(scale, upoB)

        # Compute the new point in body fixed. This point will be within a
        # pixel of the origin but in the same direction as the requested la/lon
        # of the point of interest, i.e. the subsolar point
        nB = spice.vadd(self.spoint, spoB)

        coords = Coords.fromtuple(spice.reclat(nB))
        return coords.dlon, coords.dlat
Exemple #2
0
    def point_towards_sun(self, pixel_res=0.5):
        """
        Compute the solar azimuth.

        Pixel resolution is required to stay within one pixel of the origin
        point
        """
        # Check if surface point spoint was set
        if not self.spoint_set:
            raise SPointNotSetError
        # Get the difference vector poB=subsolar-origin with its tail at origin
        # and its head at the subsolar point
        poB = spice.vsub(self.subsolar, self.spoint)

        # get pixel scale in km/pixel and then divide by 2 to insure to stay
        # within a pixel of the origin point
        scale = (pixel_res / 1000.0) / 2.0

        # the difference vector cuts through the body,
        # we need the tangent vector
        # to the surface at the origin point. vperp receives the perpendicular
        # component of the poB towards the spoint vector
        hpoB = spice.vperp(poB, self.spoint)
        # unitize the tangent vector and then scale it to within a pixel of the
        # origin point
        upoB = spice.vhat(hpoB)
        spoB = spice.vscl(scale, upoB)

        # Compute the new point in body fixed. This point will be within a
        # pixel of the origin but in the same direction as the requested la/lon
        # of the point of interest, i.e. the subsolar point
        nB = spice.vadd(self.spoint, spoB)

        coords = SurfaceCoords.fromtuple(spice.reclat(nB))
        return coords.dlon, coords.dlat
Exemple #3
0
def dooneRandom():
    ### Random normal unit vector
    unitNormal = sp.vhat([r.uniform(-1, 1) for i in xrange(3)])

    ### Random positive semi-axes' lengths
    semi_axes = [abs(r.uniform(.5, 100)) for i in xrange(3)]

    ### Solve for surface point with that surface normal
    xyz = norm2surfpt(semi_axes, unitNormal)

    ### Use spiceypy.surfnm() to calculate surface unit normal vector, at
    ### solved-for surface point vector xyz, to compare to input unit normal
    ### vector, and calculate error magnitude, errMag

    surfnm = sp.surfnm(semi_axes[0], semi_axes[1], semi_axes[2], xyz)
    errVec = sp.vsub(surfnm, unitNormal)
    errMag = sp.vnorm(errVec)

    if doLog:
        pprint.pprint(dict(errVec=errVec, errMag=errMag))

    ###return error magnitude
    return errMag
Exemple #4
0
                      mars2tgo)[3] * sp.dpr()
            for time, mars2tgo in zip(list(times), list(mars2tgo_pos))
        ])

        print("Calculating altitudes")
        #calculate tangent point altitude
        altitudes = np.asfarray([
            sp.npedln(mars_axes[0], mars_axes[1], mars_axes[2], line_point,
                      line_vector)[1] for line_point, line_vector in zip(
                          list(line_points), list(line_vectors))
        ])

        print("Checking if occultations real or not")
        #check that tgo is really behind mars as seen from sun: calculate angle between tgo-sun vector and tgo-mars centre vector
        sep_angles = np.asfarray([
            sp.vsep(sp.vsub(line_coord, line_point), line_vector)
            for line_coord, line_point, line_vector in zip(
                list(tangent_coords), list(line_points), list(line_vectors))
        ])
        #if angle greater than 90 then tgo is between mars and sun, not behind mars
        valid_occ_indices = np.asfarray([
            1 if sep_angle <= sp.halfpi() else 0
            for sep_angle in list(sep_angles)
        ])

        print("Removing invalid points")
        #calculate all valid tangent altitudes
        tangent_altitudes = np.asfarray([
            altitude if valid_occ == 1 else np.nan
            for altitude, valid_occ in zip(list(altitudes),
                                           list(valid_occ_indices))
                            "earth")[0]

### Use SPICE to calculate vector from earth to the the SSB-relative
### fixed star position with LT+S correction
earth2star_lts = sp.spkcpt(vstar, ssb, j2000, et, j2000, "observer", LTS,
                           "earth")[0]

if do_debug:
    ### Ensure that light-time correction is zero for earth->star vector
    ### for star at fixed positon relative to SSB
    earth2star_lt = sp.spkcpt(vstar, ssb, j2000, et, j2000, "observer", LT,
                              "earth")[0]
    assert 0.0 == sp.vnormg(sp.vsubg(earth2star_none, earth2star_lt, 6), 6)

### Calculate differences between gaiif_util.py and SPICE results ...
ab_vec_spice = sp.vsub(earth2star_lts[:3], earth2star_none[:3])
ab_vec_gaia = sp.vscl(range2star, sp.vsub(uvstar_ab, uvstar_noab))
ab_vec_diff = sp.vsub(ab_vec_spice, ab_vec_gaia)
ab_diff_frac = sp.vnorm(ab_vec_diff) / sp.vnorm(ab_vec_spice)

no_ab_diff = sp.vsep(uvstar_noab, sp.vhat(earth2star_none[:3]))
ab_diff = sp.vsep(uvstar_ab, sp.vhat(earth2star_lts[:3]))
ab_diff_frac = sp.vsep(uvstar_ab, sp.vhat(earth2star_lts[:3]))

try:
    ### ... Success
    assert 1e-15 > no_ab_diff
    assert 1e-8 > ab_diff
except:
    ### ... Failure
    print(
    degPerHour = 2.0 * dpr * twopi / hpd

    xTolerance = lambda xDiff: xDiff < 1e-10
    xDiffTolerance = lambda x, xExpect: xTolerance(abs(x - xExpect))

    et, iPass = et0, 0
    while et < (et0 + spd + 1):

        ### Get the state of the MINUTE and HOUR bodies every half hour
        stMinute, lt = sp.spkezr(sMinute, et, 'J2000', 'NONE', sClock)
        stHour, lt = sp.spkezr(sHour, et, 'J2000', 'NONE', sClock)

        if (iPass % 2):
            ### On the half hour, the minute hand will be at RA=180, along [-1,0,0]
            assert xTolerance(
                sp.vnorm(sp.vsub([-1.0, 0., 0.], sp.vhat(stMinute[:3]))))
        else:
            ### On the hour, the minute hand will be at RA=0, at [+1,0,0]
            assert xTolerance(
                sp.vnorm(sp.vsub([1.0, 0., 0.], sp.vhat(stMinute[:3]))))
            vsepDeg = dpr * sp.vsep(stHour[:3], stMinute[:3])
            vsepExpectDeg = (degPerHour * (iPass >> 1)) % 360
            ### On the hour, the houre hand will be (30 * iPass) degrees clockwise
            ### from +X, and therefor also the same from the minute hand
            assert xDiffTolerance(vsepDeg, vsepExpectDeg) or xDiffTolerance(
                (360 - vsepDeg), vsepExpectDeg)

        ### Step to next half hour and pass
        et += halfHour
        iPass += 1
Exemple #7
0
  def star_in_fov(self
                 ,vstar
                 ,parallax_maspau=None
                 ,pmra_maspy=None
                 ,pmdec_maspy=None
                 ):
    """Return True if the star (RA,Dec or xyz) argument is in the FOV

Argument vstar is either an RA,Dec pair (degrees) or a 3-vector

"""

    if self.fovtype == FOV.RADECBOXTYPE:
      ##################################################################
      ### Compare star vector to [RA,Dec] box
      ra,dec = parse_inertial(vstar,return_radec=True)[:2]
      for ralo,rahi,declo,dechi in self.radec_boxes:
        if ra<ralo: continue
        if ra>rahi: continue
        if dec<declo: continue
        if dec>dechi: continue
        return True,sp.radrec(1.,rpd*ra,rpd*dec)
      return False,None

    ### Get inertial star unit vector without RA,Dec
    uvinertial = uvraw = parse_inertial(vstar,return_radec=False)

    ### Corrections for direction to star
    ### - Assume all corrections are small and can be applied in units
    ###   of radians to a unit vector in a plane perpendicular to the
    ###   vector to the star

    ### - Proper Motion (PM)
    ###   - Uses PM in RA and Dec only, not radial velocity and parallax
    if (not (None is self.obs_year)
       ) and (not (None in (pmra_maspy,pmdec_maspy,))
       ) and (pmra_maspy != 0.0 or pmdec_maspy != 0.0):
      ### - Unit vectors E and N in plane perpendicular to star vector
      uveast = sp.ucrss([0,0,1],uvraw)
      uvnorth = sp.ucrss(uvraw,uveast)
      ### - Scale unit vectors in radians, and add to nominal vector
      ### - pmra_maspy from Gaia includes factor of secant(Declination)
      uvinertial = sp.vhat(sp.vlcom3(self.obs_year*rpmas*pmdec_maspy,uvnorth
                                    ,self.obs_year*rpmas*pmra_maspy,uveast
                                    ,1.0,uvinertial
                                    )
                          )

    ### - Parallax
    if (not (None is self.obs_pos)
       ) and (not (None is parallax_maspau)
       ) and (parallax_maspau != 0.0):
      ### - Scale observer position, by parallax in mas/AU, then scale
      ###   to radians (since star vector is unit vector), make that the
      ###   new origin of the vector
      uvinertial = sp.vhat(sp.vsub(uvinertial
                                  ,sp.vscl(aupkm*parallax_maspau*rpmas,self.obs_pos)
                                  )
                          )

    ### - Stellar Aberration
    if not (None is self.obs_vel):
      ### - Scale observer velocity by reciprocal of the speed of light,
      ###   add result to unit vector toward star.
      uvinertial = sp.vhat(sp.vadd(uvinertial
                                  ,sp.vscl(recip_clight,self.obs_vel)
                                  )
                          )

    if self.fovtype == FOV.CIRCLETYPE:
      ##################################################################
      ### Compare inertial star vector to circular FOV
      return sp.vdot(uvinertial,self.uv_cone_axis) >= self.min_cosine,uvinertial

    assert FOV.POLYGONTYPE == self.fovtype,'Unknown FOV type [{0}]'.format(self.fovtype)

    ####################################################################
    ### Compare star vector to polygonal FOV

    if self.is_convex():
      ### Convex FOV:  a negative dot product with the inward-pointing
      ###              normal to any side indicates star is outside FOV
      for inwardnorm in self.inwardsidenorms:
        if sp.vdot(uvinertial,inwardnorm) < 0.0: return False,uvinertial

      ### All dot products were non-negative:  star is within FOV
      return True,uvinertial

    ### Rotate inertial unit vector to local reference frame (reffrm)
    uvlocalstar = self.rotate_to_local(uvinertial)

    ### Scale to Z=unity
    if uvlocalstar[2] < 1e-15: return False,uvinertial
    z1star = sp.vscl(1.0/uvlocalstar[2],uvlocalstar)

    ### Setup .localxyzs and .fovsides
    if None is self.localxyzs: self.setup_localxyzs()

    ### Count number of crossings of FOV sides
    count = len([None
                 for fovside in self.fovsides
                 if fovside.right_of(z1star)
                ])

    return ((count&1) and True or False),uvinertial
Exemple #8
0
 def to_north(self):
     if not self.spoint_set:
         raise SPointNotSetError
     return spice.vsub(self.north_pole, self.spoint)
Exemple #9
0
 def sun_direction(self):
     if not self.spoint_set:
         raise SPointNotSetError
     return spice.vsub(self.center_to_sun.value, self.spoint)
Exemple #10
0
 def _get_to_south(self):
     if not self.spoint_set:
         raise SPointNotSetError
     return spice.vsub(self.south_pole, self.spoint)
Exemple #11
0
 def _get_sun_direction(self):
     if not self.spoint_set:
         raise SPointNotSetError
     return spice.vsub(self.center_to_sun, self.spoint)