<jupyter_start><jupyter_text>Balloon Flight Prediction ToolThis application predicts balloon flight trajectories via the ASTRA High Altitude Balloon Flight Planner but is capable of automating mission planning proceedures and provides data analytics.<jupyter_code>import sys
import os
import pathlib
import xml.dom.minidom as md
from pathlib import Path
import kml2geojson as kg
import folium
import json
import geojson
from folium import plugins
from folium.plugins import HeatMap
import numpy as np
from datetime import datetime, timedelta, time
from astra.simulator import *
import statistics
from math import sin, cos, sqrt, atan2, radians
import matplotlib.pyplot as plt
import pandas as pd
import datetime<jupyter_output><empty_output><jupyter_text>Launch time is calculated as 8:00 AM local time on the upcoming Saturday.  If today is Saturday, launch time is current time.<jupyter_code>def next_weekday(d, weekday):
    days_ahead = weekday - d.weekday()
    if days_ahead <= 0: # Target day already happened this week
        days_ahead += 7
    return d + datetime.timedelta(days_ahead)

if datetime.datetime.now().weekday() == 5: # check if today is Saturday
    launch_time = datetime.datetime.now()
    
else:
    d = datetime.datetime.now()
    launch_day = next_weekday(d, 5) # 0 = Monday, 1=Tuesday, 2=Wednesday...
    t = datetime.time(hour=8, minute=0)
    launch_time = datetime.datetime.combine(launch_day, t)

print(launch_time)<jupyter_output><empty_output><jupyter_text>Define assorted constants and flight parameters<jupyter_code>np.random.seed(62)

R = 6373.0

loops = 8<jupyter_output><empty_output><jupyter_text>Setup flight parameters.  Adjust accordingly<jupyter_code>for x in range(loops):
    launch_datetime = launch_time + datetime.timedelta(hours=1*x)
    simEnvironment = forecastEnvironment(launchSiteLat=35.39730,      # deg
                                         launchSiteLon=-90.9965,     # deg
                                         launchSiteElev=100,           # m
                                         dateAndTime=launch_datetime,
                                         forceNonHD=True,
                                         debugging=True)


    simFlight = flight(environment=simEnvironment,
                       balloonGasType='Helium',
                       balloonModel='HW1600',
                       nozzleLift=7.5,                                # kg
                       payloadTrainWeight=5.4,                    # kg
                       parachuteModel='SPH54',
                       numberOfSimRuns=25,
                       trainEquivSphereDiam=0.3,                    # m
                       floatingFlight=False,
                       excessPressureCoeff=1,
                       #outputFile=os.path.join('.', 'astra_output'),
                       outputFile= os.path.join('data', 'balloon_track' + str(x) + '.kml'),
                       debugging=False,
                       log_to_file=True)

    simFlight.run()
#simFlight.write_CSV(os.path.join('.', 'testing'))<jupyter_output><empty_output><jupyter_text>Decode the results of each simulation, determine centroid & error, and add to maps<jupyter_code>kw = {'location': [simEnvironment.launchSiteLat, simEnvironment.launchSiteLon], 'zoom_start': 8,}
out_dir = Path('./results')
m = folium.Map(tiles='OpenStreetMap', **kw)
h = folium.Map(tiles='OpenStreetMap', **kw)

disthist = []
for x in range(loops):
    kml_path = Path(os.path.join('data', 'balloon_track%s' % x + '.kml'))
    mark_path = Path(os.path.join('data', 'balloon_track%s' % x + '_markers.kml'))

    
    layers = kg.convert(kml_path, out_dir)
    marklayers = kg.convert(mark_path, out_dir)
for x in range(loops):
    impact = []
    lon = []
    lat = []
    lon_sum = 0
    lat_sum = 0
    track = os.path.join('results', 'balloon_track%s.geojson' % x)
    markers = os.path.join('results', 'balloon_track%s_markers.geojson' % x)


    tracks = folium.GeoJson(track)

    tracks.add_to(m)
    
    with open(markers) as f:
        landings = json.load(f)



    for feature in landings['features']:
        if feature['properties']['name'].find('landing') > 0:
            coords = feature['geometry']['coordinates']
            #print(coords)
            impact.append([coords[1],coords[0]])
            lon.append(coords[1])
            lat.append(coords[0])
            #llon.append(spot[1])
            #print(coords)
            lon_sum += coords[1]
            lat_sum += coords[0]
            
            lat1 = radians(coords[1])
            lon1 = radians(coords[0])
            lon2 = radians(simEnvironment.launchSiteLon)
            lat2 = radians(simEnvironment.launchSiteLat)
            
            dlon = lon2 - lon1
            dlat = lat2 - lat1

            a = sin(dlat / 2)**2 + cos(lat1) * cos(lat2) * sin(dlon / 2)**2
            c = 2 * atan2(sqrt(a), sqrt(1 - a))

            distance = R * c
            disthist.append(distance)
            #print(distance)

    lonerr = statistics.stdev(lon)
    laterr = statistics.stdev(lat)

    #print(laterr, lon)

    loncent = lon_sum / len(impact)
    latcent = lat_sum / len(impact)

    #print(impact)
    #print(loncent, latcent)
    #print(impact)

    folium.CircleMarker([loncent,latcent], radius=10, color='black').add_to(m)
    #marks = folium.GeoJson(markers)

    #marks.add_to(m)
    latp = []
    lonp = []

    latp.append([loncent-lonerr,latcent])
    latp.append([loncent+lonerr,latcent])
    lonp.append([loncent,latcent-laterr])
    lonp.append([loncent,latcent+laterr])

    folium.PolyLine(latp, color="green", weight=2.5, opacity=1).add_to(m)
    folium.PolyLine(lonp, color="green", weight=2.5, opacity=1).add_to(m)
    #print(disthist)
    

    HeatMap(impact).add_to(h)
    folium.Marker([loncent,latcent]).add_to(h)<jupyter_output><empty_output><jupyter_text>Plot balloon tracks with centroid & error overlay<jupyter_code>m
h
n_bins = 20

fig, axs = plt.subplots()

# We can set the number of bins with the `bins` kwarg
axs.hist(disthist, bins=n_bins)

plt.show()

msg = str(statistics.mean(disthist)) + ',' + str(statistics.median(disthist)) + ',' + str(statistics.stdev(disthist))

print(msg)
from noaa_sdk import noaa

n = noaa.NOAA()
n.points_forecast(simEnvironment.launchSiteLat, simEnvironment.launchSiteLon, hourly=False)
h.save(os.path.join('results', 'map.html'))<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11613406079501169, 'fraction_numerical': 0.014653156664068589, 'mean_word_length': 2.6126126126126126, 'pattern_counts': {'":': 0, '<': 26, '<?xml version=': 0, '>': 26, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 1}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '272488', 'license': 'BSD-3-Clause', 'n_tokens_mistral': 2155, 'n_tokens_neox': 2019, 'n_words': 420, 'path': 'saturday planner.ipynb', 'repo_name': 'muonide/hab-planner', 'size': '6415'}