---
arrival_airport: GVAC
categories: [ec_under, ec_track, c_north, c_mid, c_south, c_atr]
crew:
- job: PI
  name: "Silke Gro\xDF"
- job: WALES
  name: Julia Windmiller
- job: HAMP
  name: Lutz Hirsch
- job: Dropsondes
  name: Theresa Mieslinger
- job: Smart/VELOX
  name: Sophie Rosenburg
- job: SpecMACS
  name: Lea Volkmer
- job: Flight Documentation
  name: Elina Plesca
- job: Ground contact
  name: Romain Fiévet
departure_airport: GVAC
flight_id: HALO-20240831a
jupytext:
  text_representation:
    extension: .md
    format_name: myst
kernelspec:
  display_name: Python 3 (ipykernel)
  language: python
  name: python3
landing: '2024-08-31 17:30:00Z'
orphan: true
platform: HALO
takeoff: '2024-08-31 08:45:00Z'
---

{logo}`PERCUSION`

# Flight plan - {front}`flight_id`

```{badges}
```

## Crew

The flight is planned to take off at {front}`takeoff`.

```{crew}
```

## Flight plan

```{code-cell} ipython3
:tags: [hide-input]

from dataclasses import asdict
from datetime import datetime
import cartopy.crs as ccrs
import easygems.healpix as egh
import intake
import matplotlib.pyplot as plt
import numpy as np
import orcestra
import orcestra.flightplan as fp
import orcestra.sat
from orcestra.flightplan import LatLon, IntoCircle, bco, sal, mindelo, find_ec_lon, vertical_preview, to_kml\

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)

# Global coordinates and definitions that should not change from flight to flight

lon_min, lon_max, lat_min, lat_max = -65, -5, -5, 25

radius = 130e3
atr_radius = 72e3

band = "east"
airport = sal if band == "east" else bco
natal = LatLon(-5 - 47/60. - 42.00/3600.,-35 - 12/60. - 33.98/3600., label = "natal")

# Define dates for forecast initialization and flight

issued_time = datetime(2024, 8, 30, 0, 0, 0)

flight_time = datetime(2024, 8, 31, 12, 0, 0)
flight_index = f"HALO-{flight_time.strftime('%Y%m%d')}a"

# adjust takeoff time to match EC overpass
takeoff_time = np.datetime64("2025-08-31T08:45")

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-30", 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} 14:00", None))
ec_lons, ec_lats = ec_track.lon.values, ec_track.lat.values

# Latitudes where we enter and leave the ec track (visually estimated)
lat_ec_north_in = sal.lat
lat_ec_south = 1.0
lat_ec_shuttle_in = 16.0
lat_ec_shuttle_out = 14.0

# latitude of circle centers
lat_c_north = 11.5
lat_c_north_n = lat_c_north + 1.0

lat_c_south = 4.0
lat_c_south_n = lat_c_south + 1.0
lat_c_south_s = lat_c_south - 1.0

lat_c_mid = lat_c_south + (lat_c_north-lat_c_south)/2.0
lat_c_mid_n = lat_c_mid + 1.0
lat_c_mid_s = lat_c_mid - 1.0

lat_ec_under = 13.0

lat_c_atr = lat_ec_shuttle_out + atr_radius/111e3
#c_atr_nw = LatLon(17.433,-23.500, label = "c_atr")
#c_atr_se = LatLon(16.080,-21.715, label = "c_atr")

c_atr_nw = LatLon(18.58125000,-24.27616667, label = "c_atr")
c_atr_se = LatLon(15.79318333,-24.82891944, label = "c_atr")

# create ec track
ec_north = LatLon(lat_ec_north_in, find_ec_lon(lat_ec_north_in, ec_lons, ec_lats), label = "ec_north")
ec_south = LatLon(lat_ec_south, find_ec_lon(lat_ec_south, ec_lons, ec_lats), label = "ec_south")

# create shuttle track
ec_shuttle_in = LatLon(lat_ec_shuttle_in, find_ec_lon(lat_ec_shuttle_in, ec_lons, ec_lats), label = "ec_shuttle_in")
ec_shuttle_out = LatLon(lat_ec_shuttle_out, find_ec_lon(lat_ec_shuttle_out, ec_lons, ec_lats), label = "ec_shuttle_out")

# create circles
c_north = LatLon(lat_c_north, find_ec_lon(lat_c_north, ec_lons, ec_lats), label = "c_north")
c_north_n = LatLon(lat_c_north_n, find_ec_lon(lat_c_north_n, ec_lons, ec_lats), label = "c_north_n")

c_south = LatLon(lat_c_south, find_ec_lon(lat_c_south, ec_lons, ec_lats), label = "c_south")
c_south_s = LatLon(lat_c_south_s, find_ec_lon(lat_c_south_s, ec_lons, ec_lats), label = "c_south_s")
c_south_n = LatLon(lat_c_south_n, find_ec_lon(lat_c_south_n, ec_lons, ec_lats), label = "c_south_n")

c_mid = LatLon(lat_c_mid, find_ec_lon(lat_c_mid, ec_lons, ec_lats), label = "c_mid")
c_mid_s = LatLon(lat_c_mid_s, find_ec_lon(lat_c_mid_s, ec_lons, ec_lats), label = "c_mid_s")
c_mid_n = LatLon(lat_c_mid_n, find_ec_lon(lat_c_mid_n, ec_lons, ec_lats), label = "c_mid_n")

c_atr = LatLon(lat_c_atr, find_ec_lon(lat_c_atr, ec_lons, ec_lats), label = "c_atr")

# ec underpass
ec_under = LatLon(lat_ec_under, find_ec_lon(lat_ec_under, ec_lons, ec_lats), label = "ec_under")
ec_under = ec_under.assign(time=str(ec_time_at_lat(ec_track, ec_under.lat).values)+"Z")

# Define flight track
outbound_legs = [
     airport.assign(fl=0),
     ec_north.assign(fl=410),
     ec_south.assign(fl=410),
     ]

ec_legs = [
     c_south_s.assign(fl=410),
     IntoCircle(c_south.assign(fl=410), radius, 360), 
     c_south_n.assign(fl=410),
     c_mid_s.assign(fl=430),
     IntoCircle(c_mid.assign(fl=430), radius, 360), 
     c_mid_n.assign(fl=430),
     IntoCircle(c_north.assign(fl=430), radius, 360), 
     c_north_n.assign(fl=430),
     ec_under.assign(fl=430),
     ]
inbound_legs = [
     ec_shuttle_out.assign(fl=450),
     ec_shuttle_in.assign(fl=450),
     ec_shuttle_out.assign(fl=350),
     IntoCircle(c_atr.assign(fl=350), atr_radius, 360), 
#     IntoCircle(c_atr_nw.assign(fl=350), atr_radius, 360),
#     IntoCircle(c_atr_se.assign(fl=350), atr_radius, 360),
     airport.assign(fl=0),
     ]

waypoints = outbound_legs + ec_legs + inbound_legs 

waypoint_centers = []
for point in waypoints:
    if isinstance(point, IntoCircle):
        point = point.center
    waypoint_centers.append(point)

path = fp.expand_path(waypoints, dx=10e3)

# extra way points on track

# extra way points off track

plan = path.isel(distance = path.waypoint_indices).to_dataframe().set_index("waypoint_labels")

extra_waypoints = []

notes = {'c_south_in':f' {radius/1852:2.0f} nm circle centered at {c_south.format_pilot()}',
        'c_mid_in':f' {radius/1852:2.0f} nm circle centered at {c_mid.format_pilot()}',
        'c_north_in':f' {radius/1852:2.0f} nm circle centered at {c_north.format_pilot()}',
        'c_atr_in':f' {atr_radius/1852:2.0f} nm circle centered at {c_atr_se.format_pilot()}',
        'xwp2':'Alternative center for c_south',
        'xwp3':'Alternative center for c_atr',
         }


plt.figure(figsize = (14, 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, ax, levels = [50.0, 52.0, 54.0, 56.0, 58.0, 60.0])
plt.title(f"{flight_time}\n(CWV forecast issued on {issued_time})")

plt.plot(ec_lons, ec_lats, c='k', ls='dotted')

for wp in waypoint_centers:
    plt.scatter(wp.lon,wp.lat,s=10.,color='k')
for wp in extra_waypoints:
    plt.scatter(wp.lon,wp.lat,s=10.,color='r',marker='o')
fp.plot_path(path, ax, color="C1")
```

```{code-cell} ipython3
:tags: [hide-input]

# Detailed overview with notes
for index, row in plan.iterrows():
    if (index[0]+index[-4:]!='c_out'):
        print(f"{index:12s} {LatLon(row['lat'],row['lon']).format_pilot():20s}, FL{int(row['fl']):03d}, {takeoff_time+row['duration']:%H:%M:%S}, {notes.get(index,'')}" )
print ('\n-- circle centers:')
for point in waypoints:
    if isinstance(point, IntoCircle):
        point = point.center
        print (f'{point.label:12s} {point.format_pilot()}')
print ('\n-- extra waypoints:')
for point in extra_waypoints:
    print (f'{point.label:12s} {point.format_pilot()}, {notes.get(point.label,'')}' )
```

```{code-cell} ipython3
:tags: [hide-input]

vertical_preview(waypoints)
plt.title("Profile")
```

```{code-cell} ipython3
import os

localdir = "/Users/juliawindmiller/Downloads/"
if os.path.isdir(localdir):
    print (localdir)
    with open(f"{localdir}{flight_index}.kml", "w") as f:
        f.write(to_kml(path))
        
    with open( f"{localdir}{flight_index}_waypoints.txt", "w") as file:
        file.write(f"Flight {flight_index}\n\n")
        #
        # DM Format
        file.write("------------------------------------------------------------\n")
        file.write("\nDM Format:\n")
        file.write(" ".join(wp.format_1min() for wp in waypoint_centers) + "\n")
        for point in extra_waypoints:
            file.write(f"Extra waypoint: {point.format_1min()}\n")
        #
        # DM.mm format
        file.write("\n------------------------------------------------------------\n")
        file.write("\nDMmm Format:\n")
        for point in waypoint_centers:
            file.write(f"{point.format_pilot()}, {point.label}\n")
        file.write("\n-- extra waypoints:\n")
        for point in extra_waypoints:
            file.write(f"{point.format_pilot()}, {notes.get(point.label,'')}\n")
        #
        # Detailed overview with notes
        file.write("\n------------------------------------------------------------\n")
        file.write(f"\n\nDetailed Overview:\n")
        for index, row in plan.iterrows():
            if (index[0]+index[-4:]!='c_out'):
                file.write(f"{index:12s} {LatLon(row['lat'],row['lon']).format_pilot():20s}, FL{int(row['fl']):03d}, {takeoff_time+row['duration']:%H:%M:%S}, {notes.get(index,'')}\n" )
        file.write ('\n -- circle centers:')
        for point in waypoints:
            if isinstance(point, IntoCircle):
                point = point.center
                file.write (f'\n{point.label:12s} {point.format_pilot()}')
        file.write ('\n\n -- extra waypoints:')
        for point in extra_waypoints:
            file.write (f'\n{point.label:12s} {point.format_pilot()}, {notes.get(point.label,'')}' )
```

```{code-cell} ipython3
:tags: [hide-input]

from orcestra.flightplan import export_flightplan

export_flightplan("HALO-20240831a", path)
```

```{code-cell} ipython3

```
