예제 #1
0
파일: test_main.py 프로젝트: huleg/pymap3d
def test_geodetic():
    xyz = pm.geodetic2ecef(*lla0)

    assert xyz == approx(xyz0)
    assert pm.geodetic2ecef(*rlla0, deg=False) == approx(xyz)

    with pytest.raises(ValueError):
        pm.geodetic2ecef(lla0[0], lla0[1], -1)

    with pytest.raises(ValueError):
        pm.geodetic2ecef(-100, lla0[1], lla0[2])

    with pytest.raises(ValueError):
        pm.geodetic2ecef(lla0[0], -200, lla0[2])

    assert pm.ecef2geodetic(*xyz) == approx(lla0)
    assert pm.ecef2geodetic(*xyz, deg=False) == approx(rlla0)

    lla2 = pm.aer2geodetic(*aer0, *lla0)
    rlla2 = pm.aer2geodetic(*raer0, *rlla0, deg=False)

    with pytest.raises(ValueError):
        pm.aer2geodetic(aer0[0], aer0[1], -1, *lla0)

    assert lla2 == approx(lla1)
    assert rlla2 == approx(rlla1)

    assert pm.geodetic2aer(*lla2, *lla0) == approx(aer0)
    assert pm.geodetic2aer(*rlla2, *rlla0, deg=False) == approx(raer0)

    anan = np.empty((10, 10))
    anan.fill(np.nan)
    assert np.isnan(pm.geodetic2aer(anan, anan, anan, *lla0)).all()
    assert np.isnan(pm.aer2geodetic(anan, anan, anan, *lla0)).all()
예제 #2
0
def getIonosphericPiercingPoints(rx_xyz, sv, obstimes, ipp_alt, navfn,
                                 cs='wsg84', rx_xyz_coords='xyz', el0=0):
    """
    Sebastijan Mrak
    Function returns a list of Ionospheric Piersing Point (IPP) trajectory in WSG84
    coordinate system (CS). Function takes as parameter a receiver location in 
    ECEF CS, satellite number, times ob observation and desired altitude of a IPP
    trajectory. You also have to specify a full path to th navigation data file.
    It returns IPP location in either WSG84 or AER coordinate system.
    """
    
    ipp_alt = ipp_alt * 1E3
    if rx_xyz_coords == 'xyz':
        rec_lat, rec_lon, rec_alt = ecef2geodetic(rx_xyz[0], rx_xyz[1], rx_xyz[2])
    else:
        if not isinstance(rx_xyz, list): rx_xyz = list(rx_xyz)
        if len(rx_xyz) == 2: rx_xyz.append(0)
        assert len(rx_xyz) == 3
        
        rec_lat = rx_xyz[0]
        rec_lon = rx_xyz[1]
        rec_alt = rx_xyz[2]
        rx_xyz = geodetic2ecef(lat = rec_lon, lon = rec_lat, alt = rec_alt)
    
    if sv[0] == 'G':
        if navfn.endswith('n'):
            xyz = gpsSatPosition(navfn, obstimes, sv=sv, rx_position=rx_xyz, coords='xyz')
        elif navfn.endswith('sp3'):
            xyz = gpsSatPositionSP3(navfn, obstimes, sv=sv, rx_position=rx_xyz, coords='xyz')
        az,el,r = ecef2aer(xyz[0,:],xyz[1,:],xyz[2,:],rec_lat, rec_lon, rec_alt)
        aer_vector = np.array([az, el, r])
        
        r_new = []
        for i in range(len(el)):
            if el[i] > el0:
                fm = np.sin(np.radians(el[i]))
                r_new.append(ipp_alt / fm)
            else:
                r_new.append(np.nan)
        lla_vector = np.array(aer2geodetic(az, el, r_new, rec_lat, rec_lon, rec_alt))
        
    elif sv[0] == 'R':
        aer_vector = gloSatPosition(navfn=navfn, sv=sv, obstimes=obstimes, rx_position=[rec_lon, rec_lat, rec_alt], cs='aer')
        fm = np.sin(np.radians(aer_vector[1]))
        r_new = ipp_alt / fm
        lla_vector = np.array(aer2geodetic(aer_vector[0], aer_vector[1], r_new, rec_lat, rec_lon, rec_alt))
    else:
        print ('Type in valid sattype initial. "G" for GPS and "R" for GLONASS')
        
    if (cs == 'wsg84'):
        return lla_vector
    elif (cs == 'aer'):
        return aer_vector
    else:
        print ('Enter either "wsg84" or "aer" as coordinate system. "wsg84" is default one.')
예제 #3
0
def test_aer():
    lla2 = pm.aer2geodetic(*aer0, *lla0)
    rlla2 = pm.aer2geodetic(*raer0, *rlla0, deg=False)

    with pytest.raises(ValueError):
        pm.aer2geodetic(aer0[0], aer0[1], -1, *lla0)

    assert lla2 == approx(lla1)
    assert rlla2 == approx(rlla1)

    assert pm.geodetic2aer(*lla2, *lla0) == approx(aer0)
    assert pm.geodetic2aer(*rlla2, *rlla0, deg=False) == approx(raer0)
예제 #4
0
def test_aer():
    lla2 = pm.aer2geodetic(*aer0, *lla0)
    rlla2 = pm.aer2geodetic(*raer0, *rlla0, deg=False)

    with pytest.raises(ValueError):
        pm.aer2geodetic(aer0[0], aer0[1], -1, *lla0)

    assert lla2 == approx(lla1)
    assert rlla2 == approx(rlla1)

    assert pm.geodetic2aer(*lla2, *lla0) == approx(aer0)
    assert pm.geodetic2aer(*rlla2, *rlla0, deg=False) == approx(raer0)
예제 #5
0
def test_aer_geodetic(aer, lla, lla0):
    assert pm.aer2geodetic(*aer, *lla0) == approx(lla)

    raer = (radians(aer[0]), radians(aer[1]), aer[2])
    rlla0 = (radians(lla0[0]), radians(lla0[1]), lla0[2])
    assert pm.aer2geodetic(*raer, *rlla0, deg=False) == approx((radians(lla[0]), radians(lla[1]), lla[2]))

    with pytest.raises(ValueError):
        pm.aer2geodetic(aer[0], aer[1], -1, *lla0)

    assert pm.geodetic2aer(*lla, *lla0) == approx(aer, rel=1e-3)
    assert pm.geodetic2aer(radians(lla[0]), radians(lla[1]), lla[2], *rlla0, deg=False) == approx(raer, rel=1e-3)
예제 #6
0
def test_ned():
    xyz = pm.aer2ecef(*aer0, *lla0)
    enu = pm.aer2enu(*aer0)
    ned = (enu[1], enu[0], -enu[2])
    lla = pm.aer2geodetic(*aer0, *lla0)

    assert pm.aer2ned(*aer0) == approx(ned0)

    with pytest.raises(ValueError):
        pm.aer2ned(aer0[0], aer0[1], -1)

    assert pm.enu2aer(*enu) == approx(aer0)
    assert pm.enu2aer(*enu, deg=False) == approx(raer0)

    assert pm.ned2aer(*ned) == approx(aer0)

    assert pm.ecef2ned(*xyz, *lla0) == approx(ned)

    assert pm.ned2ecef(*ned, *lla0) == approx(xyz)
    # %%
    assert pm.ecef2enuv(vx, vy, vz, *lla0[:2]) == approx((ve, vn, vu))

    assert pm.ecef2nedv(vx, vy, vz, *lla0[:2]) == approx((vn, ve, -vu))

    # %%
    enu3 = pm.geodetic2enu(*lla, *lla0)
    ned3 = (enu3[1], enu3[0], -enu3[2])

    assert pm.geodetic2ned(*lla, *lla0) == approx(ned3)

    assert pm.enu2geodetic(*enu3, *lla0) == approx(lla)

    assert pm.ned2geodetic(*ned3, *lla0) == approx(lla)
예제 #7
0
def test_ned():
    xyz = pm.aer2ecef(*aer0, *lla0)
    enu = pm.aer2enu(*aer0)
    ned = (enu[1], enu[0], -enu[2])
    lla = pm.aer2geodetic(*aer0, *lla0)

    assert pm.aer2ned(*aer0) == approx(ned0)

    with pytest.raises(ValueError):
        pm.aer2ned(aer0[0], aer0[1], -1)

    assert pm.enu2aer(*enu) == approx(aer0)
    assert pm.enu2aer(*enu, deg=False) == approx(raer0)

    assert pm.ned2aer(*ned) == approx(aer0)

    assert pm.ecef2ned(*xyz, *lla0) == approx(ned)

    assert pm.ned2ecef(*ned, *lla0) == approx(xyz)
# %%
    assert pm.ecef2enuv(vx, vy, vz, *lla0[:2]) == approx((ve, vn, vu))

    assert pm.ecef2nedv(vx, vy, vz, *lla0[:2]) == approx((vn, ve, -vu))

# %%
    enu3 = pm.geodetic2enu(*lla, *lla0)
    ned3 = (enu3[1], enu3[0], -enu3[2])

    assert pm.geodetic2ned(*lla, *lla0) == approx(ned3)

    assert pm.enu2geodetic(*enu3, *lla0) == approx(lla)

    assert pm.ned2geodetic(*ned3, *lla0) == approx(lla)
예제 #8
0
def asi_projection(dat: xarray.Dataset, projalt_m: float = None, min_el: float = 10.0, ofn: Path = None):
    """
    plots ASI projected to altitude

    * dat: Xarray containing image stack and metadata (az, el, lat, lon)
    * projalt_m: projection altitude in meters
    * min_el: minimum elevation angle (degrees). Data near the horizon is poorly calibrated (large angular error).
    * ofn: filename to write of plot (optional)
    """
    if projalt_m is None:
        logging.error("projection altitude must be specified")
        return

    if dat["imgs"].shape[0] == 0:
        return

    if ofn:
        ofn = Path(ofn).expanduser()
        odir = ofn.parent

    # %% censor pixels near the horizon with large calibration error do to poor skymap fits
    badpix = dat["el"] < min_el
    az = dat["az"].values
    el = dat["el"].values
    az[badpix] = np.nan
    el[badpix] = np.nan
    # %% coordinate transformation, let us know if error occurs
    slant_range = projalt_m / np.sin(np.radians(el))

    lat, lon, alt = pm.aer2geodetic(az, el, slant_range, dat.lat.item(), dat.lon.item(), dat.alt_m.item())
    # %% plots
    fg = figure()
    ax = fg.gca()

    hi = pcolormesh_nan(lon, lat, dat["imgs"][0], cmap="gray", axis=ax)  # priming

    ttxt = f"Themis ASI {dat.site}  projected to altitude {projalt_m/1e3} km\n"  # FOV vs. HST0,HST1: green,red '
    ht = ax.set_title(ttxt, color="g")
    ax.set_xlabel("longitude")
    ax.set_ylabel("latitude")
    ax.autoscale(True, tight=True)
    ax.grid(False)
    # %% plot narrow FOV outline
    if "imgs2" in dat:
        overlayrowcol(ax, dat.rows, dat.cols)
    # %% play video
    try:
        for im in dat["imgs"]:
            ts = im.time.values.astype(str)[:-6]
            hi.set_array(im.values.ravel())  # for pcolormesh
            ht.set_text(ttxt + ts)
            draw()
            pause(0.01)
            if ofn:
                fn = odir / (ofn.stem + ts + ofn.suffix)
                print("saving", fn, end="\r")
                fg.savefig(fn, bbox_inches="tight", facecolor="k")
    except KeyboardInterrupt:
        return
예제 #9
0
def aer2ipp(aer, rxp, H=350):
    H*=1e3
    aer_new = np.copy(aer)
    fm = np.sin(np.radians(aer[:,:,1]))
    aer_new[:,:,2] = (H / fm)
    rxp
    ipp = np.array(aer2geodetic(aer_new[:,:,0], aer_new[:,:,1], aer_new[:,:,2], 
                                rxp[0], rxp[1], rxp[2]))
    return ipp
예제 #10
0
def projected_coord(imgs: xarray.Dataset, ind: np.ndarray, lla: Tuple[float, float, float]):
    az = imgs.az[ind[:, 0], ind[:, 1]].values.squeeze()
    el = imgs.el[ind[:, 0], ind[:, 1]].values.squeeze()

    alt_m = lla[2] * 1000 if lla is not None else 100e3

    plat, plon, palt_m = pm.aer2geodetic(az, el, alt_m / np.sin(np.radians(el)), imgs.lat, imgs.lon, imgs.alt_m)

    return az, el, plat, plon, palt_m
예제 #11
0
파일: pyGnss.py 프로젝트: yihanGPS/pyGnss
def dataFromNC(fnc,
               fnav,
               sv,
               fsp3=None,
               el_mask=30,
               tlim=None,
               satpos=False,
               ipp=False,
               ipp_alt=None):
    leap_seconds = uf.getLeapSeconds(fnav)
    D = gr.load(fnc, useindicators=True).sel(sv=sv)
    D['time'] = np.array([np.datetime64(ttt) for ttt in D.time.values])
    if tlim is not None:
        if len(tlim) == 2:
            D = D.where(np.logical_and(D.time >= np.datetime64(tlim[0]),
                                       D.time <= np.datetime64(tlim[1])),
                        drop=True)
    obstimes64 = D.time.values

    dt = np.array([Timestamp(t).to_pydatetime() for t in obstimes64]) - \
               datetime.timedelta(seconds = leap_seconds)
    if fsp3 is None:
        aer = gpsSatPosition(fnav,
                             dt,
                             sv=sv,
                             rx_position=D.position,
                             coords='aer')
    else:
        aer = gpsSatPositionSP3(fsp3,
                                dt,
                                sv=sv,
                                rx_position=D.position_geodetic,
                                coords='aer')
    idel = (aer[1, :] >= el_mask)
    aer[:, ~idel] = np.nan
    D['time'] = dt

    if satpos:
        D['az'] = aer[0, :]
        D['el'] = aer[1, :]
        D['idel'] = idel
    if ipp:
        if ipp_alt is None:
            print('Auto assigned altitude of the IPP: 250 km')
            ipp_alt = 250e3
        else:
            ipp_alt *= 1e3
        rec_lat, rec_lon, rec_alt = D.position_geodetic
        fm = np.sin(np.radians(aer[1]))
        r_new = ipp_alt / fm
        lla_vector = np.array(
            aer2geodetic(aer[0], aer[1], r_new, rec_lat, rec_lon, rec_alt))
        D['ipp_lon'] = lla_vector[1]
        D['ipp_lat'] = lla_vector[0]
        D['ipp_alt'] = ipp_alt
    return D
예제 #12
0
파일: gps.py 프로젝트: tucano1976/PyGPS
def getPP(satpos, sv, recpos, pph, err=1.0):
    """
    get az and el to the satellite and repeatedly increase the range,
    converting to LLA each time to check the altitude. Stop when all
    the altitudes are within err of pph. Inputs satellite position
    array in ECEF, satellite number, receiver position in ECEF, pierce point
    height in km and error in km if you want.
    """

    rlat, rlon, ralt = ecef2geodetic(recpos)
    sataz, satel, satr = ecef2aer(satpos[:, 0], satpos[:, 1], satpos[:, 2],
                                  rlat, rlon, ralt)

    r = np.zeros(len(satr))
    pplat, pplon, ppalt = aer2geodetic(sataz, satel, r, rlat, rlon, ralt)
    mask = (ppalt / 1000 - pph) < 0

    while np.sum(mask) > 0:
        r[mask] += 100
        pplat, pplon, ppalt = aer2geodetic(sataz, satel, r * 1000, rlat, rlon,
                                           ralt)
        mask = (ppalt / 1000 - pph) < 0

    sRange = r - 100.0
    eRange = r
    count = 0
    while not np.all(abs(ppalt / 1000 - pph) < err):
        count += 1
        mRange = (sRange + eRange) / 2.0
        pplat, pplon, ppalt = aer2geodetic(sataz, satel, mRange * 1000, rlat,
                                           rlon, ralt)
        mask = ppalt / 1000 > pph
        eRange[mask] = mRange[mask]
        sRange[~mask] = mRange[~mask]

        if (count > 100):
            raise TypeError('going too long')
            break

    ppalt = pph * 1000

    return pplat, pplon, ppalt
예제 #13
0
def plot4d(atmos: xarray.Dataset, rodir: Path = None):
    if aer2geodetic is None:
        return

    for i, t in enumerate(atmos.time):
        time = Time(str(t.values))
        obs = EarthLocation(0, 0)  # geodetic lat,lon = 0,0 arbitrary
        sun = get_sun(time=time)
        aaf = AltAz(obstime=time, location=obs)
        sloc = sun.transform_to(aaf)
        slat, slon = aer2geodetic(sloc.az.value, sloc.alt.value,
                                  sloc.distance.value, 0, 0, 0)[:2]

        plot2dlatlon(atmos.sel(time=t), rodir, slat, slon)
예제 #14
0
def _toLLT(rxp=None, az=None, el=None, H=350):
    """
    Default height of the IPP is 350 km.
    """
    H *= 1e3
    r = H / np.sin(np.radians(el))
    lat, lon, alt = aer2geodetic(az=az,
                                 el=el,
                                 srange=r,
                                 lat0=rxp[0],
                                 lon0=rxp[1],
                                 h0=rxp[2])

    return lat, lon
예제 #15
0
def test_aer_geodetic(aer, lla, lla0):
    lat1, lon1, alt1 = pm.aer2geodetic(*aer, *lla0)
    assert lat1 == approx(lla[0])
    assert lon1 == approx(lla[1])
    assert alt1 == approx(lla[2])
    assert isinstance(lat1, float)
    assert isinstance(lon1, float)
    assert isinstance(alt1, float)

    raer = (radians(aer[0]), radians(aer[1]), aer[2])
    rlla0 = (radians(lla0[0]), radians(lla0[1]), lla0[2])
    assert pm.aer2geodetic(*raer, *rlla0, deg=False) == approx(
        (radians(lla[0]), radians(lla[1]), lla[2]))

    with pytest.raises(ValueError):
        pm.aer2geodetic(aer[0], aer[1], -1, *lla0)

    assert pm.geodetic2aer(*lla, *lla0) == approx(aer, rel=1e-3)
    assert pm.geodetic2aer(radians(lla[0]),
                           radians(lla[1]),
                           lla[2],
                           *rlla0,
                           deg=False) == approx(raer, rel=1e-3)
예제 #16
0
def makeImage(dtec,
              xgrid,
              ygrid,
              longitude=None,
              latitude=None,
              azimuth=None,
              elevation=None,
              rxp=None,
              altkm=None,
              im=np.nan):
    imout = np.nan * np.ones(im.shape, dtype=np.float32)
    lonlim = [np.min(xgrid), np.max(xgrid)]
    latlim = [np.min(ygrid), np.max(ygrid)]
    if azimuth is not None and elevation is not None and rxp is not None and altkm is not None:
        r1 = (altkm * 1e3) / np.sin(np.radians(elevation))
        h0 = rxp[:, 2]  #if rxp[2] >= 0 else 0
        ipp_lla = aer2geodetic(az=azimuth,
                               el=elevation,
                               srange=r1,
                               lat0=rxp[:, 0],
                               lon0=rxp[:, 1],
                               h0=h0)
        longitude = ipp_lla[1]
        latitude = ipp_lla[0]
    assert (longitude
            is not None) and (latitude
                              is not None), "Lat/Lon coordinates invalid!"

    for isv in range(dtec.shape[0]):
        for irx in np.where(np.isfinite(dtec[isv]))[0]:
            idx, idy = getImageIndex(x=longitude[isv, irx],
                                     y=latitude[isv, irx],
                                     xlim=lonlim,
                                     ylim=latlim,
                                     xgrid=xgrid,
                                     ygrid=ygrid)
            # If image indexes are valid
            if np.isfinite(idx) and np.isfinite(idy):
                if im[idx, idy] is None:
                    im[idx, idy] = [dtec[isv, irx]]
                else:
                    im[idx, idy].append(dtec[isv, irx])
    for i in range(im.shape[0]):
        for j in range(im.shape[1]):
            if im[i, j] is not None:
                imout[i, j] = np.nanmedian(im[i, j])

    return imout
예제 #17
0
파일: test_ned.py 프로젝트: nhz2/pymap3d
def test_ned_geodetic():
    lla = pm.aer2geodetic(*aer0, *lla0)

    enu3 = pm.geodetic2enu(*lla, *lla0)
    ned3 = (enu3[1], enu3[0], -enu3[2])

    assert pm.geodetic2ned(*lla, *lla0) == approx(ned3)

    lat, lon, alt = pm.enu2geodetic(*enu3, *lla0)
    assert lat == approx(lla[0])
    assert lon == approx(lla[1])
    assert alt == approx(lla[2])

    lat, lon, alt = pm.ned2geodetic(*ned3, *lla0)
    assert lat == approx(lla[0])
    assert lon == approx(lla[1])
    assert alt == approx(lla[2])
예제 #18
0
def test_ned_geodetic():
    lat1, lon1, alt1 = pm.aer2geodetic(*aer0, *lla0)

    enu3 = pm.geodetic2enu(lat1, lon1, alt1, *lla0)
    ned3 = (enu3[1], enu3[0], -enu3[2])

    assert pm.geodetic2ned(lat1, lon1, alt1, *lla0) == approx(ned3)

    lat, lon, alt = pm.enu2geodetic(*enu3, *lla0)
    assert lat == approx(lat1)
    assert lon == approx(lon1)
    assert alt == approx(alt1)
    assert isinstance(lat, float)
    assert isinstance(lon, float)
    assert isinstance(alt, float)

    lat, lon, alt = pm.ned2geodetic(*ned3, *lla0)
    assert lat == approx(lat1)
    assert lon == approx(lon1)
    assert alt == approx(alt1)
    assert isinstance(lat, float)
    assert isinstance(lon, float)
    assert isinstance(alt, float)
예제 #19
0
파일: test.py 프로젝트: cchuravy/pymap3d
def test_ecefenu():
    assert_allclose(pm.aer2ecef(taz, tel, tsrange, tlat, tlon, talt),
                    (a2x, a2y, a2z),
                    rtol=0.01,
                    err_msg='aer2ecef: {}'.format(
                        pm.aer2ecef(taz, tel, tsrange, tlat, tlon, talt)))

    assert_allclose(pm.aer2enu(taz, tel, tsrange), (a2e, a2n, a2u),
                    rtol=0.01,
                    err_msg='aer2enu: ' + str(pm.aer2enu(taz, tel, tsrange)))

    assert_allclose(pm.aer2ned(taz, tel, tsrange), (a2n, a2e, -a2u),
                    rtol=0.01,
                    err_msg='aer2ned: ' + str(pm.aer2ned(taz, tel, tsrange)))

    assert_allclose(pm.ecef2enu(tx, ty, tz, tlat, tlon, talt), (e2e, e2n, e2u),
                    rtol=0.01,
                    err_msg='ecef2enu: {}'.format(
                        pm.ecef2enu(tx, ty, tz, tlat, tlon, talt)))

    assert_allclose(pm.ecef2enuv(vx, vy, vz, tlat, tlon), (ve, vn, vu))

    assert_allclose(pm.ecef2ned(tx, ty, tz, tlat, tlon, talt),
                    (e2n, e2e, -e2u),
                    rtol=0.01,
                    err_msg='ecef2ned: {}'.format(
                        pm.ecef2enu(tx, ty, tz, tlat, tlon, talt)))

    assert_allclose(pm.ecef2nedv(vx, vy, vz, tlat, tlon), (vn, ve, -vu))

    assert_allclose(pm.aer2geodetic(taz, tel, tsrange, tlat, tlon, talt),
                    (a2la, a2lo, a2a),
                    rtol=0.01,
                    err_msg='aer2geodetic {}'.format(
                        pm.aer2geodetic(taz, tel, tsrange, tlat, tlon, talt)))

    assert_allclose(pm.ecef2aer(tx, ty, tz, tlat, tlon, talt),
                    (ec2az, ec2el, ec2rn),
                    rtol=0.01,
                    err_msg='ecef2aer {}'.format(
                        pm.ecef2aer(a2x, a2y, a2z, tlat, tlon, talt)))
    #%%
    assert_allclose(pm.enu2aer(te, tn, tu), (e2az, e2el, e2rn),
                    rtol=0.01,
                    err_msg='enu2aer: ' + str(pm.enu2aer(te, tn, tu)))

    assert_allclose(pm.ned2aer(tn, te, -tu), (e2az, e2el, e2rn),
                    rtol=0.01,
                    err_msg='enu2aer: ' + str(pm.enu2aer(te, tn, tu)))

    assert_allclose(pm.enu2geodetic(te, tn, tu, tlat, tlon,
                                    talt), (lat2, lon2, alt2),
                    rtol=0.01,
                    err_msg='enu2geodetic: ' +
                    str(pm.enu2geodetic(te, tn, tu, tlat, tlon, talt)))

    assert_allclose(pm.ned2geodetic(tn, te, -tu, tlat, tlon,
                                    talt), (lat2, lon2, alt2),
                    rtol=0.01,
                    err_msg='enu2geodetic: ' +
                    str(pm.enu2geodetic(te, tn, tu, tlat, tlon, talt)))

    assert_allclose(pm.enu2ecef(te, tn, tu, tlat, tlon, talt), (e2x, e2y, e2z),
                    rtol=0.01,
                    err_msg='enu2ecef: ' +
                    str(pm.enu2ecef(te, tn, tu, tlat, tlon, talt)))

    assert_allclose(
        pm.ned2ecef(tn, te, -tu, tlat, tlon, talt), (e2x, e2y, e2z),
        rtol=0.01,
        err_msg='ned2ecef: ' + str(pm.ned2ecef(tn, te, -tu, tlat, tlon, talt)))
예제 #20
0
def test_allnan():
    np = pytest.importorskip("numpy")
    anan = np.empty((10, 10))
    anan.fill(nan)
    assert np.isnan(pm.geodetic2aer(anan, anan, anan, *lla0)).all()
    assert np.isnan(pm.aer2geodetic(anan, anan, anan, *lla0)).all()
예제 #21
0
def test_scalar_nan():
    a, e, r = pm.geodetic2aer(nan, nan, nan, *lla0)
    assert isnan(a) and isnan(e) and isnan(r)

    lat, lon, alt = pm.aer2geodetic(nan, nan, nan, *lla0)
    assert isnan(lat) and isnan(lon) and isnan(alt)
예제 #22
0
def calculate_geo_point(point, az, el, srange):
    target = pymap3d.aer2geodetic(az, el, srange,
        point['lat'], point['lon'], point['alt'])
    return { 'lat': target[0], 'lon': target[1], 'alt': target[2] }
예제 #23
0
def plotgtd(dens,temp,dtime,altkm, ap, f107,glat,glon,rodir=None):
#
    if rodir:
        rodir = Path(rodir).expanduser()

    dtime = atleast_1d(dtime)
    sfmt = ScalarFormatter(useMathText=True) #for 10^3 instead of 1e3
    sfmt.set_powerlimits((-2, 2))
    sfmt.set_scientific(True)
    sfmt.set_useOffset(False)

    if dens.ndim==2: #altitude 1-D
        plot1d(dens,temp,glat,glon,ap,f107)
    elif dens.ndim==4: #lat/lon grid
#%% sun lat/lon
        ttime = Time(dtime)
        obs = EarthLocation(0,0) # geodetic lat,lon = 0,0 arbitrary
        sun = get_sun(time=ttime)
        aaf = AltAz(obstime=ttime,location=obs)
        sloc = sun.transform_to(aaf)
        slat,slon = aer2geodetic(sloc.az.value, sloc.alt.value, sloc.distance.value,0,0,0)[:2]
#%%
        #iterate over time
        for k,d in enumerate(dens): #dens is a 4-D array  time x species x lat x lon
            fg,ax = subplots(4,2,sharex=True, figsize=(8,8))
            fg.suptitle(datetime.fromtimestamp(d.time.item()/1e9, tz=UTC).isoformat(timespec='minutes') +
                        f' alt.(km) {altkm}\nAp={ap[0]}  F10.7={f107}')
            ax=ax.ravel(); i = 0 #don't use enumerate b/c of skip

            #iterate over species
            for s in d:
                thisspecies = s.species.values
                if thisspecies != 'Total':
                    a = ax[i]

                    hi = a.imshow(s.values, aspect='auto',
                            interpolation='none',cmap='viridis',
                             extent=(glon[0,0],glon[0,-1],glat[0,0],glat[-1,0]))
                    fg.colorbar(hi,ax=a, format=sfmt)

                    a.plot(slon[k],slat[k],linestyle='none',
                                        marker='o',markersize=5,color='w')

                    a.set_title(f'Density: {thisspecies}')
                    a.set_xlim(-180,180)
                    a.set_ylim(-90,90)
                    a.autoscale(False)
                    i+=1
            for i in range(0,6+2,2):
                ax[i].set_ylabel('latitude (deg)')
            for i in (6,7):
                ax[i].set_xlabel('longitude (deg)')

            if rodir:
                thisofn = rodir / f'{altkm[0]:.1f}_{k:03d}.png'
                print('writing',thisofn)
                fg.savefig(str(thisofn), dpi=100, bbox_inches='tight')
                close()
    else:
        print('densities',dens)
        print('temperatures',temp)
예제 #24
0
def map_target(tx, rx, az, el, rf, dop, wavelength):
    """
    Find the scatter location given tx location, rx location, total rf distance, and target angle-of-arrival
    using the 'WGS84' Earth model. Also determines the bistatic velocity vector and bistatic radar wavelength.

    Parameters
    ----------
        tx : float np.array
            [latitude, longitude, altitude] of tx array in degrees and kilometers
        rx : float np.array
            [latitude, longitude, altitude] of rx array in degrees and kilometers
        az : float np.array
            angle-of-arrival azimuth in degrees
        el : float np.array
            angle-of-arrival elevation in degrees
        rf : float np.array
            total rf path distance rf = c * tau in kilometers
        dop : float np.array
            doppler shift in hertz
        wavelength : float
            radar signal center wavelength

    Returns
    -------
        sx : float np.array
            [latitude, longitude, altitude] of scatter in degrees and kilometers
        sa : float np.array
            [azimuth, elevation, slant range] of scatter in degrees and kilometers
        sv : float np.array
            [azimuth, elevation, velocity] the bistatic Doppler velocity vector in degrees and kilometers.
            Coordinates given in the scattering targets local frame (azimuth from North, elevation up from
            the plane normal to zenith, Doppler [Hz] * lambda / (2 cos(e/2)) )

    Notes
    -----
    tx : transmitter location
    rx : receiver location
    sx : scatter location
    gx : geometric center of Earth, origin
    u_rt : unit vector rx to tx
    u_rs : unit vector rx to sx
    u_gt : unit vector gx to tx
    u_gr : unit vector gx to rx
    u_gs : unit vector gx to sx
    """

    # Initialize output arrays
    sx = np.zeros((3, len(rf)), dtype=float)
    sa = np.zeros((3, len(rf)), dtype=float)
    sv = np.zeros((3, len(rf)), dtype=float)

    # Setup variables in correct units for pymap3d
    rf = rf * 1.0e3
    az = np.where(az < 0.0, az + 360.0, az)
    az = np.deg2rad(az)
    el = np.deg2rad(np.abs(el))

    # Determine the slant range, r
    bx1, by1, bz1 = pm.geodetic2ecef(rx[0],
                                     rx[1],
                                     rx[2],
                                     ell=pm.Ellipsoid("wgs84"),
                                     deg=True)
    v_gr = np.array([bx1, by1, bz1])
    bx2, by2, bz2 = pm.geodetic2ecef(tx[0],
                                     tx[1],
                                     tx[2],
                                     ell=pm.Ellipsoid("wgs84"),
                                     deg=True)
    v_gt = np.array([bx2, by2, bz2])
    raz, rel, b = pm.ecef2aer(bx2,
                              by2,
                              bz2,
                              rx[0],
                              rx[1],
                              rx[2],
                              ell=pm.Ellipsoid("wgs84"),
                              deg=True)
    u_rt = np.array([
        np.sin(np.deg2rad(raz)) * np.cos(np.deg2rad(rel)),
        np.cos(np.deg2rad(raz)) * np.cos(np.deg2rad(rel)),
        np.sin(np.deg2rad(rel))
    ])
    el -= relaxation_elevation(el, rf, az, b, u_rt)
    u_rs = np.array(
        [np.sin(az) * np.cos(el),
         np.cos(az) * np.cos(el),
         np.sin(el)])
    r = (rf**2 - b**2) / (2 * (rf - b * np.dot(u_rt, u_rs)))

    # WGS84 Model for lat, long, alt
    sx[:, :] = pm.aer2geodetic(np.rad2deg(az),
                               np.rad2deg(el),
                               np.abs(r),
                               np.repeat(rx[0], len(az)),
                               np.repeat(rx[1], len(az)),
                               np.repeat(rx[2], len(az)),
                               ell=pm.Ellipsoid("wgs84"),
                               deg=True)

    # Determine the bistatic Doppler velocity vector
    x, y, z = pm.geodetic2ecef(sx[0, :],
                               sx[1, :],
                               sx[2, :],
                               ell=pm.Ellipsoid('wgs84'),
                               deg=True)
    v_gs = np.array([x, y, z])
    v_bi = (-1 * v_gs.T + v_gt / 2.0 + v_gr / 2.0).T
    u_bi = v_bi / np.linalg.norm(v_bi, axis=0)
    v_sr = (v_gr - v_gs.T).T
    u_sr = v_sr / np.linalg.norm(v_sr, axis=0)
    radar_wavelength = wavelength / np.abs(
        2.0 * np.einsum('ij,ij->j', u_sr, u_bi))
    # doppler_sign = np.sign(dop)  # 1 for positive, -1 for negative, and 0 for zero
    doppler_sign = np.where(
        dop >= 0, 1, -1)  # 1 for positive, -1 for negative, and 0 for zero
    vaz, vel, _ = pm.ecef2aer(doppler_sign * u_bi[0, :] + x,
                              doppler_sign * u_bi[1, :] + y,
                              doppler_sign * u_bi[2, :] + z,
                              sx[0, :],
                              sx[1, :],
                              sx[2, :],
                              ell=pm.Ellipsoid("wgs84"),
                              deg=True)

    # Convert back to conventional units
    sx[2, :] /= 1.0e3
    az = np.rad2deg(az)
    el = np.rad2deg(el)
    sa[:, :] = np.array([az, el, r / 1.0e3])
    sv[:, :] = np.array([vaz, vel, dop * radar_wavelength])

    return sx, sa, sv
예제 #25
0
def plotgtd(atmos: xarray.Dataset, rodir=None):
    #
    if rodir:
        rodir = Path(rodir).expanduser()

    sfmt = ScalarFormatter(useMathText=True)  #for 10^3 instead of 1e3
    sfmt.set_powerlimits((-2, 2))
    sfmt.set_scientific(True)
    sfmt.set_useOffset(False)

    if atmos['N2'].squeeze().ndim == 1:  #altitude 1-D
        plot1d(atmos)
    elif atmos['N2'].squeeze().ndim == 4:  #lat/lon grid
        #%% sun lat/lon
        time = Time(str(atmos.time[0].values))
        obs = EarthLocation(0, 0)  # geodetic lat,lon = 0,0 arbitrary
        sun = get_sun(time=time)
        aaf = AltAz(obstime=time, location=obs)
        sloc = sun.transform_to(aaf)
        slat, slon = aer2geodetic(sloc.az.value, sloc.alt.value,
                                  sloc.distance.value, 0, 0, 0)[:2]
        slat = np.atleast_1d(slat)
        slon = np.atleast_1d(slon)
        #%% tableau
        for i, t in enumerate(atmos.time):
            fg = figure(figsize=(8, 8))
            ax = fg.subplots(4, 2, sharex=True)
            fg.suptitle(
                str(t.values)[:-13] + f' alt.(km) {atmos.alt_km[0]}\n'
                f'Ap={atmos.Ap[0]}  F10.7={atmos.f107.item()}')
            ax = ax.ravel()

            j = 0
            for s in atmos.species:
                if s == 'Total':
                    continue

                a = ax[j]

                hi = a.imshow(atmos[s][i][0],
                              aspect='auto',
                              interpolation='none',
                              cmap='viridis',
                              extent=(atmos.lon[0], atmos.lon[-1],
                                      atmos.lat[0], atmos.lat[-1]))

                fg.colorbar(hi, ax=a, format=sfmt)
                # %% sun icon moving
                a.plot(slon[i],
                       slat[i],
                       linestyle='none',
                       marker='o',
                       markersize=5,
                       color='w')

                a.set_title(f'Density: {s}')
                a.set_xlim(-180, 180)
                a.set_ylim(-90, 90)
                a.autoscale(False)
                j += 1

            for k in range(0, 6 + 2, 2):
                ax[k].set_ylabel('latitude (deg)')
            for k in (6, 7):
                ax[k].set_xlabel('longitude (deg)')

            if rodir:
                ofn = rodir / f'{atmos.alt_km[0].item():.1f}_{i:03d}.png'
                print('writing', ofn)
                fg.savefig(ofn, dpi=100, bbox_inches='tight')
                close()

    else:
        print(atmos)
예제 #26
0
    def test_geodetic(self):
        if pyproj:
            ecef = pyproj.Proj(proj='geocent', ellps='WGS84', datum='WGS84')
            lla = pyproj.Proj(proj='latlong', ellps='WGS84', datum='WGS84')

        xyz1 = pm.geodetic2ecef(*lla0)

        assert_allclose(pm.geodetic2ecef(*rlla0, deg=False),
                        xyz1,
                        err_msg='geodetic2ecef: rad')
        assert_allclose(xyz1, xyz0, err_msg='geodetic2ecef: deg')

        assert_allclose(pm.ecef2geodetic(*xyz1),
                        lla0,
                        err_msg='ecef2geodetic: deg')
        assert_allclose(pm.ecef2geodetic(*xyz1, deg=False),
                        rlla0,
                        err_msg='ecef2geodetic: rad')

        if pyproj:
            assert_allclose(
                pyproj.transform(lla, ecef, lla0[1], lla0[0], lla0[2]), xyz1)
            assert_allclose(pyproj.transform(ecef, lla, *xyz1),
                            (lla0[1], lla0[0], lla0[2]))

        lla2 = pm.aer2geodetic(*aer0, *lla0)
        rlla2 = pm.aer2geodetic(*raer0, *rlla0, deg=False)

        assert_allclose(lla2, lla1, err_msg='aer2geodetic: deg')
        assert_allclose(rlla2, rlla1, err_msg='aer2geodetic:rad')

        assert_allclose(pm.geodetic2aer(*lla2, *lla0),
                        aer0,
                        err_msg='geodetic2aer: deg')
        assert_allclose(pm.geodetic2aer(*rlla2, *rlla0, deg=False),
                        raer0,
                        err_msg='geodetic2aer: rad')

        # %% aer-ecef
        xyz2 = pm.aer2ecef(*aer0, *lla0)

        assert_allclose(pm.aer2ecef(*raer0, *rlla0, deg=False),
                        axyz0,
                        err_msg='aer2ecef:rad')

        assert_allclose(xyz2, axyz0, err_msg='aer2ecef: deg')

        assert_allclose(pm.ecef2aer(*xyz2, *lla0),
                        aer0,
                        err_msg='ecef2aer:deg')
        assert_allclose(pm.ecef2aer(*xyz2, *rlla0, deg=False),
                        raer0,
                        err_msg='ecef2aer:rad')
        # %% aer-enu
        enu1 = pm.aer2enu(*aer0)
        ned1 = (enu1[1], enu1[0], -enu1[2])

        assert_allclose(enu1, enu0, err_msg='aer2enu: deg')
        assert_allclose(pm.aer2enu(*raer0, deg=False),
                        enu0,
                        err_msg='aer2enu: rad')

        assert_allclose(pm.aer2ned(*aer0), ned0, err_msg='aer2ned')

        assert_allclose(pm.enu2aer(*enu1), aer0, err_msg='enu2aer: deg')
        assert_allclose(pm.enu2aer(*enu1, deg=False),
                        raer0,
                        err_msg='enu2aer: rad')

        assert_allclose(pm.ned2aer(*ned1), aer0, err_msg='ned2aer')

        # %% enu-ecef
        assert_allclose(pm.enu2ecef(*enu1, *lla0),
                        xyz2,
                        err_msg='enu2ecef: deg')
        assert_allclose(pm.enu2ecef(*enu1, *rlla0, deg=False),
                        xyz2,
                        err_msg='enu2ecef: rad')

        assert_allclose(pm.ecef2enu(*xyz2, *lla0),
                        enu1,
                        err_msg='ecef2enu:deg')
        assert_allclose(pm.ecef2enu(*xyz2, *rlla0, deg=False),
                        enu1,
                        err_msg='ecef2enu:rad')

        assert_allclose(pm.ecef2ned(*xyz2, *lla0), ned1, err_msg='ecef2ned')

        assert_allclose(pm.ned2ecef(*ned1, *lla0), xyz2, err_msg='ned2ecef')
        # %%
        assert_allclose(pm.ecef2enuv(vx, vy, vz, *lla0[:2]), (ve, vn, vu))

        assert_allclose(pm.ecef2nedv(vx, vy, vz, *lla0[:2]), (vn, ve, -vu))

        # %%
        enu3 = pm.geodetic2enu(*lla2, *lla0)
        ned3 = (enu3[1], enu3[0], -enu3[2])

        assert_allclose(pm.geodetic2ned(*lla2, *lla0),
                        ned3,
                        err_msg='geodetic2ned: deg')

        assert_allclose(pm.enu2geodetic(*enu3, *lla0),
                        lla2,
                        err_msg='enu2geodetic')

        assert_allclose(pm.ned2geodetic(*ned3, *lla0),
                        lla2,
                        err_msg='ned2geodetic')
예제 #27
0
def test_allnan():

    anan = np.empty((10, 10))
    anan.fill(nan)
    assert np.isnan(pm.geodetic2aer(anan, anan, anan, *lla0)).all()
    assert np.isnan(pm.aer2geodetic(anan, anan, anan, *lla0)).all()
예제 #28
0
aaf = AltAz(obstime=time, location=obs)
sloc = sun.transform_to(aaf)
# %%
time = time.to_datetime()

fg = figure()
ax = fg.subplots(2, 1, sharex=True)
ax[0].plot(time, sloc.alt)
ax[0].set_title('sun elevation')
ax[0].set_ylabel('elevation [deg]')

ax[1].plot(time, sloc.az)
ax[1].set_title('sun azimuth')
ax[1].set_ylabel('azimuth [deg]')
ax[1].set_xlabel('time')

fg.suptitle(f'sun over 1 year @ lat,lon,alt: {obslla}')

# %%

lat, lon, alt = aer2geodetic(sloc.az.value, sloc.alt.value,
                             sloc.distance.value, *obslla)

ax = figure().gca()
ax.plot(time, lat)
ax.set_title('subsolar latitude vs. time')
ax.set_ylabel('latitude [deg]')
ax.set_xlabel('time')

show()
예제 #29
0
import cartopy.crs as ccrs
import dascutils.io as dio
import pymap3d as pm
from pathlib import Path

PC = ccrs.PlateCarree()
ST = ccrs.Stereographic()
MR = ccrs.Mercator()
R = Path('~/code/dascutils/').expanduser()

dat = dio.load(R / 'tests', R / 'cal/PKR_DASC_20110112')
img = dat[428].isel(time=1).values
# %% coord conv.
alt = 100000
srange = alt / np.sin(np.radians(dat.el.values))
lat, lon, alt = pm.aer2geodetic(dat.az.values, dat.el.values, srange, dat.lat,
                                dat.lon, 0)

mask = np.isfinite(lat)
top = None
for i, m in enumerate(mask):
    good = m.nonzero()[0]

    if good.size == 0:
        continue
    elif top is None:
        top = i

    lat[i, good[-1]:] = lat[i, good[-1]]
    lat[i, :good[0]] = lat[i, good[0]]

    lon[i, good[-1]:] = lon[i, good[-1]]
예제 #30
0
            cax = fig.add_axes([posn.x0, posn.y0 - 0.03, posn.width, 0.02])
            fig.colorbar(tecax,
                         cax=cax,
                         label='TEC [TECu]',
                         orientation='horizontal')

        # Plot image
        gpsdata = h5py.File(gpsfn, 'r')
        el = np.nanmedian(gpsdata['el'][i - average:i + 1], axis=0)
        az = np.nanmedian(gpsdata['az'][i - average:i + 1], axis=0)
        r1 = (altkm * 1e3) / np.sin(np.radians(el))
        h0 = np.nan_to_num(rxp[:, 2])
        h0[h0 < 0] = 0
        ipp_lla = aer2geodetic(az=az,
                               el=el,
                               srange=r1,
                               lat0=rxp[:, 0],
                               lon0=rxp[:, 1],
                               h0=h0)
        glon = ipp_lla[1]
        glat = ipp_lla[0]
        try:
            # Convert coordinates
            #            rotia = np.nanmedian(gpsdata['roti'][i-average:i+1, :, :], axis=0) * 60
            idf = np.isfinite(glon) & np.isfinite(glat)
            if i > average and i < dt.size:
                rotia = np.nanmedian(gpsdata['roti'][i - average:i + 1],
                                     axis=0) * 60
            elif average > i:
                rotia = np.nanmedian(gpsdata['roti'][i:i + 2], axis=0) * 60
            else:
                rotia = np.nanmedian(gpsdata['roti'][i - average:i],
예제 #31
0
def create_start_point(origin_offset, target):
    point = pymap3d.aer2geodetic(origin_offset['az'], origin_offset['el'], origin_offset['srange'],
        target['lat'], target['lon'], target['alt'])
    return { 'lat': point[0], 'lon': point[1], 'alt': point[2] }
예제 #32
0
    if el_filter is not None:
        el = np.where(el >= el_filter, el, np.nan)
        az = np.where(el >= el_filter, az, np.nan)
    # Reshape calibration files
    if im_test.shape != el.shape:
        el = pa.interpolateCoordinate(el, N=im_test.shape[0])
        az = pa.interpolateCoordinate(az, N=im_test.shape[0])
    # LLA
    # Map to altitude
    mapping_alt = 100000
    r = mapping_alt / np.sin(np.deg2rad(el))
    # Convert to WSG
    lat0 = data.lat
    lon0 = data.lon
    alt0 = data.alt_m
    lat, lon, alt = aer2geodetic(az, el, r, lat0, lon0, alt0)
    # Image
    for i in range(T.shape[0]):
        im = data[wl][i].values
        XG, YG, Zlla = pa.interpolateAS(lon, lat, im, N=N)
        asiplot.plotIMmap(XG,
                          YG,
                          Zlla,
                          title=T[i],
                          cmap='Greys_r',
                          clim=[500, 4000])

if cfg == 'lla':
    t, xgrid, ygrid, im, [lon, lat,
                          alt] = pa.returnASLatLonAlt(folder,
                                                      azfn=azfn,
예제 #33
0
def test_allnan():

    anan = np.empty((10, 10))
    anan.fill(nan)
    assert np.isnan(pm.geodetic2aer(anan, anan, anan, *lla0)).all()
    assert np.isnan(pm.aer2geodetic(anan, anan, anan, *lla0)).all()