Flight plan - HALO-20240825a#
ec_under ec_track ec_north c_north c_mid c_south c_atr ocsmCrew#
The flight is planned to take off at 2024-08-25 09:15:00+00:00.
Job |
Name |
---|---|
PI |
Julia Windmiller |
WALES |
Tanja Bodenbach |
HAMP |
Jakob Deutloff |
Dropsondes |
Theresa Mieslinger |
Smart/VELOX |
Kevin Wolf |
SpecMACS |
Lea Volkmer |
Flight Documentation |
Suelly Katiza |
Ground contact |
Nicolas Rochetin |
Flight plan#
Show code cell source
import intake
import easygems.healpix as egh
from datetime import datetime, timedelta
import numpy as np
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import orcestra.sat
import orcestra.flightplan as fp
from orcestra.flightplan import LatLon, IntoCircle, bco, sal, mindelo, find_ec_lon, vertical_preview, to_kml
# Define dates for forecast initialization and flight
issued_time = datetime(2024, 8, 24, 0, 0, 0)
flight_time = datetime(2024, 8, 25, 12, 0, 0)
flight_index = f"HALO-{flight_time.strftime('%Y%m%d')}a"
print(
f"Initalization date of IFS forecast: {issued_time}\n"
f"Flight date: {flight_time:%Y-%m-%d}\n"
f"Flight index: {flight_index}"
)
# Load forecast data
cat = intake.open_catalog("https://tcodata.mpimet.mpg.de/internal.yaml")
ds = cat.HIFS(datetime = issued_time).to_dask().pipe(egh.attach_coords)
# Load ec satellite track for
ec_track = orcestra.sat.SattrackLoader("EARTHCARE", "2024-08-24", kind="PRE").get_track_for_day(f"{flight_time:%Y-%m-%d}")
ec_track = ec_track.sel(time=slice(f"{flight_time:%Y-%m-%d} 06:00", None))
ec_lons, ec_lats = ec_track.lon.values, ec_track.lat.values
# Domain definition
lon_min, lon_max, lat_min, lat_max = -65, -5, -10, 25
## Setting lat/lon coordinates
# Mass flux circle radius (m)
radius = 130e3
atr_radius = 70e3
# Setting region (Cabo Verde vs. Barbados)
airport = sal #bco
# Latitudes where we enter and leave the ec track (visually estimated)
lat_ec_north_out = 16.0
lat_ec_north_in = 12.0
lat_ec_south = 2.5
# ITCZ edges visually estimated from iwv contours
lat_c_south = 4.0
lat_c_north = 10.0
# Extra Points along the flight track
lat_c_south_alt_s = 3.25
lat_c_south_alt_n = 4.75
lat_c_north_alt_s = 9.25
lat_c_north_alt_n = 10.75
# Extra Points off the flight track
lat_ec_south_alt = 2.0
# Setting lat/lon coordinates
# Points where we get on ec track
north_ec_in = LatLon(lat_ec_north_in, find_ec_lon(lat_ec_north_in, ec_lons, ec_lats), label = "north_ec_in")
north_ec_out = LatLon(lat_ec_north_out, find_ec_lon(lat_ec_north_out, ec_lons, ec_lats), label = "north_ec_out")
south_ec = LatLon(lat_ec_south, find_ec_lon(lat_ec_south, ec_lons, ec_lats), label = "south_ec")
# Intersection of ITCZ edges with ec track
c_north = LatLon(lat_c_north, find_ec_lon(lat_c_north, ec_lons, ec_lats), label = "c_north")
c_south = LatLon(lat_c_south, find_ec_lon(lat_c_south, ec_lons, ec_lats), label = "c_south")
# Center of middle circle
c_mid = c_south.towards(c_north).assign(label = "c_mid")
# EarthCARE underpass
ec_under = c_north.towards(north_ec_out)
ec_under = LatLon(ec_under.lat, find_ec_lon(ec_under.lat, ec_lons, ec_lats), label = "ec_under")
# ATR circle
atr_circ_sar = LatLon(lat=15.5, lon=-22.1, label="atr_sar")
# Extra Points along the way
c_south_alt_s = LatLon(lat_c_south_alt_s, find_ec_lon(lat_c_south_alt_s, ec_lons, ec_lats), label = "c_south_alt_s")
c_south_alt_n = LatLon(lat_c_south_alt_n, find_ec_lon(lat_c_south_alt_n, ec_lons, ec_lats), label = "c_south_alt_n")
c_north_alt_s = LatLon(lat_c_north_alt_s, find_ec_lon(lat_c_north_alt_s, ec_lons, ec_lats), label = "c_north_alt_s")
c_north_alt_n = LatLon(lat_c_north_alt_n, find_ec_lon(lat_c_north_alt_n, ec_lons, ec_lats), label = "c_north_alt_n")
# Extra Points
ec_south_alt = LatLon(lat_ec_south_alt, find_ec_lon(lat_ec_south_alt, ec_lons, ec_lats), label = "south_ec_alt")
# Define flight track, can be split into different legs
take_off_time = '2024-08-25T09:15:00Z'
waypoints = [
airport.assign(time=take_off_time),
north_ec_in.assign(fl=400),
c_north.assign(fl=400),
c_mid.assign(fl=400),
c_south.assign(fl=400),
south_ec.assign(fl=430),
c_south_alt_s.assign(fl=430),
IntoCircle(c_south.assign(fl=430), radius, 360),
c_south_alt_n.assign(fl=430),
IntoCircle(c_mid.assign(fl=430), radius, 360),
c_north_alt_s.assign(fl=430),
IntoCircle(c_north.assign(fl=450), radius, 360),
c_north_alt_n.assign(fl=450),
ec_under.assign(fl=450),
north_ec_out.assign(fl=450),
mindelo.assign(fl=450),
IntoCircle(atr_circ_sar.assign(fl=350), atr_radius, 360),
airport
]
path = fp.expand_path(waypoints, dx=10e3)
# Plot flight path
plt.figure(figsize = (12, 8))
ax = plt.axes(projection=ccrs.PlateCarree())
ax.set_extent([lon_min, lon_max, lat_min, lat_max], crs=ccrs.PlateCarree())
ax.coastlines(alpha=1.0)
ax.gridlines(draw_labels=True, dms=True, x_inline=False, y_inline=False, alpha = 0.25)
cwv_flight_time = ds["tcwv"].sel(time=flight_time, method = "nearest")
fp.plot_cwv(cwv_flight_time, levels = [45.0, 48.0, 50.0, 52.0, 54.0])
plt.title(f"{flight_time}\n(CWV forecast issued on {issued_time})")
plt.plot(ec_lons, ec_lats)
fp.plot_path(path, ax, color="C1")
Initalization date of IFS forecast: 2024-08-24 00:00:00
Flight date: 2024-08-25
Flight index: HALO-20240825a
/home/runner/miniconda3/envs/orcestra_book/lib/python3.12/site-packages/orcestra/sat.py:183: UserWarning: You are using an old forecast (issued on 2024-08-24) for EARTHCARE on 2024-08-25! The newest forecast issued so far was issued on 2024-08-25. It's a RES forecast.
warnings.warn(
Show code cell source
vertical_preview(waypoints)
plt.xlim(xmin = 0)
plt.ylim(ymin = 0)
plt.ylabel("flight level")
plt.xlabel("distance / m");
Show code cell source
def ec_time_at_lat(ec_track, lat):
e = np.datetime64("2024-08-01")
s = np.timedelta64(1, "ns")
return (((ec_track.swap_dims({"time":"lat"}).time - e) / s).interp(lat=lat) * s + e)
plan = path.isel(distance = path.waypoint_indices).to_dataframe().set_index("waypoint_labels")
notes = {'c_south_in':'enter from south, CCW',
'c_mid_in':'enter from south, CCW',
'c_north_in':'enter from south, CCW',
'c_atr_in':'enter from west, CCW',
'ec_under':f'overpass at {str(ec_time_at_lat(ec_track, ec_under.lat).values)[:-10]}Z',
}
print (f"Flight: {flight_index}\n")
for index, row in plan.iterrows():
print(f"{index:15s} {LatLon(row['lat'],row['lon']).format_pilot():20s}, FL{int(row['fl']):03d}, {row['time']:%H:%M:%S}, {notes.get(index,'')}" )
extra_waypoints = [ec_south_alt]
print ('\nextra waypoints:')
for wp in extra_waypoints:
print (f'{wp.label:15s} {wp.format_pilot()}')
Flight: HALO-20240825a
SAL N16 44.07, W022 56.64, FL000, 09:15:00,
north_ec_in N12 00.00, W031 04.72, FL400, 10:42:09,
c_north N10 00.00, W031 27.63, FL400, 10:58:14,
c_mid N07 00.03, W032 01.71, FL400, 11:22:22,
c_south N04 00.00, W032 35.37, FL400, 11:46:30,
south_ec N02 30.00, W032 52.16, FL430, 11:58:28,
c_south_alt_s N03 15.00, W032 43.77, FL430, 12:04:25,
c_south_in N02 50.67, W032 48.31, FL430, 12:07:38, enter from south, CCW
c_south_out N02 50.67, W032 48.31, FL430, 13:05:10,
c_south_alt_n N04 45.00, W032 26.96, FL430, 13:20:17,
c_mid_in N05 50.71, W032 14.70, FL430, 13:28:57, enter from south, CCW
c_mid_out N05 50.71, W032 14.70, FL430, 14:26:30,
c_north_alt_s N09 15.00, W031 36.17, FL430, 14:53:29,
c_north_in N08 50.70, W031 40.76, FL450, 14:56:41, enter from south, CCW
c_north_out N08 50.70, W031 40.76, FL450, 15:53:46,
c_north_alt_n N10 45.00, W031 19.06, FL450, 16:08:45,
ec_under N13 00.06, W030 53.17, FL450, 16:26:28, overpass at 2024-08-25T16:11:39Z
north_ec_out N16 00.00, W030 18.17, FL450, 16:50:04,
MINDELO N16 52.67, W024 59.70, FL450, 17:30:16,
atr_sar_in N15 46.96, W022 41.04, FL350, 17:49:58,
atr_sar_out N15 46.96, W022 41.04, FL350, 18:22:26,
SAL N16 44.07, W022 56.64, FL000, 18:31:55,
extra waypoints:
south_ec_alt N02 00.00, W032 57.76
Show code cell source
from orcestra.flightplan import export_flightplan
export_flightplan("HALO-20240825a", path)