def test_convert_latlon_lat_failure(self):
        """Test error return for co-latitudes above 90 for a single value"""
        with pytest.raises(AssertionError):
            aacgmv2.convert_latlon(91, 0, 300, self.dtime)

        with pytest.raises(AssertionError):
            aacgmv2.convert_latlon(-91, 0, 300, self.dtime)
    def test_convert_latlon_datetime_date(self):
        """Test single latlon conversion with date and datetime input"""
        (self.lat_out, self.lon_out,
         self.r_out) = aacgmv2.convert_latlon(60, 0, 300, self.ddate)
        lat_2, lon_2, r_2 = aacgmv2.convert_latlon(60, 0, 300, self.dtime)

        if self.lat_out != lat_2:
            raise AssertionError()
        if self.lon_out != lon_2:
            raise AssertionError()
        if self.r_out != r_2:
            raise AssertionError()

        del lat_2, lon_2, r_2
Beispiel #3
0
def convert_azm_aacgm2geo(azM, latG, lonG, dTime, refAlt=300):
    # Convert azimuths from AACGM to geodetic

    refZ = -refAlt * 1E3  # nvector uses z = height in metres down
    wgs84 = nv.FrameE(name='WGS84')
    nPole = aacgmv2.convert_latlon(90, 0, refAlt, dTime, method_code="A2G")

    geoAzimuths = np.ones(azM.shape) * np.nan

    for ind, mAzm in enumerate(azM):

        pointA = wgs84.GeoPoint(
            latitude=latG[ind],
            longitude=lonG[ind],
            z=refZ,
            degrees=True,
        )
        pointPole = wgs84.GeoPoint(
            latitude=nPole[0],
            longitude=nPole[1],
            z=refZ,
            degrees=True,
        )

        p_AB_N = pointA.delta_to(pointPole)
        azimuth_offset = p_AB_N.azimuth_deg[0]
        geoAzimuths[ind] = mAzm + azimuth_offset

    geoAzimuths[geoAzimuths > 180] -= 360.
    geoAzimuths[geoAzimuths < -180] += 360.

    return geoAzimuths
 def test_convert_latlon_location_failure(self):
     """Test single value latlon conversion with a bad location"""
     (self.lat_out, self.lon_out,
      self.r_out) = aacgmv2.convert_latlon(0, 0, 0, self.dtime)
     if not (np.isnan(self.lat_out) & np.isnan(self.lon_out) &
             np.isnan(self.r_out)):
         raise AssertionError()
 def test_convert_latlon(self):
     """Test single value latlon conversion"""
     (self.lat_out, self.lon_out,
      self.r_out) = aacgmv2.convert_latlon(60, 0, 300, self.dtime)
     np.testing.assert_almost_equal(self.lat_out, 58.2258, decimal=4)
     np.testing.assert_almost_equal(self.lon_out, 81.1685, decimal=4)
     np.testing.assert_almost_equal(self.r_out, 1.0457, decimal=4)
 def test_convert_latlon_maxalt_failure(self):
     """For a single value, test failure for an altitude too high for
     coefficients"""
     (self.lat_out, self.lon_out,
      self.r_out) = aacgmv2.convert_latlon(60, 0, 2001, self.dtime)
     if not (np.isnan(self.lat_out) & np.isnan(self.lon_out) &
             np.isnan(self.r_out)):
         raise AssertionError()
    def test_convert_latlon_badidea(self):
        """Test single value latlon conversion with a bad flag"""
        code = "G2A | BADIDEA"
        (self.lat_out, self.lon_out,
         self.r_out) = aacgmv2.convert_latlon(60, 0, 3000, self.dtime, code)
        np.testing.assert_almost_equal(self.lat_out, 64.3568, decimal=4)
        np.testing.assert_almost_equal(self.lon_out, 83.3027, decimal=4)
        np.testing.assert_almost_equal(self.r_out, 1.4694, decimal=4)

        del code
    def test_warning_below_ground_convert_latlon(self):
        """ Test that a warning is issued if altitude is below zero"""
        import logbook
        lwarn = u"conversion not intended for altitudes < 0 km"

        with logbook.TestHandler() as handler:
            (self.lat_out, self.lon_out,
             self.r_out) = aacgmv2.convert_latlon(60, 0, -1, self.dtime)
            if not handler.has_warning(lwarn):
                raise AssertionError()

        handler.close()
def GetStationInfo(Station=None, Date=None):

    if Station is None:
        out = Globals.Stations
    else:
        use = np.array(
            [np.where(Globals.Stations.Code == Station.upper())[0][0]])
        out = Globals.Stations[use]

    if not Date is None:
        yr, mn, dy = TT.DateSplit(Date)
        dt = datetime.datetime(year=yr[0], month=mn[0], day=dy[0])
        for i in range(out.size):
            out.mlat[i], out.mlon[i], _ = aacgmv2.convert_latlon(
                out.glat[i], out.glon[i], 0.0, dt, method_code='G2A')

    return out
Beispiel #10
0
def loc_mag_to_geo(loc, dtime):
    """
    Convert a single location in geomagnetic coords into geodetic coords
    :param loc:
        location.Location object with longitude and latitude in geomagnetic coords
    :param dtime:
        either datetime object or parse-able string
    :return:
        location.Location object with longitude and latitude in geodetic coords
    """
    dtime = _check_time(dtime)

    converted = aacgmv2.convert_latlon(loc.lat,
                                       loc.lon,
                                       100,
                                       dtime,
                                       method_code='A2G')
    newloc = Location(converted[0], converted[1])
    return newloc
Beispiel #11
0
 def test_convert_latlon_location_failure(self):
     """Test single value latlon conversion with a bad location"""
     self.out = aacgmv2.convert_latlon(0, 0, 0, self.dtime, self.in_args[-1])
     assert np.all(np.isnan(np.array(self.out)))
Beispiel #12
0
 def test_convert_latlon_high_lat(self, lat, ref):
     """Test single latlon conversion with latitude just out of bounds"""
     self.in_args[0] = lat
     self.in_args.extend([300, self.dtime, 'G2A'])
     self.out = aacgmv2.convert_latlon(*self.in_args)
     np.testing.assert_allclose(self.out, ref, rtol=self.rtol)
for lat in lats:
    in_lat = np.asarray([lat] * len(in_lon))
    out_lats, out_lons, out_rs = convert_latlon_arr(in_lat,
                                                    in_lon,
                                                    heights,
                                                    date,
                                                    method_code="A2G")
    plt.plot(out_lons,
             out_lats,
             'k',
             markersize=3,
             transform=ccrs.Geodetic(),
             label=str(lat) + " deg")

# Find the geodetic coordinates for the geomagnetic pole, and plot it as a black dot
pole_geodetic_lat_N, pole_geodetic_lon_E, _ = aacgmv2.convert_latlon(
    hemisphere.value * 90, -90, 0, date, method_code="A2G")
plt.plot([pole_geodetic_lon_E, pole_geodetic_lon_E],
         [pole_geodetic_lat_N, pole_geodetic_lat_N],
         'ko',
         markersize=3,
         transform=ccrs.Geodetic(),
         label="Geomagnetic North Pole")

ax.add_feature(cfeature.OCEAN)
ax.add_feature(cfeature.LAND)

# Plot a blue dot at the north pole
plt.plot([-90, -90], [90, 90],
         'bo',
         markersize=3,
         transform=ccrs.Geodetic(),
Beispiel #14
0
    def print_fit_record(self):
        """
        Print fit level records
        """
        fname = None
        if self.beams is not None and len(self.beams) > 0:
            fname = self.out_file_dir + "{rad}.{dn}.{start}.{end}.txt".format(
                rad=self.rad,
                dn=self.start_date.strftime("%Y%m%d"),
                start=self.start_date.strftime("%H%M"),
                end=self.end_date.strftime("%H%M"))
            f = open(fname, "w")
            print("\n Working through: ", self.rad)
            hdw = pydarn.read_hdw_file(self.rad)
            fov_obj = rad_fov.CalcFov(hdw=hdw, rsep=self.beams[0].rsep,\
                                      ngates=self.beams[0].nrang, altitude=300.)
            for b in self.beams:
                f.write(b.time.strftime("%Y-%m-%d  "))
                f.write(b.time.strftime("%H:%M:%S  "))
                f.write(self.rad + " ")
                f.write(self.file_type + "\n")
                f.write("bmnum = " + str(b.bmnum))
                f.write("  tfreq = " + str(b.tfreq))
                f.write("  sky_noise_lev = " +
                        str(round(getattr(b, "noise.sky"))))
                f.write("  search_noise_lev = " +
                        str(round(getattr(b, "noise.search"))))
                f.write("  xcf = " + str(getattr(b, "xcf")))
                f.write("  scan = " + str(getattr(b, "scan")) + "\n")
                f.write("npnts = " + str(len(getattr(b, "slist"))))
                f.write("  nrang = " + str(getattr(b, "nrang")))
                f.write("  channel = " + str(getattr(b, "channel")))
                f.write("  cpid = " + str(getattr(b, "cp")) + "\n")

                # Write the table column header
                f.write("{0:>4s} {13:>5s} {1:>5s} / {2:<5s} {3:>8s} {4:>3s} "
                        "{5:>8s} {6:>8s} {7:>8s} {8:>8s} {9:>8s} {10:>8s} "
                        "{11:>8s} {12:>8s}\n".format("gate", "pwr_0", "pwr_l",
                                                     "vel", "gsf", "vel_err",
                                                     "width_l", "geo_lat",
                                                     "geo_lon", "geo_azm",
                                                     "mag_lat", "mag_lon",
                                                     "mag_azm", "range"))

                # Cycle through each range gate identified as having scatter in
                # the slist
                for i, s in enumerate(b.slist):
                    lat_full = fov_obj.latFull[b.bmnum]
                    lon_full = fov_obj.lonFull[b.bmnum]

                    d = geoPack.calcDistPnt(lat_full[s],
                                            lon_full[s],
                                            300,
                                            distLat=lat_full[s + 1],
                                            distLon=lon_full[s + 1],
                                            distAlt=300)
                    gazm = d["az"]
                    # get aacgm_coords
                    mlat, mlon, alt = aacgmv2.convert_latlon(lat_full[s],
                                                             lon_full[s],
                                                             300.,
                                                             b.time,
                                                             method_code="G2A")
                    mlat2, mlon2, alt2 = aacgmv2.convert_latlon(
                        lat_full[s + 1],
                        lon_full[s + 1],
                        300.,
                        b.time,
                        method_code="G2A")
                    d = geoPack.calcDistPnt(mlat,
                                            mlon,
                                            300,
                                            distLat=mlat2,
                                            distLon=mlon2,
                                            distAlt=300)
                    mazm = d["az"]

                    f.write(
                        "{0:4d} {13:5d} {1:>5.1f} / {2:<5.1f} {3:>8.1f} "
                        "{4:>3d} {5:>8.1f} {6:>8.1f} {7:>8.2f} {8:>8.2f} "
                        "{9:>8.2f} {10:>8.2f} {11:>8.2f} {12:>8.2f}\n".format(
                            s,
                            getattr(b, "pwr0")[i],
                            getattr(b, "p_l")[i],
                            getattr(b, "v")[i],
                            getattr(b, "gflg")[i],
                            getattr(b, "v_e")[i],
                            getattr(b, "w_l")[i], lat_full[s], lon_full[s],
                            gazm, mlat, mlon, mazm,
                            getattr(b, "frang") + s * getattr(b, "rsep")))
                f.write("\n")
        f.close()
        return {"fname": fname}
Beispiel #15
0
 def test_convert_latlon_failure(self, in_rep, in_irep, msg):
     self.in_args.extend([300, self.dtime, "G2A"])
     self.in_args[in_irep] = in_rep
     with pytest.raises(ValueError, match=msg):
         aacgmv2.convert_latlon(*self.in_args)
Beispiel #16
0
 def test_convert_latlon(self, alt, method_code, ref):
     """Test single value latlon conversion"""
     self.in_args.extend([alt, self.dtime, method_code])
     self.out = aacgmv2.convert_latlon(*self.in_args)
     np.testing.assert_allclose(self.out, ref, rtol=self.rtol)
Beispiel #17
0
 def test_convert_latlon_datetime_date(self):
     """Test single latlon conversion with date and datetime input"""
     self.in_args.extend([300, self.ddate, 'TRACE'])
     self.out = aacgmv2.convert_latlon(*self.in_args)
     np.testing.assert_allclose(self.out, [58.2268,81.1613,1.0457],
                                rtol=self.rtol)
Beispiel #18
0
 def test_convert_latlon_time_failure(self):
     """Test single value latlon conversion with a bad datetime"""
     self.in_args.extend([300, None, 'TRACE'])
     with pytest.raises(ValueError):
         self.out = aacgmv2.convert_latlon(*self.in_args)
Beispiel #19
0
 def test_convert_latlon_maxalt_failure(self):
     """test convert_latlon failure for an altitude too high for coeffs"""
     self.in_args.extend([2001, self.dtime, ""])
     self.out = aacgmv2.convert_latlon(*self.in_args)
     assert np.all(np.isnan(np.array(self.out)))
 def test_convert_latlon_time_failure(self):
     """Test single value latlon conversion with a bad datetime"""
     with pytest.raises(AssertionError):
         (self.lat_out, self.lon_out,
          self.r_out) = aacgmv2.convert_latlon(60, 0, 300, None)
Beispiel #21
0
 def test_convert_latlon_lat_low_failure(self):
     """Test error return for co-latitudes below -90 for a single value"""
     with pytest.raises(ValueError):
         aacgmv2.convert_latlon(-91, 0, 300, self.dtime)
Beispiel #22
0
def data_grid_at(in_time, lookback_time, gld=None):
    # P_A = 5e3
    # P_B = 1e5
    # tpeak  = np.log(P_A/P_B)/(P_A - P_B)
    # Ipeak = np.exp(-P_A*tpeak) - np.exp(-P_B*tpeak)
    # Ipeak2Io = 1.0/Ipeak
    Ipeak2Io = 1.2324    # Conversion between peak current and Io
                         # (i.e., normalize the exponential terms)
    # Ipeak2Io = 1
#     print np.shape(times_to_do)
    print(f"loading flashes at {in_time}")
    # data_grid = []
    data_grid_cgm = []
    data_grid_mag = []

    # Ktimes, Kp = load_Kp('data/indices/Kp_1999_2018.dat')
    # Ktimes = [k + datetime.timedelta(minutes=90) for k in Ktimes]  # 3-hour bins; the original script labeled them in the middle of the bin
    # Ktimes = np.array(Ktimes)
    # Kp = np.array(Kp)

    # Get Kpmax -- max value of Kp over the last 24 hours (8 bins):
    # Kpmax = np.max([Kp[0:-8],Kp[1:-7],Kp[2:-6], Kp[3:-5], Kp[4:-4],Kp[5:-3],Kp[6:-2], Kp[7:-1], Kp[8:]],axis=0)
    # Kpmtimes = Ktimes[8:]

    itrpl = interp1d([x.timestamp() for x in Kpmtimes], Kpmax, kind='nearest')
    Kpm = itrpl(in_time.timestamp())
    itrpl = interp1d([x.timestamp() for x in Ktimes], Kp, kind='nearest')
    Kp_cur = itrpl(in_time.timestamp())

    # flashes, flash_times = gld.load_flashes(in_time, lookback_time)

    t0 = in_time - lookback_time
    t1 = in_time    


    cur_day = t0.replace(hour=0, minute=0, second=0, microsecond=0)

    if gld.loaded_day != cur_day:
        print(f'loading whole day file for {cur_day}')
        gld.load_day(cur_day)

    if len(gld.times) > 0:
        flashes = gld.flashes[(gld.times >=t0) & (gld.times < t1)]
        flash_times = gld.times[(gld.times >=t0) & (gld.times < t1)]
    else:
        flashes = None
        flash_times = None

    if flashes is not None:
        print(f'Loaded {np.shape(flashes)[0]} flashes')
        # ------------------- day / night calculation --------------------       
        # Threshold day / night via terminator, in geographic coordinates:
        is_day = np.zeros_like(flash_times, dtype='bool')
        t0 = in_time - lookback_time
        t1 = in_time
        dt_daynite = datetime.timedelta(minutes=10) # Timestep to generate day/nite terminator
        tbreaks = [datetime.datetime.fromtimestamp(x) for x in 
                            np.arange(t0.timestamp(), t1.timestamp(), dt_daynite.seconds)]


        for ta in tbreaks:
            tcenter = ta + dt_daynite/2
            tb = ta + dt_daynite
            # print(f'{ta} and {tb}')
            # print(f'flash times contain dates between {min(flash_times)} and {max(flash_times)}')
            # print( np.where((flash_times >=ta) & (flash_times < tb))[0])
            hits = np.where((flash_times >=ta) & (flash_times < tb))[0]
            if len(hits) > 0:
        
                local_times = flash_times[hits]
                # local_lats = flashes[hits,7]
                # local_lons = flashes[hits,8]
                local_lats = flashes[hits,2]
                local_lons = flashes[hits,3]
                

                # Get terminator, in geographic coordinates
                tlons, tlats, tau, dec = daynight_terminator(tcenter, 1, -180, 180)

                # Lon to lat interpolator
                interpy = interp1d(tlons, tlats,'linear', fill_value='extrapolate')

                thresh_lats = interpy(local_lons)
                # fig, ax = plt.subplots(1,1)
                # ax.plot(tlons, tlats)
                # plt.show()

                
                if dec > 0: 
                    is_day[hits] = local_lats > thresh_lats
                else:
                    is_day[hits] = local_lats < thresh_lats


        print(f'{np.sum(is_day)} day bins, {np.sum(~is_day)} night bins')
        # if CGM:
    # ----------------------- CGM coordinates -----------------------
        # pre_cgm_happy_inds = (np.abs(flashes[:,7]) < 90.) & (np.abs(flashes[:,8]) < 360.) 
        # I_pre = np.array(flashes[:,9])
        I_pre = np.array(flashes[:,4])
        ft_pre = flash_times[:]

        # cgmlat, cgmlon = aacgmv2.convert(flashes[pre_cgm_happy_inds,7], flashes[pre_cgm_happy_inds,8], 5.0*np.ones_like(flashes[pre_cgm_happy_inds,7]))
        # geolats = (flashes[:, 7])
        # geolons = (flashes[:, 8])
        geolats = (flashes[:, 2])
        geolons = (flashes[:, 3])
        geoalts = (5.0*np.ones_like(geolats)).tolist()
        
        cgmlat = np.zeros([len(geolats)])
        cgmlon = np.zeros([len(geolats)])
        mlts   = np.zeros([len(geolats)])

        # Do the loop here, since the vectorized version is having trouble
        for x in range(len(geolats)):
            cgmlat[x], cgmlon[x], _ = aacgmv2.convert_latlon(geolats[x], geolons[x], 5.0, ft_pre[x], 'G2A')
            
            # Theirs is probably more correct than mine! But it's slow...
            # mlts[x] = aacgmv2.convert_mlt(cgmlon[x], ft_pre[x], False)
            mlts[x] = xf.lon2MLT(ft_pre[x], cgmlon[x])

        happy_inds = ~np.isnan(cgmlat).flatten()

        cgmlat = cgmlat[happy_inds]
        cgmlon = cgmlon[happy_inds]
        mlts   = mlts[happy_inds]
        is_day_tmp = is_day[happy_inds]
        cgmlon[cgmlon < 0] += 360.

        I = I_pre[happy_inds]*Ipeak2Io
        # print(Kpm)
        # print(np.shape(cgmlat), np.shape(cgmlon), np.shape(mlts), np.shape(I), Kpm, Kp_cur)
        # print(mlts)
        # print(np.shape(cgmlat), np.shape(cgmlon), np.shape(mlts), np.shape(I), np.shape(Kpm*np.ones_like(I)))
        data_grid_cgm = np.vstack([cgmlat, cgmlon, mlts, I, Kpm*np.ones_like(I), Kp_cur*np.ones_like(I), is_day_tmp]).T
        # print(data_grid[:,2])
        # return data_grid

        # else:
    # ----------------------- Magnetic Dipole coordinates -----------------------
        for flash, flashtime, day_flag in zip(flashes, flash_times, is_day):

            # glat = flash[7]
            # glon = flash[8]
            # I    = flash[9]*Ipeak2Io  # Added after stats_v6
            # Indices from gld_whole_file
            glat = flash[2]
            glon = flash[3]
            I    = flash[4]*Ipeak2Io  # Added after stats_v6
            # Get location in geomagnetic coordinates
            mloc = xf.rllgeo2rllmag([1.0, glat, glon], flashtime)

            # Get MLT:
            mlt = xf.lon2MLT(flashtime, mloc[2])

            data_grid_mag.append([mloc[1], mloc[2], mlt, I, Kpm, Kp_cur, day_flag])

        data_grid_mag = np.array(data_grid_mag)
        # print(data_grid[:,2])
        # return data_grid

        return data_grid_cgm, data_grid_mag
    else:
        return None
Beispiel #23
0
def geolocate_radar_fov(rad, time=None):
    """ 
    Geolocate each range cell 
    Input parameters
    ----------------
    rad <str>: Radar code
    time <datetime> (optional): datetime object to calculate magnetic cordinates
    
    Return parameters
    -----------------
    _dict_ {
            beams <list(int)>: Beams
            gates <list(int)>: Gates
            glat [beams, gates] <np.float>: Geogarphic latitude
            glon [beams, gates] <np.float>: Geogarphic longitude
            azm [beams, gates] <np.float>: Geogarphic azimuth of ray-bearing
            mlat [beams, gates] <np.float>: Magnetic latitude
            mlon [beams, gates] <np.float>: Magnetic longitude
            mazm [beams, gates] <np.float>: Magnetic azimuth of ray-bearing
           }
    
    Calling sequence
    ----------------
    from geopos import geolocate_radar_fov
    _dict_ = geolocate_radar_fov("bks")
    """
    logger.info(f"Geolocate radar ({rad}) FoV")
    hdw = pydarn.read_hdw_file(rad)
    fov_obj = rad_fov.CalcFov(hdw=hdw, altitude=300.)
    blen, glen = hdw.beams, hdw.gates
    if glen >= 110: glen = 110
    glat, glon, azm = np.zeros((blen, glen)), np.zeros((blen, glen)), np.zeros(
        (blen, glen))
    mlat, mlon, mazm = np.zeros((blen, glen)) * np.nan, np.zeros(
        (blen, glen)) * np.nan, np.zeros((blen, glen)) * np.nan
    for i, b in enumerate(range(blen)):
        for j, g in enumerate(range(glen)):
            if j < 110:
                glat[i,
                     j], glon[i,
                              j] = fov_obj.latCenter[b,
                                                     g], fov_obj.lonCenter[b,
                                                                           g]
                d = geoPack.calcDistPnt(fov_obj.latFull[b, g],
                                        fov_obj.lonFull[b, g],
                                        300,
                                        distLat=fov_obj.latFull[b, g + 1],
                                        distLon=fov_obj.lonFull[b, g + 1],
                                        distAlt=300)
                azm[i, j] = d["az"]

                if time is not None:
                    mlat[i, j], mlon[i, j], _ = aacgmv2.convert_latlon(
                        fov_obj.latFull[b, g],
                        fov_obj.lonFull[b, g],
                        300.,
                        time,
                        method_code="G2A")
                    mlat2, mlon2, _ = aacgmv2.convert_latlon(
                        fov_obj.latFull[b, g + 1],
                        fov_obj.lonFull[b, g + 1],
                        300.,
                        time,
                        method_code="G2A")
                    d = geoPack.calcDistPnt(mlat[i, j],
                                            mlon[i, j],
                                            300,
                                            distLat=mlat2,
                                            distLon=mlon2,
                                            distAlt=300)
                    mazm[i, j] = d["az"]
    _dict_ = {
        "beams": range(blen),
        "gates": range(glen),
        "glat": glat,
        "glon": glon,
        "azm": azm,
        "mlat": mlat,
        "mlon": mlon,
        "mazm": mazm
    }
    return _dict_