コード例 #1
0
def lon_lat_r(body, time, earth_radius=6371e3):
    """
    Use SPICE software to get longitude and latitude of the point on Earth at
    which <body> is in zenith and the distance between the barycenters of Earth
    and <body> at a specified <time> (in UTC). We're pretending the earth is a
    sphere here, as is commonly done in tidal studies (and presumably is done in
    the ocean model this is fed into).

    Input:
      body         - SPICE name of the body (e.g. "SUN" or "MOON")
      time         - date and time in datetime format (UTC)
      earth_radius - radius of the earth (default 6371e3 m)
    Output:
      lon, lat     - longitude and latitude at which <body> is in zenith
      r            - range of the body (distance between barycenters)
    """

    # convert UTC time to ephemeris time
    time = spice.str2et(str(time) + " UTC")

    # get position in rectangular coordinate system (body frame of Earth)
    pos_rec, _ = spice.spkpos(body, time, "ITRF93", "NONE", "EARTH")

    # transform to geodetic coordinates assuming zero flatness (to get lat/lon)
    pos_geo = spice.recgeo(pos_rec, earth_radius / 1e3, 0)

    # transform to range, right ascension, declination (to get range)
    pos_rad = spice.recrad(pos_rec)

    # isolate coordinates we'll need (and convert from km to m)
    lon = pos_geo[0]
    lat = pos_geo[1]
    r = pos_rad[0] * 1e3

    return lon, lat, r
コード例 #2
0
def producegeometrylamda(et, sv, when):
    [TGO, _] = spice.spkpos(sv.front, et - when, sv.fframe, 'NONE', sv.target)
    [MEX, _] = spice.spkpos(sv.front, et - when, sv.fframe, 'NONE', sv.obs)

    dist = math.floor(spice.vdist(TGO, MEX))
    print(dist)
    # NEED TO PRODUCE VECTOR OF SZA AND HEIGHTS THAT ARE 'DIST' LONG [13242.9 m] *comp expensive
    # start by making DIST length vector, 3 height, for every meter from mex to tgo
    # MAYBE FIND THE UNIT VECTOR AND ADD ONE IN ITS DIRECTION!!
    angleseparation = (spice.vsep(MEX, TGO)) * (180 / math.pi
                                                )  # angle taken a mars center
    initialangle = (spice.vsep(-MEX, (TGO - MEX))) * (
        180 / math.pi
    )  # angle taken at mars-MEX-tgo, that points to tgo. needed for the bending functions original starting angle
    #script needs to work via periods of ray and not meters. [totalperiods is the main iterable, not meters]
    vacuumwavelength = constants.c / 437.1e6
    scale = 1  # scale =10, means we are itertating per 100 wavelenghts instead of 1000 (default 1000 because SPICE works in km)
    wavelengthsinameter = 1 / vacuumwavelength
    a = wavelengthsinameter * dist * scale
    total1000periods = math.floor(a)  # ~that many thousands of periods
    remainingdistance = (vacuumwavelength / scale) * (
        (wavelengthsinameter * dist * scale) - total1000periods
    )  # quanitfy the remaineder, this distance can
    # added later, this remaining portion is extreamly high altitude (near Target) and has no refractive effects. therfor simply added (km)
    #total1000periods = total1000periods.astype(int)

    sc2sc = TGO - MEX
    norm = np.linalg.norm(sc2sc)
    unitsc2sc = sc2sc / (norm * vacuumwavelength * scale
                         )  #this needs to shrink if the repeatable expands
    points = np.empty([3, total1000periods])
    sza = np.empty([1, total1000periods])

    marsrad = spice.bodvrd(sv.front, 'RADII', 3)
    flatteningcoefficient = (marsrad[1][0] - marsrad[1][2]) / marsrad[1][0]
    equatorialradii = marsrad[1][0]
    # find direction of sun, it will not change much during the occultation. so only calc it once
    [SUN, _] = spice.spkpos(sv.front, et, sv.fframe, 'NONE', 'SUN')
    for i in range(total1000periods):
        point = MEX + (
            i * unitsc2sc
        )  #move along ray, 1000 wavelength distance at a time (685 m). but unitsc2sc is in km...
        sza[0, i] = spice.vsep(SUN, point)
        points[:, i] = spice.recgeo(point, equatorialradii,
                                    flatteningcoefficient)
        points[0, i] = (points[0, i] * (-180 / math.pi))
        points[1, i] = (points[1, i] * (-180 / math.pi))

        print((i / math.floor(total1000periods)) * 100)

    ray = np.concatenate((points, sza), axis=0)
    print('stop here')

    return ray, dist, angleseparation, initialangle, total1000periods, vacuumwavelength, remainingdistance
コード例 #3
0
def producegeometrymeter(et, sv, when):
    [TGO, _] = spice.spkpos(sv.front, et - when, sv.fframe, 'NONE', sv.target)
    [MEX, _] = spice.spkpos(sv.front, et - when, sv.fframe, 'NONE', sv.obs)

    dist = math.floor(spice.vdist(TGO, MEX))
    print(dist)
    # NEED TO PRODUCE VECTOR OF SZA AND HEIGHTS THAT ARE 'DIST' LONG [13242.9 m] *comp expensive
    # start by making DIST length vector, 3 height, for every meter from mex to tgo
    # MAYBE FIND THE UNIT VECTOR AND ADD ONE IN ITS DIRECTION!!
    angleseparation = (spice.vsep(MEX, TGO))  # angle taken a mars center
    initialangle = (spice.vsep(-MEX, (TGO - MEX))) * (
        180 / math.pi
    )  # angle taken at mars-MEX-tgo, that points to tgo. needed for the bending functions original starting angle
    #script needs to work via periods of ray and not meters. [totalperiods is the main iterable, not meters]

    scale = 0.1  # scale =10, means we are itertating per 100 wavelenghts instead of 1000 (default 1000 because SPICE works in km)

    dist = math.floor(dist)  # km

    sc2sc = TGO - MEX
    norm = np.linalg.norm(sc2sc)
    unitsc2sc = sc2sc / norm  #this needs to shrink if the repeatable expands
    points = np.empty([3, dist])
    sza = np.empty([1, dist])
    angleprogression = np.empty([1, dist])

    xyzpoints = np.zeros([3, dist])
    marsrad = spice.bodvrd(sv.front, 'RADII', 3)
    flatteningcoefficient = (marsrad[1][0] - marsrad[1][2]) / marsrad[1][0]
    equatorialradii = marsrad[1][0]
    # find direction of sun, it will not change much during the occultation. so only calc it once
    [SUN, _] = spice.spkpos(sv.front, et, sv.fframe, 'NONE', 'SUN')
    for i in range(dist):
        xyzpoint = MEX + (
            i * unitsc2sc
        )  #move along ray, 1000 wavelength distance at a time (685 m). but unitsc2sc is in km...
        xyzpoints[:, i] = xyzpoint
        sza[0, i] = spice.vsep(SUN, xyzpoint)
        angleprogression[0, i] = (spice.vsep(xyzpoint, MEX)) * (180 / math.pi)
        points[:, i] = spice.recgeo(xyzpoint, equatorialradii,
                                    flatteningcoefficient)
        points[0, i] = (points[0, i] * (-180 / math.pi))
        points[1, i] = (points[1, i] * (-180 / math.pi))

        print((i / math.floor(dist)) * 100)

    ray = np.concatenate((points, sza), axis=0)

    #plt.plot(angleprogression[0,:], ray[2,:])
    #plt.show()

    # ray is in lat/lon/alt + sza and xyzpoints is cartesian, both describe the same thing
    return ray, dist, unitsc2sc, angleseparation, initialangle, MEX, TGO, xyzpoints, angleprogression
コード例 #4
0
def producegeometrymeter(et, sv, when):

    [TGO, _] = spice.spkpos(sv.front, et - when, sv.fframe, 'NONE', sv.target)
    [MEX, _] = spice.spkpos(sv.front, et - when, sv.fframe, 'NONE', sv.obs)

    dist = math.floor(spice.vdist(TGO, MEX))

    angleseparation = (spice.vsep(MEX, TGO))  # angle taken a mars center
    initialangle = (spice.vsep(-MEX, (TGO - MEX))) * (
        180 / math.pi
    )  # angle taken at mars-MEX-tgo, that points to tgo. needed for the bending functions original starting angle
    #script needs to work via periods of ray and not meters. [totalperiods is the main iterable, not meters]

    sc2sc = TGO - MEX
    norm = np.linalg.norm(sc2sc)
    unitsc2sc = sc2sc / norm  #this needs to shrink if the repeatable expands
    points = np.empty([3, dist])
    sza = np.empty([1, dist])
    angleprogression = np.empty([1, dist])

    xyzpoints = np.zeros([3, dist])
    marsrad = spice.bodvrd(sv.front, 'RADII', 3)
    flatteningcoefficient = (marsrad[1][0] - marsrad[1][2]) / marsrad[1][0]
    equatorialradii = marsrad[1][0]
    # find direction of sun, it will not change much during the occultation. so only calc it once
    [SUN, _] = spice.spkpos(sv.front, et, sv.fframe, 'NONE', 'SUN')
    for i in range(dist):
        xyzpoint = MEX + (
            i * unitsc2sc
        )  #move along ray, 1000 wavelength distance at a time (685 m). but unitsc2sc is in km...
        xyzpoints[:, i] = xyzpoint
        sza[0, i] = spice.vsep(SUN, xyzpoint)
        angleprogression[0, i] = (spice.vsep(xyzpoint, MEX)) * (180 / math.pi)
        points[:, i] = spice.recgeo(xyzpoint, equatorialradii,
                                    flatteningcoefficient)
        points[0, i] = (points[0, i] * (-180 / math.pi))
        points[1, i] = (points[1, i] * (-180 / math.pi))

    ray = np.concatenate((points, sza),
                         axis=0)  # important for when sza is included

    #plt.plot(angleprogression[0,:], ray[2,:])
    #plt.show()

    # ray is in lat/lon/alt + sza and xyzpoints is cartesian, both describe the same thing
    return initialangle, MEX, TGO, xyzpoints
コード例 #5
0
def lon_lat_r(body, time):

    """
    Use SPICE software to get

      - longitude and latitude of <body>'s subsolar point, or the 
        coordinates at which <body> is in zenith (or point 'Q' in 
        Munk and Cartwright 1966's figure 13), and

      - the distance between the barycenters of Earth and <body>
        at a specified <time> (in UTC).

    The input <body> is a string like "SUN" or "MOON", and <time>
    is a datestring with format 'yyyy-mm-dd hh:mm:ss'
    """

    # The equivalent spherical radius of earth.
    earth_radius = 6371e3

    # Convert UTC time to ephemeris time in seconds past J2000 TDB.
    time = spice.str2et(str(time) + " UTC")

    # Get the position in km in a rectangular coordinate system whose
    # origin lies at the center of "EARTH", with no time-correction.
    pos_rec, _ = spice.spkpos(body, time, "ITRF93", "NONE", "EARTH")

    # Calculate the lat, lon position on an unflattened sphere with 
    # Earth's average radius on a line passing from pos_rec
    # to (0, 0, 0) (which is the Earth's center).
    flatten_coeff = 0
    pos_geo = spice.recgeo(pos_rec, earth_radius/1e3, flatten_coeff)

    # Transform pos_rec to range (in km), right ascension, declination.
    # The 'range' is the 'r' we seek: the distance between the center 
    # of the body and the center of the Earth.
    pos_rad = spice.recrad(pos_rec)

    # Isolate coordinates we'll need and convert range from km to m
    lon = pos_geo[0]
    lat = pos_geo[1]
    r = pos_rad[0]*1e3

    return lon, lat, r
コード例 #6
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
コード例 #7
0
def flatbending(xyzpoints, initialangle, MEX, TGO, referencedirection):
    class SpiceVariables:
        obs = '-74'  # NAIF code for MEX
        target = 'MARS ODYSSEY'  # NAIF code for TGO ['EARTH'/'SUN'/ a groundstation etc]
        obsfrm = 'IAU_MARS'
        abcorr = 'NONE'
        crdsys = 'LATITUDINAL'
        coord = 'LATITUDE'
        stepsz = 100.0  # Check every 300 seconds if there is an occultation
        MAXILV = 100000  #Max number of occultations that can be returned by gfoclt
        bshape = 'POINT'
        fshape = 'DSK/UNPRIORITIZED'
        front = 'MARS'
        fframe = 'IAU_MARS'
        TFMT = 'YYYY-MM-DD HR:MN:SC'  # Format that Cosmographia understands

    sv = SpiceVariables()

    #form a coordinate system where tgo is @ y=0 and x= (5000 +norm), Mar's Barrycenter being @ [5000,0]
    subgroupsize = 1
    #initialise non-global variables
    miniray = np.zeros(subgroupsize)
    raystep = np.zeros(
        (2,
         100000000))  # create a large array to populate and then shrink later

    barry2mex = np.linalg.norm(MEX)
    barry2tgo = np.linalg.norm(TGO)

    #find the martian geomoerty so you can reliably find the altitude of a point
    marsrad = spice.bodvrd(sv.front, 'RADII', 3)
    flatteningcoefficient = (marsrad[1][0] - marsrad[1][2]) / marsrad[1][0]
    equatorialradii = marsrad[1][0]

    TGO = TGO + 0
    MEX = MEX + 0  #force to be non-strided
    _, _, MEXalt = spice.recgeo(MEX, equatorialradii, flatteningcoefficient)
    _, _, TGOalt = spice.recgeo(TGO, equatorialradii, flatteningcoefficient)

    #the possition of MEX is found by assuming that it will be somewhere over the relative horizon from TGO
    # (meaning over θ = 90°), finding the angle between the MEX and TGO's negative vector, will give the coords of MEX
    MexRelativeElevation = spice.vsep(-TGO, MEX)  #radians
    mex_y = barry2mex * np.sin(MexRelativeElevation)
    mex_x = barry2mex * np.cos(MexRelativeElevation)

    mex = np.array([0 - mex_x, mex_y])
    tgo = np.array([0 + barry2tgo, 0])
    barry = np.array([0, 0])

    #to plot the non-refracted propogation, we must convert the 3d xyzpoints to 2d, we do this the same way we found the x&y for MEX
    # ,using the norm distance and sep from -TGO5
    length = np.size(xyzpoints, 1)
    UnrefractedDistance = np.linalg.norm(xyzpoints[:, 0] -
                                         xyzpoints[:, -1])  #in km
    UnrefractedRay = np.zeros([2, length])
    for i in range(length):  #conversion to 2D
        point = xyzpoints[:,
                          i] + 0  #need to put vector into temp variable as spice cant handle strided array inputs
        angle = spice.vsep(-TGO, point)
        norm = np.linalg.norm(point)
        point_x = norm * np.cos(angle)
        point_y = norm * np.sin(angle)
        UnrefractedRay[0, i] = 0 - point_x
        UnrefractedRay[1, i] = point_y

    #this will produce and angle that is likly not going to be exactly on
    #the original propagation path, you compare to this if there is a drifting error, as both this and the resultant refracted ray
    # have the same bias error. THIS ANGLE IS BENDING ANTICLOCKWISE IN THIS FRAME (BENDING UPWARDS)
    initialtheta = -(spice.vsep(MEX - TGO, MEX))
    nicetohave = np.degrees(initialtheta)

    #THIS NEEDS TO VARY IF THERE IS AN OVERSHOOT
    unit = 1  # in km
    unitoriginal = unit

    rotationvector = np.array(((np.cos(initialtheta), -np.sin(initialtheta)),
                               (np.sin(initialtheta), np.cos(initialtheta))))

    #get unit vecotr of -MEX (then add this vecotr to MEX for each alt calcultation)
    unitmex = -mex / barry2mex  #unit direction (2d)

    if referencedirection == [0, 0, 0]:
        initialdirection = unitmex.dot(
            rotationvector
        ) * unit  #make a 2d vector coming from MEX YOU DO NOT KNOW WHAT WAY THIS IS ROTATING
    else:  # if there is a value for the fed-back starting direction than use this as the first firection
        initialdirection = referencedirection

    iterationcount = 0
    #while iterationcount<100:
    #print( "Finding Bending Angle (", str(iterationcount) ,"% Complete)")
    errorstore = np.zeros((11, 100000))
    S = np.zeros(20000)

    #IF REFERCEDRECTION==0 DO NORMAL, IF /= INCLUDE THIS AS THE FIRST DIRECTION.

    while iterationcount < 10:
        tic = timer.perf_counter()

        if iterationcount == 0:
            direction = initialdirection

        else:

            missangle = missangle / 1

            missrotationvector = np.array(
                ((np.cos(missangle), -np.sin(missangle)), (np.sin(missangle),
                                                           np.cos(missangle))))

            direction = initialdirection.dot(missrotationvector)
            #check the differecne between the initial and the direction, see if the same for both
            CHECK_ME = direction - initialdirection
            initialdirection = direction

        turningcounter = 0
        stage = 0
        t = 0
        unit = unitoriginal
        #with tqdm(total = mex[1], desc = "Progress", leave=False) as pbar:
        while stage < 2:  #==0first unit, so move two units. ==1 propergate step by step. ==2 exit and analyse entire path
            #take the alt at 10 possitions across this unit

            #lets get a quick calculated for the magnitude of the direction
            MAAAAG = np.linalg.norm(direction)  # this should = unit

            if stage == 0:
                for k in range(subgroupsize):  #this starts with 0
                    point = mex + ((k + 1) * (direction / subgroupsize))
                    #_,_,miniray[k] = spice.recgeo(point, equatorialradii,flatteningcoefficient)
                    miniray[k] = np.linalg.norm(
                        point) - 3389  #average radii of mars

                N0 = findrefractivity(miniray, subgroupsize)
                raystep[:, t] = point  #save the last location
                t = t + 1
                stage = stage + 1

            if stage == 1:
                for k in range(subgroupsize):
                    point = raystep[:, t - 1] + (
                        (k + 1) * (direction / subgroupsize)
                    )  #am i double counting the end of the last and the start of the next?
                    #_,_,miniray[k] = spice.recgeo(point, equatorialradii,flatteningcoefficient)  #THIS ONLY WORKS IN 3D
                    # IMPLEMENTING MARS AS A SIMPLE CIRCLE OF AVERAGE 3389 KM RADIUS, !THIS WILL BE UPDATED TO ELLIPSE!
                    miniray[k] = np.linalg.norm(point) - 3389

                raystep[:,
                        t] = point  #9 is the end of the unit, and refraction always happens relative to the center of refractivity, so rotate off this vector
                N1 = findrefractivity(miniray, subgroupsize)

                #IF THE Y VALUE DROPS BELOW 0, LOOP BACK WITH A STEP SIZE OF 1/10TH#################################################################<- HERE
                if point[1] < 0:  #if the position drops below the x axis
                    direction = direction / 10  #drop the step size
                    unit = unit / 10
                    #stage = stage+1

                    #MAYBE SHRINK THE DIRECTION INSTEAD OF THE UNIT, IT DOESNT GET REINITIALED IN THIS WHILE LOOP
                    # t is not incrememented so that it can loop back to the last position
                    # , t-1 is the position just before crossing over into negative space
                    if abs(point[1]) < 0.00001:  # is it smaller than cm
                        stage = stage + 1  #increase the stage value so the while loop is exited
                    continue

                    # #this section allows for better timing of the function, increment the progresbar by 1 if the current
                    # #position goes one y-value lower
                    # currenty = raystep[1,t]
                    # progress[1] = mex[1] - currenty #this value will be increasing from 0 -> Mex height
                    # increment = np.floor(progress[1])- np.floor(progress[0]) #only when
                    # if increment ==1 :
                    #     pbar.update(1)
                    # progress[0] = progress[1]

                if abs(N1) < 1e-20:  #catch for precision errors
                    S[t] = unit - (
                        N1 * unit
                    )  # whilst neglegible N, Electric distance is can simply be inversly proportional to N
                    t = t + 1
                    N0 = N1
                    continue

                #THE SECTION BELOW IS ONLY ACCESSED WHEN THE REFRACTIVTY IS ABOVE E-20
                #print('Current Y possition is', currenty) #this is alt, so is ~3389 km smaller than the vector
                r = N0 / N1  #NEED MORE PRECISION
                numorator = N0 + 1
                denominator = N1 + 1
                rbending = numorator / denominator  #average would just add 1 to total N
                # if t==5000: #only bend when there is a refractive gradient between consecutive air volumes[NO CHANGE IN DIRECTION]
                #     t=t+1
                #     N0=N1
                #     continue

                #this section is only reached if a turning is going to happen
                # ,testing to see if there is 10 X less turing if the units are 10X smaller -TRUE
                TEST = float(rbending)
                if TEST != 1:
                    turningcounter = turningcounter + 1

                # !! NOW WITH PRECISION !!

                #find the angle between the unit (air volume) boarder and the current direction
                unitrotationaxis = raystep[:, t] / (
                    (np.linalg.norm(raystep[:, t])) * unit)
                #unitdirection = direction #MAYBE ALTERING UNITS WILL EFFECT THIS * OR / BY UNIT, CANT FIGURE OUT NOW, OK WHEN UNIT =1
                DotProduct = np.dot((unitrotationaxis), direction)
                AngleofIncidence = (math.pi / 2) - np.arccos(
                    DotProduct)  #angle it enters the next air volume
                #simple snell law to find the bending angle (should be tiny angle)
                AngleofRefraction = np.arcsin(rbending *
                                              np.sin(AngleofIncidence))
                # THIS IS NOT EXACTLY WHAT THE TURN IN DIRECTION IS, NEED TO THINK ABOUT
                rotateby = ((AngleofIncidence - AngleofRefraction)
                            )  #+ve =clockwise, -ve=anticlockwise

                INCIDENCEDEGREES = np.degrees(AngleofIncidence)
                REFRACTIONDEGREES = np.degrees(AngleofRefraction)
                ROTATIONDEGREES = np.degrees(rotateby)

                #an if statement is required, if this
                if ROTATIONDEGREES > 1 or ROTATIONDEGREES < -1:
                    print('stophere, u r bending to much')
                rotationvector = np.array(
                    ((np.cos(rotateby), -np.sin(rotateby)),
                     (np.sin(rotateby), np.cos(rotateby))))
                direction = direction.dot(rotationvector)

                N0 = N1

                #store N1 to calc electric distance
                S[t] = unit - (N1 * unit)
                t = t + 1

            #pbar.refresh()

        unit_initial = initialdirection / np.linalg.norm(initialdirection)
        dot_product = np.dot(unit_initial, unitmex)
        FinalBendingAngle = np.arccos(dot_product)

        error = np.zeros(t)
        #print("Number of turns:", turningcounter)
        #error = swiftmain.finderror(raystep, UnrefractedRay) # also find the y-overshoot here

        miss = error  # 1D along the abscissa

        #update for the miss angle, going to include miss in the ordinate
        #START EDITING HERE
        miss = point[0] - UnrefractedRay[0, -1]  # X domain

        deltaX = UnrefractedRay[0, -1]  #TGO X value
        deltaY = UnrefractedRay[
            1,
            0]  # this is the height of the whole 2d scene (both refract and unrefacted have the same height)
        unrefractedangle = np.arctan(deltaX / deltaY)
        refractedangle = np.arctan((deltaX + miss) / deltaY)
        missangle = refractedangle - unrefractedangle  # if positive, then rotate clockwise
        #missangle = (np.arcsin(miss/UnrefractedDistance)) # this shouldnt work
        toc = timer.perf_counter()
        passingtime = toc - tic
        #print('miss =', format(miss*1000, '.5f') ,'m || Angle =', np.degrees(missangle) ,
        #                    '° || Speed =',passingtime,' Sec \n', sep = " ", end= " ", flush =True)

        if abs(miss) < 1e-4:  #is the miss smaller than 10 cm?
            #ploterrortraces(errorstore,t)
            break

        iterationcount = iterationcount + 1

    #find the total bending angle at MEX for this final configuration

    #from the refractive profile from MEX ->TGO, calc the intergral of the change in wavelength to aquire doppler
    S = S[S != 0]
    ElectricDistance = (
        np.sum(S)
    )  #N * wavelengths in a km (UNITS MUST BE KEPT THE SAME AS STEP-SIZE)[+ OVERSHOT BECAUSE IT IS A NEGATIVE VARIABLE ]

    return FinalBendingAngle, ElectricDistance, initialdirection  #feedback the starting vector for speed
コード例 #8
0
def producegeometrymeter(MEX, TGO):
    #maybe completly thin this out, you know this is moslty pointless, what does it actually make

    class SpiceVariables:
        obs = '-41'  # NAIF code for MEX '-74'
        target = '-143'  # NAIF code for TGO ['EARTH'/'SUN'/ a groundstation etc] 'MARS ODYSSEY'
        obsfrm = 'IAU_MARS'
        abcorr = 'NONE'
        crdsys = 'LATITUDINAL'
        coord = 'LATITUDE'
        stepsz = 1.0  # Check every [300] seconds if there is an occultation
        MAXILV = 100000  #Max number of occultations that can be returned by gfoclt
        bshape = 'POINT'
        fshape = 'DSK/UNPRIORITIZED'
        front = 'MARS'
        fframe = 'IAU_MARS'
        TFMT = 'YYYY-MM-DD HR:MN:SC'  # Format that Cosmographia understands

    sv = SpiceVariables()

    #THIS COULD BE REMOVED
    # [TGO, _] = spice.spkpos(sv.front, et-when, sv.fframe, 'NONE', sv.target)
    # [MEX, _] = spice.spkpos(sv.front, et-when, sv.fframe, 'NONE', sv.obs)
    TGO = TGO + 0
    MEX = MEX + 0  #force to be non-strided
    dist = math.floor(spice.vdist(TGO, MEX))

    angleseparation = (spice.vsep(MEX, TGO))  # angle taken a mars center
    initialangle = (spice.vsep(-MEX, (TGO - MEX))) * (
        180 / math.pi
    )  # angle taken at mars-MEX-tgo, that points to tgo. needed for the bending functions original starting angle
    #script needs to work via periods of ray and not meters. [totalperiods is the main iterable, not meters]

    sc2sc = TGO - MEX
    norm = np.linalg.norm(sc2sc)
    unitsc2sc = sc2sc / norm  #this needs to shrink if the repeatable expands
    points = np.empty([3, dist])
    sza = np.empty([1, dist])
    angleprogression = np.empty([1, dist])

    xyzpoints = np.zeros([3, dist])
    marsrad = spice.bodvrd(sv.front, 'RADII', 3)
    flatteningcoefficient = (marsrad[1][0] - marsrad[1][2]) / marsrad[1][0]
    equatorialradii = marsrad[1][0]
    # find direction of sun, it will not change much during the occultation. so only calc it once
    #[SUN, _] = spice.spkpos(sv.front, et, sv.fframe, 'NONE', 'SUN')
    for i in range(dist):
        xyzpoint = MEX + (
            i * unitsc2sc
        )  #move along ray, 1000 wavelength distance at a time (685 m). but unitsc2sc is in km...
        xyzpoints[:, i] = xyzpoint
        #sza[0,i] = spice.vsep(SUN,xyzpoint)
        angleprogression[0, i] = (spice.vsep(xyzpoint, MEX)) * (180 / math.pi)
        points[:, i] = spice.recgeo(xyzpoint, equatorialradii,
                                    flatteningcoefficient)
        points[0, i] = (points[0, i] * (-180 / math.pi))
        points[1, i] = (points[1, i] * (-180 / math.pi))

    # ray = np.concatenate((points,sza), axis=0) # important for when sza is included

    #plt.plot(angleprogression[0,:], ray[2,:])
    #plt.show()

    # ray is in lat/lon/alt + sza and xyzpoints is cartesian, both describe the same thing
    return initialangle, xyzpoints
コード例 #9
0
def straight(ray, initialdirection, MEX, angleseparation, angleprogression,
             initialangle, xyzpoints, sv, interval):
    alt = ray[2, :]

    rawvector = xyzpoints[:, len(xyzpoints) - 1] - xyzpoints[:, 0]
    norm = np.linalg.norm(rawvector)
    rayunit = rawvector / norm
    interval = 1

    marsrad = spice.bodvrd(sv.front, 'RADII', 3)
    flatteningcoefficient = (marsrad[1][0] - marsrad[1][2]) / marsrad[1][0]
    equatorialradii = marsrad[1][0]
    direction = initialdirection
    # everything must have a alt/ equiv dtheta
    poss = np.zeros([3, 10000])
    dtheta = np.zeros([1, 10000])
    possalt = np.zeros([1, 10000])
    poss[:, 0] = MEX
    step = 10  # this will scale down to 0.001 (1m)

    miniray = np.zeros([3, step])
    totalarcdistance = math.floor(alt[1] * angleseparation)  # in km
    angleseparation = angleseparation * (180 / math.pi
                                         )  #we want in degrees now
    #NOTE TO SELF, AT FIRST THE DIFFERNCE IN N MIGHT BE TO SMALL IN THE HIGH ALT. MAYBE JUMP TO WHERE THE IONO BEGINS THEN START THIS LOOP

    for p in range(
            100000 //
            step):  #10,000 is the max distance, this will never be reached
        if p == 0:  #You need a before n and after n so for the begining go forwards two to get a n0 and n1
            point = poss[:,
                         0] + 0  # regeo needs non-strided arrays, this achieved by adding 0 (cheat)
            _, _, possalt[0, p] = spice.recgeo(point, equatorialradii,
                                               flatteningcoefficient)
            dtheta[0, p] = (spice.vsep(point, MEX)) * (
                180 / math.pi)  #should give 0 degrees
            for i in range(step):
                point = poss[:, 0] + (interval * i * direction
                                      )  #make a small 'step' long 3d vector
                miniray[:, i] = spice.recgeo(
                    point, equatorialradii,
                    flatteningcoefficient)  #(lon; lat; alt)
            n0 = findrefractivity(miniray, step)

        else:
            n0 = n1

        for i in range(step):
            point = poss[:, p] + (interval * i * direction
                                  )  #make a small 'step' long 3d vector
            miniray[:, i] = spice.recgeo(point, equatorialradii,
                                         flatteningcoefficient)
        n1 = findrefractivity(miniray, step)

        #VECTOR CLACS [dont understand inuitivly, boiler plate] maybe this breaks if no r
        #SHOULD HIT THE IONO AT P=332, THIS MAKES SENSE
        r = n0 / n1

        nextposs = poss[:, p] + (
            interval * step * direction
        )  #move along this arc for 1km  then recalc your position
        poss[:, p +
             1] = nextposs  #vsep doesnt allow strided arrays, so make a temp variable
        _, _, possalt[0, p + 1] = spice.recgeo(nextposs, equatorialradii,
                                               flatteningcoefficient)
        #need to have a catch for when the dtheta has been satisfied
        dtheta[0, p + 1] = (spice.vsep(nextposs, MEX)) * (180 / math.pi)
        if dtheta[0, p] > angleseparation:
            break

    #shorten the arrays to just contain the non-zeros values
    dtheta = dtheta[dtheta != 0]

    possalt = possalt[possalt != 0]
    straighterrors = np.zeros([1, p])

    #ALT AND ANGLE PROGRESSION HAVE THE SAME LENGTH
    t = 0
    alteration = alt[0] - possalt[0]
    for i in range(np.size(angleprogression, 1)):  #up tp 6478
        if t == 93:
            print('stophere')

        if angleprogression[0, i] > dtheta[t] and t < p:
            if t == 0:
                alteration = possalt[t] - alt[i]

            straightrayalt = alt[i]
            bendalt = possalt[t]
            error = straightrayalt - bendalt + alteration
            straighterrors[0, t] = error
            t = t + 1
        else:
            continue

    return straighterrors
コード例 #10
0
def bending(ray, initialdirection, MEX, angleseparation, angleprogression,
            initialangle, xyzpoints, sv):
    alt = ray[2, :]

    #THIS IS AN ATMOSPHERE TEST
    # ionoresidual = atmosphere.iono(ray,np.size(ray,1))
    # neutralresidual = atmosphere.neutral(ray,np.size(ray,1))
    # residual = 1 + (ionoresidual + neutralresidual)

    # plt.plot(angleprogression[0,:],residual[0,:])
    # plt.title("Refractive Index through Propergation of Ray")
    # plt.xlabel("MEX -> Possition angle (degrees)")
    # plt.ylabel("Refractive Index")
    # plt.show()

    rawvector = xyzpoints[:, np.size(xyzpoints, 1) - 1] - xyzpoints[:, 0]
    norm = np.linalg.norm(rawvector)
    rayunit = rawvector / norm  # THIS IS SLIGHTLY DIFFERENT TO THE RAY, THERE ARE PYTHON ROUNDING ERRORS

    marsrad = spice.bodvrd(sv.front, 'RADII', 3)
    flatteningcoefficient = (marsrad[1][0] - marsrad[1][2]) / marsrad[1][0]
    equatorialradii = marsrad[1][0]
    direction = rayunit
    # everything must have a alt/ equiv dtheta
    poss = np.zeros([3, 100000])
    straightray = np.zeros([3, 100000])
    poss[:, 0] = MEX
    straightray[:, 0] = MEX
    iterationmax = 0
    miss = 0
    glitchcount = 0
    totalarcdistance = math.floor(alt[1] * angleseparation)  # in km
    angleseparation = angleseparation * (180 / math.pi
                                         )  #we want in degrees now
    #NOTE TO SELF, AT FIRST THE DIFFERNCE IN N MIGHT BE TO SMALL IN THE HIGH ALT. MAYBE JUMP TO WHERE THE IONO BEGINS THEN START THIS LOOP

    while iterationmax <= 100:
        dtheta = np.zeros(
            100000
        )  # must be re-initialised as the vectors are filtered for 0 towards the end of this loop
        possalt = np.zeros(100000)
        straightpossalt = np.zeros(100000)
        #alter initial angle slightly according to miss
        #if miss ~0 dont alter angle, if miss +ve then bend down, (you will likely be bending up initially due to tropo)

        if miss == 0:
            print('.')  # continue will make a 10-line loop with while
        else:
            angle = np.radians(miss *
                               0.03)  # a miss of one km (0.3km = 2 degrees )
            #alter the initail starting angle
            unitposs = MEX / np.linalg.norm(
                MEX)  #vector going upwards radially if n0>n1
            unitdirection = initialdirection / np.linalg.norm(initialdirection)
            rotationaxis = np.cross(
                unitposs, unitdirection
            )  #if direction is going rightwards, this rotation vector is going away from the viewer
            rotationvector = rotationaxis * angle  #must be in degrees
            rotation = R.from_rotvec(rotationvector)
            direction = rotation.apply(
                initialdirection
            )  # produce the slightly re-angled new direction (tiny difference)

        step = 10  # this will scale down to 0.001 (1m)
        interval = 1
        miniray = np.zeros([3, 10])
        constantdirection = direction
        for p in range(
                100000 //
                step):  #10,000 is the max distance, this will never be reached
            if p == 0:  #You need a before n and after n so for the begining go forwards two to get a n0 and n1
                point = poss[:,
                             0] + 0  # regeo needs non-strided arrays, this achieved by adding 0 (cheat)
                _, _, possalt[p] = spice.recgeo(point, equatorialradii,
                                                flatteningcoefficient)
                dtheta[p] = (spice.vsep(point, MEX)) * (
                    180 / math.pi)  #should give 0 degrees

                for i in range(step):
                    point = poss[:,
                                 0] + (interval * i * direction
                                       )  #make a small 'step' long 3d vector
                    miniray[:, i] = spice.recgeo(
                        point, equatorialradii,
                        flatteningcoefficient)  #(lon; lat; alt)
                n0 = findrefractivity(miniray, step)

            elif p == 477:
                print('inspect from here')

            else:
                n0 = n1

            for i in range(step):
                point = poss[:, p] + (interval * i * direction
                                      )  #make a small 'step' long 3d vector
                miniray[:, i] = spice.recgeo(point, equatorialradii,
                                             flatteningcoefficient)
            n1 = findrefractivity(miniray, step)

            #VECTOR CLACS [dont understand inuitivly, boiler plate] maybe this breaks if no r
            #SHOULD HIT THE IONO AT P=332, THIS MAKES SENSE
            r = n0 / n1
            if r > 2 or r < 0.5:
                print('stop here cause neutral is causing huge bending')

            direction, hasglitched = newdirection(poss[:, p], direction, r, p)

            if hasglitched == 1:
                glitchcount = glitchcount + 1

            nextposs = poss[:, p] + (
                interval * step * direction
            )  #move along this arc for 1km  then recalc your position
            nextstraightposs = straightray[:, p] + +(interval * step *
                                                     constantdirection)
            straightray[:, p + 1] = nextstraightposs
            poss[:, p +
                 1] = nextposs  #vsep doesnt allow strided arrays, so make a temp variable
            _, _, possalt[p + 1] = spice.recgeo(nextposs, equatorialradii,
                                                flatteningcoefficient)
            _, _, straightpossalt[p + 1] = spice.recgeo(
                nextstraightposs, equatorialradii, flatteningcoefficient)

            #need to have a catch for when the dtheta has been satisfied
            dtheta[p + 1] = (spice.vsep(nextposs, MEX)) * (180 / math.pi)
            if dtheta[p] > angleseparation:
                break

        #shorten the arrays to just contain the non-zeros values
        dtheta = dtheta[dtheta != 0]

        possalt = possalt[possalt != 0]
        straightpossalt = straightpossalt[straightpossalt != 0]
        errors = np.zeros([1, p])
        straighterrors2 = np.zeros([1, p])
        straightrayalt = np.zeros([1, p])

        #ALT AND ANGLE PROGRESSION HAVE THE SAME LENGTH
        t = 0
        alteration = alt[0] - possalt[0]
        for i in range(np.size(angleprogression, 1)):

            if angleprogression[0, i] > dtheta[t] and t < p:
                if t == 0:
                    alteration = possalt[t] - alt[i]
                    straightalteration = straightpossalt[t] - alt[i]

                straightrayalt[0, t] = alt[i]

                bendalt = possalt[t]
                iteratedstraightrayalt = straightpossalt[t]
                error = straightrayalt[0, t] - bendalt + alteration
                straighterrors2[0, t] = straightrayalt[
                    0, t] - iteratedstraightrayalt + straightalteration
                errors[0, t] = error
                t = t + 1

            else:
                continue

        straighterrors = straight(ray, direction, MEX, angleseparation,
                                  angleprogression, initialangle, xyzpoints,
                                  sv, interval)
        #if straighterrors2 == straighterrors, we can skip this

        straightcut = straighterrors[0, 0:p]
        #errors = errors[0]
        refractedcut = errors[0]
        # there is a glitch when the altitude becomes negative due to the spheriod not being considered. This is a patch to
        # remove the point of inflexion. Further inspection shows that glitches occured in low altitude and not negative altidue, the expnential
        # decay shape of the neutral refractivity profile led to small changes in alt, leading to huge changes in N, thus the refractive
        #  ratio can exceed two and the ray can bend extreamly, veering it of the straight ray and into the martian core, meaning it never touches the 2nd ionsphere

        #This shouldnt be required once a good starting angle is found, only required for graphing early ray propogations (rays with the largest misses)
        # for i in range(p-1): #
        #     if straightcut[i+1] < straightcut[i]:#inflexion
        #         straightcut[i+1] = straightcut[i] + (straightcut[i]-straightcut[i-1])
        #     if refractedcut[i+1] < refractedcut[i]:#inflexion
        #         refractedcut[i+1] = refractedcut[i] + (refractedcut[i]-refractedcut[i-1])

        results = straightcut - refractedcut
        dtheta = dtheta[0:-2]
        results = results[:-1]

        miss = results[
            -3]  #take the last results, this is how many km away the ray is when dtheta is satisfied

        ploterrorvariation(dtheta[0:-2], results[0:-2], straightrayalt)

        iterationmax = iterationmax + 1
コード例 #11
0
def cartesianbending(xyzpoints, initialangle, sv, MEX, TGO):
    #form a coordinate system where tgo is @ y=0 and x= (5000 +norm), Mar's Barrycenter being @ [5000,0]

    #initialise non-global variables
    miniray = np.zeros(10)
    raystep = np.zeros(
        (2, 10000))  # create a large array to populate and then shrink later

    barry2mex = np.linalg.norm(MEX)
    barry2tgo = np.linalg.norm(TGO)

    #find the martian geomoerty so you can reliably find the altitude of a point
    marsrad = spice.bodvrd(sv.front, 'RADII', 3)
    flatteningcoefficient = (marsrad[1][0] - marsrad[1][2]) / marsrad[1][0]
    equatorialradii = marsrad[1][0]

    _, _, MEXalt = spice.recgeo(MEX, equatorialradii, flatteningcoefficient)
    _, _, TGOalt = spice.recgeo(TGO, equatorialradii, flatteningcoefficient)

    #the possition of MEX is found by assuming that it will be somewhere over the relative horizon from TGO
    # (meaning over θ = 90°), finding the angle between the MEX and TGO's negative vector, will give the coords of MEX
    MexRelativeElevation = spice.vsep(-TGO, MEX)  #radians
    mex_y = barry2mex * np.sin(MexRelativeElevation)
    mex_x = barry2mex * np.cos(MexRelativeElevation)

    mex = np.array([0 - mex_x, mex_y])
    tgo = np.array([0 + barry2tgo, 0])
    barry = np.array([0, 0])

    #to plot the non-refracted propogation, we must convert the 3d xyzpoints to 2d, we do this the same way we found the x&y for MEX
    # ,using the norm distance and sep from -TGO5
    length = np.size(xyzpoints, 1)
    UnrefractedDistance = np.linalg.norm(xyzpoints[:, 0] -
                                         xyzpoints[:, -1])  #in km
    UnrefractedRay = np.zeros([2, length])
    for i in range(length):
        point = xyzpoints[:,
                          i] + 0  #need to put vector into temp variable as spice cant handle strided array inputs
        angle = spice.vsep(-TGO, point)
        norm = np.linalg.norm(point)
        point_x = norm * np.cos(angle)
        point_y = norm * np.sin(angle)
        UnrefractedRay[0, i] = 0 - point_x
        UnrefractedRay[1, i] = point_y

    #psuedo
    #.decide what the unit is (probably iterable),start propergation with the initial angle in one unit direction (doesnt have to be 1 km),
    #. feed each unit/10 into an alt finder and calc the avg N for this unit
    #. simple snell to find new angle with n0/n1 (does it need entry angle?)
    #.find barry2ray possition, and the bend will be from the normal of that (simple)
    #.rotate current vector up(iono) or down(neutral) minutely
    #.save coords at each unit step
    # . propergate
    #.exit when y = ~0 (bare in mind the nuetral and really f**k up at low alts), this should show in a plot anyways
    #. check variance with an altered ploterrorvariation() function
    #.calc miss, x value will usually be greater than tgo(x) because it will mostly bend upwards

    initialtheta = -(
        spice.vsep(MEX - TGO, MEX)
    )  #this will produce and angle that is likly not going to be exactly on
    #the original propagation path, you compare to this if there is a drifting error, as both this and the resultant refracted ray
    # have the same bias error. THIS ANGLE IS BENDING ANTICLOCKWISE IN THIS FRAME (BENDING UPWARDS)
    nicetohave = np.degrees(initialtheta)
    unit = 1  # in km
    rotationvector = np.array(((np.cos(initialtheta), -np.sin(initialtheta)),
                               (np.sin(initialtheta), np.cos(initialtheta))))

    #get unit vecotr of -MEX (then add this vecotr to MEX for each alt calcultation)
    unitmex = -mex / barry2mex  #unit direction (2d)
    direction = unitmex.dot(
        rotationvector
    ) * unit  #make a 2d vector coming from MEX YOU DO NOT KNOW WHAT WAY THIS IS ROTATING

    stage = 0
    t = 0  # index counter for steps along the ray
    while stage < 2:  #==0first unit, so move two units. ==1 propergate step by step. ==2 exit and analyse entire path
        #take the alt at 10 possitions across this unit
        if stage == 0:
            for k in range(10):
                point = mex + (k * (direction / 10))
                #_,_,miniray[k] = spice.recgeo(point, equatorialradii,flatteningcoefficient)
                miniray[k] = np.linalg.norm(point) - 3389
            N0 = findrefractivity(miniray, 10)
            raystep[:, t] = point  #save the last location
            t = t + 1
            stage = stage + 1

        if t == 5440:
            print('stophere')

        if stage == 1:
            for k in range(10):
                point = raystep[:, t - 1] + (k * (direction / 10))
                #_,_,miniray[k] = spice.recgeo(point, equatorialradii,flatteningcoefficient)  #THIS ONLY WORKS IN 3D
                # IMPLEMENTING MARS AS A SIMPLE CIRCLE OF AVERAGE 3389 KM RADIUS, !THIS WILL BE UPDATED TO ELLIPSE!
                miniray[k] = np.linalg.norm(point) - 3389
            raystep[:,
                    t] = point  #9 is the end of the unit, and refraction always happens relative to the center of refractivity, so rotate off this vector
            N1 = findrefractivity(miniray, 10)

            if point[1] < 0:  #if the position drops below the x axis
                stage = stage + 1  #increase the stage value so the while loop is exited

            #DEBUGGING CATCHES:
            r = N0 / N1
            if r == 1:  #only bend when there is a refractive gradient between consecutive air volumes
                t = t + 1
                N0 = N1
                continue

            #find the angle between the unit (air volume) boarder and the current direction
            unitrotationaxis = -(raystep[:, t] / np.linalg.norm(raystep[:, t]))
            #unitdirection = direction #MAYBE ALTERING UNITS WILL EFFECT THIS * OR / BY UNIT, CANT FIGURE OUT NOW, OK WHEN UNIT =1
            DotProduct = np.dot(unitrotationaxis, direction)
            AngleofIncidence = (math.pi / 2) - np.arccos(
                DotProduct)  #angle it enters the next air volume
            #simple snell law to find the bending angle (should be tiny angle)
            AngleofRefraction = np.arcsin(r * np.sin(AngleofIncidence))
            # THIS IS NOT EXACTLY WHAT THE TURN IN DIRECTION IS, NEED TO THINK ABOUT
            rotateby = 300 * ((AngleofIncidence - AngleofRefraction)
                              )  #+ve =clockwise, -ve=anticlockwise

            INCIDENCEDEGREES = np.degrees(AngleofIncidence)
            REFRACTIONDEGREES = np.degrees(AngleofRefraction)
            ROTATIONDEGREES = np.degrees(rotateby)

            #an if statement is required, if this
            if ROTATIONDEGREES > 1 or ROTATIONDEGREES < -1:
                print('stophere, u r bending to much')
            rotationvector = np.array(
                ((np.cos(rotateby), -np.sin(rotateby)), (np.sin(rotateby),
                                                         np.cos(rotateby))))
            direction = direction.dot(rotationvector)

            t = t + 1
            N0 = N1

    error = np.zeros(t)
    g = 0

    #INSERT THE SOLUTION HERE:
    #method4
    error = finderror(raystep, UnrefractedRay, initialtheta)

    #smoothraystep  = interpolate.interp1d(raystep[0],raystep[1], kind = 'linear')
    #smoothUnrefractedRay  = interpolate.interp1d(UnrefractedRay[0],UnrefractedRay[1], kind = 'linear')
    # i=0
    # raysteparea = np.trapz(raystep[0:6482], axis =0)
    # unrefractedarea = np.trapz(UnrefractedRay[0:6482], axis =0)
    # #for i in range(6482):

    # error[i] = raysteppoint[0]-UnrefractedRaypoint[0] + 0.25
    #x_progress  = np.floor(range(int(np.floor(max(raystep[0,:])) - np.floor(min(raystep[0,:])))) + raystep[0,0])
    # raystep_xy = np.zeros((2,np.size(x_progress)))
    #UnrefractedRay_xy = np.zeros((2,np.size(x_progress)))
    error = np.zeros(t)
    # smallerraystep_x = raystep[0,:]
    # smallerraystep_x = smallerraystep_x[smallerraystep_x != 0]
    # roundedraysteps_x = np.floor(smallerraystep_x)
    # roundedunrefracted_x = np.floor(UnrefractedRay[0,:])

    # #rounded_x = np.floor(UnrefractedRay[0,:])
    # #analyse at each raystep to see the error, you can do an x value match and then correct for the delay
    #for i in range(t):

    # raystep_x = raystep[0,:]
    # UnrefractedRay_x = UnrefractedRay[0,:]
    # idxray = np.searchsorted(UnrefractedRay_x , raystep_x[i], side ='left')
    # if idxray > UnrefractedRay_x[-1]:
    #     break
    # UnrefractedRay_xy = UnrefractedRay[:,idxray]
    # #idxUnrefracted = np.searchsorted(roundedunrefracted_x,  x_progress[i], side ='left') # and raystep_x[0,:] > x_progress[i] ]# to deal with the high precision numbers
    # if idxray ==[]:
    #     break

    #ray_y = raystep[1,idxray]
    #unrefracted_y = UnrefractedRay[1,idxUnrefracted]
    #error[i] = ray_y-unrefracted_y

    # index_xUnrefracted= np.where(UnrefractedRay[0,:] < (x_progress[i] + 1) and UnrefractedRay[0,:] > x_progress[i] ) # it is not found because Ray has many decimal points
    # index_xRefracted = np.where(raystep[0,:] < (x_progress[i] +1) and raystep[0,:] > x_progress[i]) #maybe add a -+ limiter aound it?
    # indexU = index_xUnrefracted[1][0]
    # UnrefractedRaypoint = UnrefractedRay[:,indexU]
    # indexR = index_xRefracted[1][0]
    # raysteppoint = raystep[:,indexR]

    #     error[i] = raysteppoint[0]-UnrefractedRaypoint[0] + 0.25
    # #     #PossiblePoints = PossiblePoints[PossiblePoints > x_progress[i] ]# splitting the conditional across two lines due to a ambiguity error
    # #     #PossiblePoints1 = PossiblePoints[PossiblePoints !=0]

    # error = error[error !=0]

    # #LETS SMOOTH THE ERRORS TO FIX YOUR ROUNDING ERROR
    # window_size = 10
    # i = 0
    # moving_averages = []
    # while i < len(error) - window_size + 1:
    #     this_window = error[i : i + window_size]
    #     window_average = sum(this_window) / window_size
    #     moving_averages.append(window_average)
    #     i += 1

    # plt.plot( moving_averages , '.')
    # plt.ylabel('Error')
    # plt.xlabel('X progression')
    # plt.show()

    #     # #F**K IT EVEN OLDER VERSION
    #     # #FIND VALUE IN RAYSTEP THAT SUITS THE XPROGRESS CONDITIONS
    #     # raystep_x = raystep[0,:]
    #     # PossiblePoints = raystep_x[raystep_x < (x_progress[i]+1)]# and raystep_x[0,:] > x_progress[i] ]# to deal with the high precision numbers
    #     # PossiblePoints = PossiblePoints[PossiblePoints > x_progress[i] ]# splitting the conditional across two lines due to a ambiguity error
    #     # PossiblePoints1 = PossiblePoints[PossiblePoints !=0]
    #     # if PossiblePoints.size ==0:#very rarely there maybe be no value for this value of x
    #     #     continue #we might have got to the end
    #     # SearchFor = PossiblePoints1[0]# only take the first value
    #     # index = np.where(raystep_x == SearchFor)
    #     # Index1 = index[0][0]
    #     # raystep_xy[:,i] = raystep[:,Index1]

    #     # #FIND VALUE IN UNREFRACTED THAT SUITS THE XPROGRESS CONDITIONS
    #     # UnrefractedRay_x = UnrefractedRay[0,:]
    #     # PossiblePoints = UnrefractedRay_x[UnrefractedRay_x< (x_progress[i]+1)]# to deal with the high precision numbers
    #     # PossiblePoints = PossiblePoints[PossiblePoints > x_progress[i] ]# splitting the conditional across two lines due to a ambiguity error
    #     # PossiblePoints2 = PossiblePoints[PossiblePoints !=0]
    #     # if PossiblePoints.size ==0:
    #     #     continue
    #     # SearchFor = PossiblePoints2[0]# only take the first value
    #     # index = np.where(UnrefractedRay_x == SearchFor)
    #     # Index2 = index[0][0]
    #     # UnrefractedRay_xy[:,i] = UnrefractedRay[:,Index2]

    #     # # OLD METHOD

    #     #error[i] = np.linalg.norm(raystep_xy[:,i]-UnrefractedRay_xy[:,i]) #probs alter the format of 'index'
    #     g=g+1 #only do this if it set!!

    # #error = error[error < 0.1 ]#take every 10th value]
    # #x_progress = x_progress[0::10]
    # plt.plot( error , '.')
    # plt.ylabel('Error')
    # plt.xlabel('X progression')
    # plt.show()

    fig, ax = plt.subplots()
    plt.plot(barry[0], barry[1], 'x')
    plt.annotate('$\u2642$', (barry[0], barry[1]), fontsize=20)
    marsradii = plt.Circle((0, 0), 3389, color='red', fill=False)
    ax.add_artist(marsradii)
    plt.plot(mex[0], mex[1], '.')
    plt.annotate('MEX', (mex[0], mex[1]))
    plt.plot(tgo[0], tgo[1], 'o')
    plt.annotate('TGO', (tgo[0], tgo[1]))
    plt.plot(UnrefractedRay[0], UnrefractedRay[1], ':')
    plt.annotate(
        'Distance = %ikm' % UnrefractedDistance,
        (UnrefractedRay[0, length // 2], UnrefractedRay[1, length // 2]),
        fontsize=8)
    plt.plot(raystep[0], raystep[1], '.')
    plt.gca().set_aspect('equal', adjustable='box')
    ax.set_xlabel('X')
    ax.set_ylabel('Y')
    plt.show()

    print('stophere')
コード例 #12
0
def flatbending(xyzpoints, initialangle, sv, MEX, TGO):
    #form a coordinate system where tgo is @ y=0 and x= (5000 +norm), Mar's Barrycenter being @ [5000,0]
    subgroupsize = 10
    #initialise non-global variables
    miniray = np.zeros(subgroupsize)
    raystep = np.zeros(
        (2,
         100000000))  # create a large array to populate and then shrink later

    barry2mex = np.linalg.norm(MEX)
    barry2tgo = np.linalg.norm(TGO)

    #find the martian geomoerty so you can reliably find the altitude of a point
    marsrad = spice.bodvrd(sv.front, 'RADII', 3)
    flatteningcoefficient = (marsrad[1][0] - marsrad[1][2]) / marsrad[1][0]
    equatorialradii = marsrad[1][0]

    _, _, MEXalt = spice.recgeo(MEX, equatorialradii, flatteningcoefficient)
    _, _, TGOalt = spice.recgeo(TGO, equatorialradii, flatteningcoefficient)

    #the possition of MEX is found by assuming that it will be somewhere over the relative horizon from TGO
    # (meaning over θ = 90°), finding the angle between the MEX and TGO's negative vector, will give the coords of MEX
    MexRelativeElevation = spice.vsep(-TGO, MEX)  #radians
    mex_y = barry2mex * np.sin(MexRelativeElevation)
    mex_x = barry2mex * np.cos(MexRelativeElevation)

    mex = np.array([0 - mex_x, mex_y])
    tgo = np.array([0 + barry2tgo, 0])
    barry = np.array([0, 0])

    #to plot the non-refracted propogation, we must convert the 3d xyzpoints to 2d, we do this the same way we found the x&y for MEX
    # ,using the norm distance and sep from -TGO5
    length = np.size(xyzpoints, 1)
    UnrefractedDistance = np.linalg.norm(xyzpoints[:, 0] -
                                         xyzpoints[:, -1])  #in km
    UnrefractedRay = np.zeros([2, length])
    for i in range(length):  #conversion to 2D
        point = xyzpoints[:,
                          i] + 0  #need to put vector into temp variable as spice cant handle strided array inputs
        angle = spice.vsep(-TGO, point)
        norm = np.linalg.norm(point)
        point_x = norm * np.cos(angle)
        point_y = norm * np.sin(angle)
        UnrefractedRay[0, i] = 0 - point_x
        UnrefractedRay[1, i] = point_y

    #this will produce and angle that is likly not going to be exactly on
    #the original propagation path, you compare to this if there is a drifting error, as both this and the resultant refracted ray
    # have the same bias error. THIS ANGLE IS BENDING ANTICLOCKWISE IN THIS FRAME (BENDING UPWARDS)
    initialtheta = -(spice.vsep(MEX - TGO, MEX))
    nicetohave = np.degrees(initialtheta)

    unit = 1  # in km

    rotationvector = np.array(((np.cos(initialtheta), -np.sin(initialtheta)),
                               (np.sin(initialtheta), np.cos(initialtheta))))

    #get unit vecotr of -MEX (then add this vecotr to MEX for each alt calcultation)
    unitmex = -mex / barry2mex  #unit direction (2d)
    initialdirection = unitmex.dot(
        rotationvector
    ) * unit  #make a 2d vector coming from MEX YOU DO NOT KNOW WHAT WAY THIS IS ROTATING

    iterationcount = 0
    #while iterationcount<100:
    #print( "Finding Bending Angle (", str(iterationcount) ,"% Complete)")
    errorstore = np.zeros((11, 100000))
    Nstore = np.zeros(20000)

    while iterationcount < 100:
        tic = timer.perf_counter()
        if iterationcount == 0:
            direction = initialdirection
        else:
            # the initail direction must be rotated by a 10th of the miss at the end
            missangle = missangle / 1
            missrotationvector = np.array(
                ((mp.cos(missangle), mp.sin(missangle)), (mp.sin(missangle),
                                                          mp.cos(missangle))))
            direction = initialdirection.dot(missrotationvector)
            initialdirection = direction

        turningcounter = 0
        progress = [0, 0]
        stage = 0
        t = 0
        with tqdm(total=mex[1], desc="Progress", leave=False) as pbar:
            while stage < 2:  #==0first unit, so move two units. ==1 propergate step by step. ==2 exit and analyse entire path
                #take the alt at 10 possitions across this unit

                #lets get a quick calculated for the magnitude of the direction
                MAAAAG = np.linalg.norm(direction)  # this should = unit

                if stage == 0:
                    for k in range(subgroupsize):  #this starts with 0
                        point = mex + ((k + 1) * (direction / subgroupsize))
                        #_,_,miniray[k] = spice.recgeo(point, equatorialradii,flatteningcoefficient)
                        miniray[k] = np.linalg.norm(
                            point) - 3389  #average radii of mars
                    N0 = findrefractivity(miniray, subgroupsize)
                    raystep[:, t] = point  #save the last location
                    t = t + 1
                    stage = stage + 1

                if stage == 1:
                    for k in range(subgroupsize):
                        point = raystep[:, t - 1] + (
                            (k + 1) * (direction / subgroupsize)
                        )  #am i double counting the end of the last and the start of the next?
                        #_,_,miniray[k] = spice.recgeo(point, equatorialradii,flatteningcoefficient)  #THIS ONLY WORKS IN 3D
                        # IMPLEMENTING MARS AS A SIMPLE CIRCLE OF AVERAGE 3389 KM RADIUS, !THIS WILL BE UPDATED TO ELLIPSE!
                        miniray[k] = np.linalg.norm(point) - 3389
                    raystep[:,
                            t] = point  #9 is the end of the unit, and refraction always happens relative to the center of refractivity, so rotate off this vector
                    N1 = findrefractivity(miniray, subgroupsize)

                    if point[1] < 0:  #if the position drops below the x axis
                        stage = stage + 1  #increase the stage value so the while loop is exited

                    #this section allows for better timing of the function, increment the progresbar by 1 if the current
                    #position goes one y-value lower
                    currenty = raystep[1, t]
                    progress[1] = mex[
                        1] - currenty  #this value will be increasing from 0 -> Mex height
                    increment = np.floor(progress[1]) - np.floor(
                        progress[0])  #only when
                    if increment == 1:
                        pbar.update(1)
                    progress[0] = progress[1]

                    if abs(N0) < 1e-20:  #catch for precision errors
                        Nstore[t] = N1
                        t = t + 1
                        N0 = N1
                        continue

                    #print('Current Y possition is', currenty) #this is alt, so is ~3389 km smaller than the vector
                    r = N0 / N1  #NEED MORE PRECISION
                    numorator = mpf(N0) + mpf(1)
                    denominator = mpf(N1) + mpf(1)
                    rbending = mp.fdiv(
                        numorator,
                        denominator)  #average would just add 1 to total N
                    if t == 5000:  #only bend when there is a refractive gradient between consecutive air volumes[NO CHANGE IN DIRECTION]
                        t = t + 1
                        N0 = N1
                        continue

                    #this section is only reached if a turning is going to happen
                    # ,testing to see if there is 10 X less turing if the units are 10X smaller -TRUE
                    TEST = float(rbending)
                    if TEST != 1:
                        turningcounter = turningcounter + 1

                    # !! NOW WITH PRECISION !!

                    #find the angle between the unit (air volume) boarder and the current direction
                    unitrotationaxis = raystep[:, t] / np.linalg.norm(
                        raystep[:, t])
                    #unitdirection = direction #MAYBE ALTERING UNITS WILL EFFECT THIS * OR / BY UNIT, CANT FIGURE OUT NOW, OK WHEN UNIT =1
                    DotProduct = np.dot(unitrotationaxis, direction)
                    AngleofIncidence = (math.pi / 2) - mp.acos(
                        DotProduct)  #angle it enters the next air volume
                    #simple snell law to find the bending angle (should be tiny angle)
                    AngleofRefraction = mp.asin(rbending *
                                                mp.sin(AngleofIncidence))
                    # THIS IS NOT EXACTLY WHAT THE TURN IN DIRECTION IS, NEED TO THINK ABOUT
                    rotateby = ((AngleofIncidence - AngleofRefraction)
                                )  #+ve =clockwise, -ve=anticlockwise

                    INCIDENCEDEGREES = mp.degrees(AngleofIncidence)
                    REFRACTIONDEGREES = mp.degrees(AngleofRefraction)
                    ROTATIONDEGREES = mp.degrees(rotateby)

                    #an if statement is required, if this
                    if ROTATIONDEGREES > 1 or ROTATIONDEGREES < -1:
                        print('stophere, u r bending to much')
                    rotationvector = np.array(
                        ((mp.cos(rotateby), -mp.sin(rotateby)),
                         (mp.sin(rotateby), mp.cos(rotateby))))
                    direction = direction.dot(rotationvector)

                    N0 = N1

                    #store N1 to calc electric distance
                    Nstore[t] = N1
                    t = t + 1

            #pbar.refresh()

        error = np.zeros(t)
        #print("Number of turns:", turningcounter)
        error = finderror(raystep, UnrefractedRay)
        miss = error

        missangle = mp.asin(miss / UnrefractedDistance)
        toc = timer.perf_counter()
        passingtime = toc - tic
        print(' miss =',
              format(miss * 1000, '.5f'),
              'm || Angle =',
              nstr(mp.degrees(missangle), 5),
              '° || Speed =',
              passingtime,
              ' Sec \n',
              sep=" ",
              end=" ",
              flush=True)
        if abs(miss) < 1e-5:  #is the miss smaller than 10 cm?
            #ploterrortraces(errorstore,t)
            break
        iterationcount = iterationcount + 1

    #find the total bending angle at MEX for this final configuration
    unit_initial = initialdirection / np.linalg.norm(initialdirection)
    dot_product = np.dot(unit_initial, unitmex)
    FinalBendingAngle = mp.acos(dot_product)

    #from the refractive profile from MEX ->TGO, calc the intergral of the change in wavelength to aquire doppler
    Nstore = Nstore[Nstore != 0]
    Nstore = Nstore + 1  #convert N deltas into values of N
    ElectricDistance = np.sum(
        Nstore
    )  #N * wavelengths in a km (UNITS MUST BE KEPT THE SAME AS STEP-SIZE)

    return FinalBendingAngle, ElectricDistance
コード例 #13
0
def flatbending(xyzpoints, initialangle, sv, MEX, TGO):
    #form a coordinate system where tgo is @ y=0 and x= (5000 +norm), Mar's Barrycenter being @ [5000,0]

    #initialise non-global variables
    miniray = np.zeros(10)
    raystep = np.zeros(
        (2,
         100000000))  # create a large array to populate and then shrink later

    barry2mex = np.linalg.norm(MEX)
    barry2tgo = np.linalg.norm(TGO)

    #find the martian geomoerty so you can reliably find the altitude of a point
    marsrad = spice.bodvrd(sv.front, 'RADII', 3)
    flatteningcoefficient = (marsrad[1][0] - marsrad[1][2]) / marsrad[1][0]
    equatorialradii = marsrad[1][0]

    _, _, MEXalt = spice.recgeo(MEX, equatorialradii, flatteningcoefficient)
    _, _, TGOalt = spice.recgeo(TGO, equatorialradii, flatteningcoefficient)

    #the possition of MEX is found by assuming that it will be somewhere over the relative horizon from TGO
    # (meaning over θ = 90°), finding the angle between the MEX and TGO's negative vector, will give the coords of MEX
    MexRelativeElevation = spice.vsep(-TGO, MEX)  #radians
    mex_y = barry2mex * np.sin(MexRelativeElevation)
    mex_x = barry2mex * np.cos(MexRelativeElevation)

    mex = np.array([0 - mex_x, mex_y])
    tgo = np.array([0 + barry2tgo, 0])
    barry = np.array([0, 0])

    #to plot the non-refracted propogation, we must convert the 3d xyzpoints to 2d, we do this the same way we found the x&y for MEX
    # ,using the norm distance and sep from -TGO5
    length = np.size(xyzpoints, 1)
    UnrefractedDistance = np.linalg.norm(xyzpoints[:, 0] -
                                         xyzpoints[:, -1])  #in km
    UnrefractedRay = np.zeros([2, length])
    for i in range(length):
        point = xyzpoints[:,
                          i] + 0  #need to put vector into temp variable as spice cant handle strided array inputs
        angle = spice.vsep(-TGO, point)
        norm = np.linalg.norm(point)
        point_x = norm * np.cos(angle)
        point_y = norm * np.sin(angle)
        UnrefractedRay[0, i] = 0 - point_x
        UnrefractedRay[1, i] = point_y

    #this will produce and angle that is likly not going to be exactly on
    #the original propagation path, you compare to this if there is a drifting error, as both this and the resultant refracted ray
    # have the same bias error. THIS ANGLE IS BENDING ANTICLOCKWISE IN THIS FRAME (BENDING UPWARDS)
    initialtheta = -(spice.vsep(MEX - TGO, MEX))
    nicetohave = np.degrees(initialtheta)
    unit = 1  # in km
    rotationvector = np.array(((np.cos(initialtheta), -np.sin(initialtheta)),
                               (np.sin(initialtheta), np.cos(initialtheta))))

    #get unit vecotr of -MEX (then add this vecotr to MEX for each alt calcultation)
    unitmex = -mex / barry2mex  #unit direction (2d)
    direction = unitmex.dot(
        rotationvector
    ) * unit  #make a 2d vector coming from MEX YOU DO NOT KNOW WHAT WAY THIS IS ROTATING

    iterationcount = 0
    #while iterationcount<100:
    print("Finding Bending Angle (", str(iterationcount), "% Complete)")

    #some function based on miss (miss begins with )

    stage = 0
    t = 0  # index counter for steps along the ray
    while stage < 2:  #==0first unit, so move two units. ==1 propergate step by step. ==2 exit and analyse entire path
        #take the alt at 10 possitions across this unit
        if stage == 0:
            for k in range(10):
                point = mex + (k * (direction / 10))
                #_,_,miniray[k] = spice.recgeo(point, equatorialradii,flatteningcoefficient)
                miniray[k] = np.linalg.norm(
                    point) - 3389  #average radii of mars
            N0 = findrefractivity(miniray, 10)
            raystep[:, t] = point  #save the last location
            t = t + 1
            stage = stage + 1

        if stage == 1:
            for k in range(10):
                point = raystep[:, t - 1] + (k * (direction / 10))
                #_,_,miniray[k] = spice.recgeo(point, equatorialradii,flatteningcoefficient)  #THIS ONLY WORKS IN 3D
                # IMPLEMENTING MARS AS A SIMPLE CIRCLE OF AVERAGE 3389 KM RADIUS, !THIS WILL BE UPDATED TO ELLIPSE!
                miniray[k] = np.linalg.norm(point) - 3389
            raystep[:,
                    t] = point  #9 is the end of the unit, and refraction always happens relative to the center of refractivity, so rotate off this vector
            N1 = findrefractivity(miniray, 10)

            if point[1] < 0:  #if the position drops below the x axis
                stage = stage + 1  #increase the stage value so the while loop is exited

            # if N0 !=1:
            #     print('querycode')

            currenty = raystep[1, t]
            print('Current Y possition is', currenty)
            r = N0 / N1  #NEED MORE PRECISION
            if r == 1:  #only bend when there is a refractive gradient between consecutive air volumes[NO CHANGE IN DIRECTION]
                t = t + 1
                N0 = N1
                continue

            #find the angle between the unit (air volume) boarder and the current direction
            unitrotationaxis = -(raystep[:, t] / np.linalg.norm(raystep[:, t]))
            #unitdirection = direction #MAYBE ALTERING UNITS WILL EFFECT THIS * OR / BY UNIT, CANT FIGURE OUT NOW, OK WHEN UNIT =1
            DotProduct = np.dot(unitrotationaxis, direction)
            AngleofIncidence = (math.pi / 2) - np.arccos(
                DotProduct)  #angle it enters the next air volume
            #simple snell law to find the bending angle (should be tiny angle)
            AngleofRefraction = np.arcsin(r * np.sin(AngleofIncidence))
            # THIS IS NOT EXACTLY WHAT THE TURN IN DIRECTION IS, NEED TO THINK ABOUT
            rotateby = 300 * ((AngleofIncidence - AngleofRefraction)
                              )  #+ve =clockwise, -ve=anticlockwise

            INCIDENCEDEGREES = np.degrees(AngleofIncidence)
            REFRACTIONDEGREES = np.degrees(AngleofRefraction)
            ROTATIONDEGREES = np.degrees(rotateby)

            #an if statement is required, if this
            if ROTATIONDEGREES > 1 or ROTATIONDEGREES < -1:
                print('stophere, u r bending to much')
            rotationvector = np.array(
                ((np.cos(rotateby), -np.sin(rotateby)), (np.sin(rotateby),
                                                         np.cos(rotateby))))
            direction = direction.dot(rotationvector)

            #if np.linalg.norm(direction)< 0.08:# assuming unit is set to 0.1
            # print(' your movement direction is shrinking')

            t = t + 1
            N0 = N1

    error = np.zeros(t)
    g = 0

    #error = finderror(raystep, UnrefractedRay, initialtheta)

    miss = error[-1]  # +ve miss needs a clockwise rotation,
    iterationcount = iterationcount + 1

    fig, ax = plt.subplots()
    plt.plot(barry[0], barry[1], 'x')
    plt.annotate('$\u2642$', (barry[0], barry[1]), fontsize=20)
    marsradii = plt.Circle((0, 0), 3389, color='red', fill=False)
    ax.add_artist(marsradii)
    plt.plot(mex[0], mex[1], '.')
    plt.annotate('MEX', (mex[0], mex[1]))
    plt.plot(tgo[0], tgo[1], 'o')
    plt.annotate('TGO', (tgo[0], tgo[1]))
    plt.plot(UnrefractedRay[0], UnrefractedRay[1], ':')
    plt.annotate(
        'Distance = %ikm' % UnrefractedDistance,
        (UnrefractedRay[0, length // 2], UnrefractedRay[1, length // 2]),
        fontsize=8)
    plt.plot(raystep[0], raystep[1], ':')
    plt.gca().set_aspect('equal', adjustable='box')
    ax.set_xlabel('X')
    ax.set_ylabel('Y')
    plt.show()

    print('stophere')
コード例 #14
0
    kwargs = {'from_ref': from_ref,
              'to_ref': to_ref}

    tais = utc2tai(utc, utc_end, deltat)
    return distribute_work(xform_spice, xfunc, tais, **kwargs)

def utc2scs(utc, utc_end, deltat, sc):
    tais = utc2tai(utc, utc_end, deltat)
    return utc2scs_spice(tais, sc)

def scs2utc(scs, sc, deltat):
    return scs2utc_spice(scs, sc, deltat)

_POSITION_KIND = {
    None         : lambda x: x,
    'rectangular': lambda x: x,
    'latitudinal': sp.reclat,
    'radec'      : sp.recrad,
    'spherical'  : sp.recsph,
    'cylindrical': sp.reccyl,
    'geodetic'   : lambda x: sp.recgeo(x, 6378.14, 0.0033536422844278)
}

_TRANSFORM_KIND = {
    None         : lambda x: x,
    'matrix'     : lambda x: x,
    'angle'      : lambda x: sp.m2eul(x, 3, 2, 1),
    'quaternion' : sp.m2q
}
コード例 #15
0
def flatbending(xyzpoints, initialangle, MEX, TGO):
    # form a coordinate system where tgo is @ y=0 and x= (5000 +norm), Mar's Barrycenter being @ [5000,0]
    class SpiceVariables:
        obs = '-41'  # NAIF code for MEX
        # NAIF code for TGO ['EARTH'/'SUN'/ a groundstation etc]
        target = '-143'
        obsfrm = 'IAU_MARS'
        abcorr = 'NONE'
        crdsys = 'LATITUDINAL'
        coord = 'LATITUDE'
        stepsz = 100.0  # Check every 300 seconds if there is an occultation
        MAXILV = 100000  # Max number of occultations that can be returned by gfoclt
        bshape = 'POINT'
        fshape = 'DSK/UNPRIORITIZED'
        front = 'MARS'
        fframe = 'IAU_MARS'
        TFMT = 'YYYY-MM-DD HR:MN:SC'  # Format that Cosmographia understands

    sv = SpiceVariables()
    subgroupsize = 1
    unit = 0.1  # in km
    mp.dps = 40
    # initialise non-global variables
    miniray = np.zeros(subgroupsize)
    # create a large array to populate and then shrink later
    raystep = np.zeros((2, 100000000))

    barry2mex = np.linalg.norm(MEX)
    barry2tgo = np.linalg.norm(TGO)

    # find the martian geomoerty so you can reliably find the altitude of a point
    marsrad = spice.bodvrd(sv.front, 'RADII', 3)
    flatteningcoefficient = (marsrad[1][0] - marsrad[1][2]) / marsrad[1][0]
    equatorialradii = marsrad[1][0]
    TGO = TGO + 0
    MEX = MEX + 0  # force to be non-strided
    _, _, MEXalt = spice.recgeo(MEX, equatorialradii, flatteningcoefficient)
    _, _, TGOalt = spice.recgeo(TGO, equatorialradii, flatteningcoefficient)

    # the possition of MEX is found by assuming that it will be somewhere over the relative horizon from TGO
    # (meaning over θ = 90°), finding the angle between the MEX and TGO's negative vector, will give the coords of MEX
    MexRelativeElevation = spice.vsep(-TGO, MEX)  # radians
    mex_y = barry2mex * np.sin(MexRelativeElevation)
    mex_x = barry2mex * np.cos(MexRelativeElevation)

    mex = np.array([0 - mex_x, mex_y])
    tgo = np.array([0 + barry2tgo, 0])
    barry = np.array([0, 0])

    # to plot the non-refracted propogation, we must convert the 3d xyzpoints to 2d, we do this the same way we found the x&y for MEX
    # ,using the norm distance and sep from -TGO5
    length = np.size(xyzpoints, 1)
    UnrefractedDistance = np.linalg.norm(xyzpoints[:, 0] -
                                         xyzpoints[:, -1])  # in km
    UnrefractedRay = np.zeros((2, length))
    for i in range(length):
        # need to put vector into temp variable as spice cant handle strided array inputs
        point = xyzpoints[:, i] + 0
        angle = spice.vsep(-TGO, point)
        norm = np.linalg.norm(point)
        point_x = norm * np.cos(angle)
        point_y = norm * np.sin(angle)
        UnrefractedRay[0, i] = 0 - point_x
        UnrefractedRay[1, i] = point_y

    # this will produce and angle that is likly not going to be exactly on
    # the original propagation path, you compare to this if there is a drifting error, as both this and the resultant refracted ray
    # have the same bias error. THIS ANGLE IS BENDING ANTICLOCKWISE IN THIS FRAME (BENDING UPWARDS)
    initialtheta = -(spice.vsep(MEX - TGO, MEX))
    nicetohave = np.degrees(initialtheta)

    rotationvector = np.array(((np.cos(initialtheta), -np.sin(initialtheta)),
                               (np.sin(initialtheta), np.cos(initialtheta))))

    # get unit vecotr of -MEX (then add this vecotr to MEX for each alt calcultation)
    unitmex = -mex / barry2mex  # unit direction (2d)
    # make a 2d vector coming from MEX YOU DO NOT KNOW WHAT WAY THIS IS ROTATING
    initialdirection = unitmex.dot(rotationvector) * unit

    iterationcount = 0
    # while iterationcount<100:
    #print( "Finding Bending Angle (", str(iterationcount) ,"% Complete)")
    errorstore = np.zeros((11, 5000000))
    miss = inf
    missangle = inf

    while iterationcount < 100:
        if iterationcount == 0:
            direction = initialdirection
        else:
            # the initail direction must be rotated by a 10th of the miss at the end
            missangle = missangle / 1
            missrotationvector = np.array(
                ((mp.cos(missangle), -mp.sin(missangle)), (mp.sin(missangle),
                                                           mp.cos(missangle))))
            direction = initialdirection.dot(missrotationvector)

            # to make the produced direction reach mpmath dp level
            # a= mp.cos(missangle) ; b = -mp.sin(missangle) #ORIGINAL DID NOT GAVE THIS NEG, SO IT HAS BEEN MADE POSITIVE
            # c = mp.sin(missangle) ; d = mp.cos(missangle)

            # rotationvector = np.array([[a,b],[c,d]])
            # direction = direction.dot(rotationvector)

            initialdirection = direction
        Nstore = np.zeros(20000000)
        turningcounter = 0
        progress = [0, 0]
        stage = 0
        t = 0
        tic = timer.perf_counter()
        # raypositions = pd.DataFrame(raystep.T, columns=['x', 'y'])# should produce an empty dataframe to store
        # the high precision positions

        with tqdm(total=mex[1], desc="Progress", leave=False) as pbar:
            while stage < 2:  # ==0first unit, so move two units. ==1 propergate step by step. ==2 exit and analyse entire path
                # take the alt at 10 possitions across this unit

                # lets get a quick calculated for the magnitude of the direction
                MAAAAG = np.linalg.norm(direction)  # this should = unit

                if stage == 0:
                    for k in range(subgroupsize):  # this starts with 0
                        point = mex + ((k + 1) * (direction / subgroupsize))
                        miniray[k] = np.linalg.norm(
                            point) - 3389  # average radii of mars
                    N0 = findrefractivity(miniray, subgroupsize)
                    raystep[0, t] = point[0]
                    raystep[1, t] = point[1]  # save the last location
                    t = t + 1
                    stage = stage + 1

                if stage == 1:
                    for k in range(subgroupsize):
                        subvalue = ((k + 1) * (direction / subgroupsize))
                        # am i double counting the end of the last and the start of the next?
                        point = raystep[:, t - 1] + subvalue
                        # IMPLEMENTING MARS AS A SIMPLE CIRCLE OF AVERAGE 3389 KM RADIUS, !THIS WILL BE UPDATED TO ELLIPSE!
                        # provides the alt, this can have less precision
                        miniray[k] = np.linalg.norm(point) - 3389
                    raystep[0, t] = point[0]  # x
                    raystep[1, t] = point[1]  # y
                    N1 = findrefractivity(miniray, subgroupsize)

                    if point[1] < 0:  # if the position drops below the x axis
                        stage = stage + 1  # increase the stage value so the while loop is exited

                    currenty = raystep[1, t]
                    # this value will be increasing from 0 -> Mex height
                    progress[1] = mex[1] - currenty
                    increment = np.floor(progress[1]) - np.floor(
                        progress[0])  # only when
                    if increment == 1:
                        pbar.update(1)
                    progress[0] = progress[1]

                    # catch for precision errors e-50 is basically the entire propagation
                    if abs(N0) < 1e-10:
                        Nstore[t] = N1
                        t = t + 1
                        N0 = N1
                        continue

                    # ensure all the turns are being implemented

                    # print('Current Y possition is', currenty) #this is alt, so is ~3389 km smaller than the vector

                    numorator = mpf(N0) + mpf(1)
                    denominator = mpf(N1) + mpf(1)
                    # average would just add 1 to total N
                    rbending = mp.fdiv(numorator, denominator)
                    # only bend when there is a refractive gradient between consecutive air volumes[NO CHANGE IN DIRECTION]
                    if t == 5000:
                        t = t + 1
                        N0 = N1
                        continue

                    # this section is only reached if a turning is going to happen
                    # ,testing to see if there is 10 X less turing if the units are 10X smaller -TRUE
                    # TEST = float(rbending)
                    # if TEST != 1:
                    #     turningcounter = turningcounter+1

                    # !! NOW WITH PRECISION !!
                    #ray = raypositions.iloc[t,:].values
                    # find the angle between the unit (air volume) boarder and the current direction
                    unitrotationaxis = raystep[:, t] / \
                        (np.linalg.norm(raystep[:, t])*unit)
                    # unitdirection = direction #MAYBE ALTERING UNITS WILL EFFECT THIS * OR / BY UNIT, CANT FIGURE OUT NOW, OK WHEN UNIT =1
                    DotProduct = fdot(unitrotationaxis, direction)
                    # angle it enters the next air volume
                    AngleofIncidence = (math.pi / 2) - mp.acos(DotProduct)
                    # simple snell law to find the bending angle (should be tiny angle)
                    AngleofRefraction = mp.asin(rbending *
                                                mp.sin(AngleofIncidence))
                    # THIS IS NOT EXACTLY WHAT THE TURN IN DIRECTION IS, NEED TO THINK ABOUT
                    # +ve =clockwise, -ve=anticlockwise
                    rotateby = ((AngleofIncidence - AngleofRefraction))

                    INCIDENCEDEGREES = mp.degrees(AngleofIncidence)
                    REFRACTIONDEGREES = mp.degrees(AngleofRefraction)
                    ROTATIONDEGREES = mp.degrees(rotateby)

                    predirection = direction

                    # an if statement is required, if this
                    if ROTATIONDEGREES > 1 or ROTATIONDEGREES < -1:
                        print('stophere, u r bending to much')
                    a = mp.cos(rotateby)
                    b = -mp.sin(rotateby)
                    c = mp.sin(rotateby)
                    d = mp.cos(rotateby)

                    rotationvector = np.array([[a, b], [c, d]])
                    direction = direction.dot(rotationvector)

                    # rotationvector = matrix([[ mp.cos(rotateby), -mp.sin(rotateby)],
                    #                           [mp.sin(rotateby),  mp.cos(rotateby)]])
                    # direction = fdot(direction,rotationvector)

                    if direction[1] != predirection[1]:
                        # no bending has occured due to precision error
                        # if the last direction is different to the current one then a turning has occured.
                        # do we move forward with the same precision
                        turningcounter = turningcounter + 1

                    N0 = N1

                    # store N1 to calc electric distance
                    Nstore[t] = N1
                    t = t + 1

        unit_initial = initialdirection / np.linalg.norm(initialdirection)
        dot_product = np.dot(unit_initial, unitmex)
        FinalBendingAngle = mp.acos(dot_product)

        # from the refractive profile from MEX ->TGO, calc the intergral of the change in wavelength to aquire doppler
        Nstore = Nstore[Nstore != 0]
        Nstore = 1 - Nstore  # convert N deltas into values of N

        error = np.zeros(t)
        #print("Number of turns:", turningcounter)
        error = finderror(raystep, UnrefractedRay, initialtheta,
                          iterationcount)
        miss = error[-1]  # +ve miss needs a clockwise rotation

        errorstore[iterationcount, :t - 1] = error

        missangle = mp.asin(miss / UnrefractedDistance)
        toc = timer.perf_counter()
        passingtime = toc - tic
        print(' miss =',
              format(miss * 1000, '.5f'),
              'm || Angle =',
              nstr(mp.degrees(FinalBendingAngle + initialtheta), 5),
              '° || Speed =',
              passingtime,
              ' Sec \n',
              sep=" ",
              end=" ",
              flush=True)

        #print('ANGLE miss =', mp.degrees(missangle) ,'Degrees')
        if abs(miss) < 1e-5:  # is the miss smaller than 10 cm?
            # ploterrortraces(errorstore,t)
            print("stophere")
            break
        iterationcount = iterationcount + 1

        # Expensive plotting (7sec)
        fig, ax = plt.subplots()
        plt.plot(barry[0], barry[1], 'x')
        plt.annotate('$\u2642$', (barry[0], barry[1]), fontsize=20)
        marsradii = plt.Circle((0, 0), 3389, color='red', fill=False)
        ionoradii = plt.Circle((0, 0), 3389 + 130, color='blue', fill=False)
        ax.add_artist(marsradii)
        ax.add_artist(ionoradii)
        plt.plot(mex[0], mex[1], '.')
        plt.annotate('MRO', (mex[0], mex[1]))
        plt.plot(tgo[0], tgo[1], 'o')
        plt.annotate('MO', (tgo[0], tgo[1]))
        plt.plot(UnrefractedRay[0], UnrefractedRay[1], ':')
        plt.annotate(
            'Distance = %ikm' % UnrefractedDistance,
            (UnrefractedRay[0, length // 2], UnrefractedRay[1, length // 2]),
            fontsize=8)
        plt.plot(raystep[0], raystep[1], ':')
        plt.gca().set_aspect('equal', adjustable='box')
        ax.set_xlabel('X')
        ax.set_ylabel('Y')
        plt.plot(raystep[0, 0::500], raystep[1, 0::500], 'x', markersize=12)
        plt.show()

    # N * wavelengths in a km (UNITS MUST BE KEPT THE SAME AS STEP-SIZE)
    ElectricDistance = np.sum(Nstore)

    return FinalBendingAngle, ElectricDistance
    print('stophere')