Notebook#

import warnings
warnings.filterwarnings("ignore")
import pandas as pd
import hvplot.pandas
import geopandas as gpd
import geoviews as gv
import numpy as np
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
from IPython.display import display
import urllib.request
from pathlib import Path

file_name = "nearest_nexrad.py"
url = "https://raw.githubusercontent.com/syedhamidali/test_scripts/master/nearest_nexrad.py"

if not Path(file_name).is_file():
    urllib.request.urlretrieve(url, file_name)

import nearest_nexrad as nrnx
print(nrnx.get_nexrad_location("KGWX"))
(33.89667, -88.32889, 476)
sites = nrnx.nearest_sites(33.89667, -88.32889, 5).reset_index(drop=True)
display(sites)
ID lat lon elev distance
0 KGWX 33.89667 -88.32889 476.0 0.000000
1 KBMX 33.17194 -86.76972 645.0 1.719373
2 TMEM 34.88670 -90.00070 483.0 1.942964
3 KNQA 35.34472 -89.87333 282.0 2.117107
4 KDGX 32.28000 -89.98444 -99999.0 2.313972
df = pd.read_excel("Data_availability_PERiLS.xlsx")
df.drop([9, 10, 11], inplace=True)
df.reset_index(drop=True, inplace=True)
df
Instrument Lon Lat Range[m] IOP Start_Time End_Time
0 COW1 -87.946000 32.810980 88443.41 IOP1 2022-03-22 17:04:44 2022-03-22 23:03:40
1 DOW7 -88.171700 32.710800 74960.42 IOP1 2022-03-22 17:59:03 2022-03-22 23:37:13
2 DOW8 -88.436500 33.262500 58545.50 IOP1 2022-03-22 20:02:00 2022-03-22 21:08:50
3 COW1 -88.548200 33.606340 88443.41 IOP2 2022-03-30 15:52:26 2022-03-31 02:18:40
4 DOW7 -88.608500 33.485000 74960.42 IOP2 2022-03-30 18:57:33 2022-03-31 02:19:07
5 DOW8 -88.662700 33.723800 73529.96 IOP2 2022-03-30 21:42:12 2022-03-31 02:20:11
6 COW1 -86.544500 32.269600 88443.41 IOP3 2022-04-05 12:32:48 2022-04-05 17:28:42
7 DOW7 -86.679100 32.428000 74960.42 IOP3 2022-04-05 13:01:09 2022-04-05 16:24:53
8 DOW8 -86.430200 32.197800 58545.50 IOP3 2022-04-05 14:39:27 2022-04-05 17:29:50
9 UAHM -88.495400 33.132500 50000.00 IOP1 2022-03-22 22:34:17 2022-04-13 20:22:14
10 UAHM -88.712067 33.840030 99750.00 IOP2 2022-03-30 15:13:12 2022-03-31 01:42:02
11 NOXP -88.495216 33.132534 74962.00 IOP2 2022-03-30 18:29:28 2022-03-31 01:34:18
12 SMARTR1 -88.345871 32.888432 98975.00 IOP1 2022-03-22 16:05:24 2022-03-22 21:17:49
13 SMARTR2 -88.570110 33.213134 81900.00 IOP1 2022-03-22 15:49:30 2022-03-22 22:48:37
14 SMARTR2 -88.484060 33.346680 82950.00 IOP2 2022-03-30 19:11:36 2022-03-31 02:27:34
import geopandas as gpd
import shapely.geometry as sgeom
import numpy as np
from cartopy.geodesic import Geodesic

def draw_circle_on_map(df):
    gd = Geodesic()
    geoms = []
    for _, row in df.iterrows():
        lon, lat = row['Lon'], row['Lat']
        radius = row['Range[m]']
        cp = gd.circle(lon=lon, lat=lat, radius=radius)
        geoms.append(sgeom.Polygon(cp))
    gdf = gpd.GeoDataFrame(df, geometry=geoms)
    gdf.crs = "EPSG:4326"  # set the CRS
    return gdf
gdf = draw_circle_on_map(df)
gdf
Instrument Lon Lat Range[m] IOP Start_Time End_Time geometry
0 COW1 -87.946000 32.810980 88443.41 IOP1 2022-03-22 17:04:44 2022-03-22 23:03:40 POLYGON ((-87.94600 33.60843, -87.97926 33.607...
1 DOW7 -88.171700 32.710800 74960.42 IOP1 2022-03-22 17:59:03 2022-03-22 23:37:13 POLYGON ((-88.17170 33.38670, -88.19982 33.386...
2 DOW8 -88.436500 33.262500 58545.50 IOP1 2022-03-22 20:02:00 2022-03-22 21:08:50 POLYGON ((-88.43650 33.79035, -88.45856 33.790...
3 COW1 -88.548200 33.606340 88443.41 IOP2 2022-03-30 15:52:26 2022-03-31 02:18:40 POLYGON ((-88.54820 34.40368, -88.58177 34.403...
4 DOW7 -88.608500 33.485000 74960.42 IOP2 2022-03-30 18:57:33 2022-03-31 02:19:07 POLYGON ((-88.60850 34.16081, -88.63687 34.160...
5 DOW8 -88.662700 33.723800 73529.96 IOP2 2022-03-30 21:42:12 2022-03-31 02:20:11 POLYGON ((-88.66270 34.38669, -88.69060 34.386...
6 COW1 -86.544500 32.269600 88443.41 IOP3 2022-04-05 12:32:48 2022-04-05 17:28:42 POLYGON ((-86.54450 33.06712, -86.57755 33.066...
7 DOW7 -86.679100 32.428000 74960.42 IOP3 2022-04-05 13:01:09 2022-04-05 16:24:53 POLYGON ((-86.67910 33.10393, -86.70713 33.103...
8 DOW8 -86.430200 32.197800 58545.50 IOP3 2022-04-05 14:39:27 2022-04-05 17:29:50 POLYGON ((-86.43020 32.72574, -86.45200 32.725...
9 UAHM -88.495400 33.132500 50000.00 IOP1 2022-03-22 22:34:17 2022-04-13 20:22:14 POLYGON ((-88.49540 33.58331, -88.51420 33.583...
10 UAHM -88.712067 33.840030 99750.00 IOP2 2022-03-30 15:13:12 2022-03-31 01:42:02 POLYGON ((-88.71207 34.73926, -88.75008 34.738...
11 NOXP -88.495216 33.132534 74962.00 IOP2 2022-03-30 18:29:28 2022-03-31 01:34:18 POLYGON ((-88.49522 33.80840, -88.52347 33.807...
12 SMARTR1 -88.345871 32.888432 98975.00 IOP1 2022-03-22 16:05:24 2022-03-22 21:17:49 POLYGON ((-88.34587 33.78082, -88.38316 33.780...
13 SMARTR2 -88.570110 33.213134 81900.00 IOP1 2022-03-22 15:49:30 2022-03-22 22:48:37 POLYGON ((-88.57011 33.95154, -88.60103 33.951...
14 SMARTR2 -88.484060 33.346680 82950.00 IOP2 2022-03-30 19:11:36 2022-03-31 02:27:34 POLYGON ((-88.48406 34.09453, -88.51543 34.094...
def draw_circle_on_map_for_nexrad(df):
    gd = Geodesic()
    geoms = []
    for _, row in df.iterrows():
        lon, lat = row['lon'], row['lat']
        radius = 250e3
        cp = gd.circle(lon=lon, lat=lat, radius=radius)
        geoms.append(sgeom.Polygon(cp))
    gdf = gpd.GeoDataFrame(df, geometry=geoms)
    gdf.crs = "EPSG:4326"  # set the CRS
    return gdf
gsites = draw_circle_on_map_for_nexrad(sites)
def create_plot(switch):
    # Define the data based on the switch variable
    if switch == 'IOP1':
        data = gdf[gdf['IOP'] == 'IOP1']
    elif switch == 'IOP2':
        data = gdf[gdf['IOP'] == 'IOP2']
    elif switch == 'IOP3':
        data = gdf[gdf['IOP'] == 'IOP3']
    else:
        data = gdf

    # Define the point plot based on the data
    points = data.hvplot.points(x='Lon', y='Lat', geo=True, color='r',
                                alpha=0.7, coastline=True,
                                frame_height=800, frame_width=650,
                                hover_cols=['Instrument', 'Range[m]', 'IOP', 'Start_Time', 'End_Time'])

    # Define the circle plot based on the data
    circles = gv.Polygons(data=data.geometry).opts(color='gray', fill_alpha=0.2,
                                                   xlabel='Lon˚E', ylabel='Lat˚N',
                                                   frame_height=800, frame_width=650)

    # Define the point plot for the gsites data
    points_nex = gsites.hvplot.points(x='lon', y='lat', geo=True, color='k',
                                      alpha=0.7, hover_cols=['ID'],
                                      coastline=True,
                                      tiles='OpenTopoMap',
                                      frame_height=800, frame_width=650)

    # Define the circle plot for the gsites data
    circles_nex = gv.Polygons(data=gsites.geometry).opts(color='w', fill_alpha=0.2,
                                                          xlabel='Lon˚E', ylabel='Lat˚N',
                                                          frame_height=800, frame_width=650)

    # Overlay the circle plot on top of the point plot
    plot = points_nex * circles_nex * points * circles

    return plot
create_plot('IOP1')
create_plot('IOP2')
create_plot('IOP3')
create_plot(None)
def create_plot(switch):
    # Define the data based on the switch variable
    if switch == 'IOP1':
        data = gdf[gdf['IOP'] == 'IOP1']
    elif switch == 'IOP2':
        data = gdf[gdf['IOP'] == 'IOP2']
    elif switch == 'IOP3':
        data = gdf[gdf['IOP'] == 'IOP3']
    else:
        data = gdf

    # Define the colormap for instrument colors
    instrument_colors = {'COW1': 'red', 'DOW7': 'blue', 'DOW8': 'green',
                         'UAHM': 'orange', 'NOXP': 'purple', 'SMARTR1': 'cyan',
                         'SMARTR2': 'magenta'}

    # Create a color column based on the Instrument column
    data['Color'] = data['Instrument'].map(instrument_colors)

    # Define the point plot based on the data
    points = data.hvplot.points(x='Lon', y='Lat', geo=True, color='Color',
                                alpha=0.7, coastline=True,
                                frame_height=800, frame_width=650,
                                hover_cols=['Instrument', 'Range[m]', 'IOP', 'Start_Time', 'End_Time'])

    # Define the circle plot based on the data
    circles = gv.Polygons(data=data.geometry).opts(fill_alpha=0.2,
                                                   xlabel='Lon˚E', ylabel='Lat˚N',
                                                   frame_height=800, frame_width=650)

    # Define the point plot for the gsites data
    points_nex = gsites.hvplot.points(x='lon', y='lat', geo=True, color='k',
                                      alpha=0.7, hover_cols=['ID'],
                                      coastline=True,
                                      tiles='OpenTopoMap',
                                      frame_height=800, frame_width=650)

    # Define the circle plot for the gsites data
    circles_nex = gv.Polygons(data=gsites.geometry).opts(color='w', fill_alpha=0.2,
                                                          xlabel='Lon˚E', ylabel='Lat˚N',
                                                          frame_height=800, frame_width=650)

    # Overlay the circle plot on top of the point plot
    plot = points_nex * circles_nex * points * circles

    return plot
create_plot('IOP2')