cusfpredict 0.2.1__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cusfpredict-0.3.0/MANIFEST.in +3 -0
- cusfpredict-0.3.0/PKG-INFO +222 -0
- cusfpredict-0.3.0/README.md +197 -0
- {cusfpredict-0.2.1 → cusfpredict-0.3.0}/cusfpredict/__init__.py +1 -1
- {cusfpredict-0.2.1 → cusfpredict-0.3.0}/cusfpredict/utils.py +51 -12
- cusfpredict-0.3.0/cusfpredict.egg-info/PKG-INFO +222 -0
- cusfpredict-0.3.0/cusfpredict.egg-info/SOURCES.txt +20 -0
- cusfpredict-0.3.0/cusfpredict.egg-info/dependency_links.txt +1 -0
- cusfpredict-0.3.0/cusfpredict.egg-info/requires.txt +8 -0
- cusfpredict-0.3.0/cusfpredict.egg-info/top_level.txt +1 -0
- cusfpredict-0.3.0/pyproject.toml +20 -0
- cusfpredict-0.3.0/setup.cfg +4 -0
- cusfpredict-0.3.0/setup.py +44 -0
- cusfpredict-0.2.1/PKG-INFO +0 -18
- cusfpredict-0.2.1/pyproject.toml +0 -22
- cusfpredict-0.2.1/setup.py +0 -37
- {cusfpredict-0.2.1 → cusfpredict-0.3.0}/LICENSE +0 -0
- {cusfpredict-0.2.1 → cusfpredict-0.3.0}/cusfpredict/gfs.py +0 -0
- {cusfpredict-0.2.1 → cusfpredict-0.3.0}/cusfpredict/predict.py +0 -0
- {cusfpredict-0.2.1 → cusfpredict-0.3.0}/cusfpredict/reader.py +0 -0
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cusfpredict
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Python Wrapper for the CUSF High-Altitude Balloon Predictor
|
|
5
|
+
Keywords: horus balloon prediction gfs
|
|
6
|
+
Classifier: Intended Audience :: Developers
|
|
7
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Requires-Dist: fastkml
|
|
11
|
+
Requires-Dist: requests
|
|
12
|
+
Requires-Dist: numpy
|
|
13
|
+
Requires-Dist: pytz
|
|
14
|
+
Requires-Dist: shapely
|
|
15
|
+
Requires-Dist: python-dateutil
|
|
16
|
+
Requires-Dist: xarray
|
|
17
|
+
Requires-Dist: cfgrib>=0.9.8
|
|
18
|
+
Dynamic: classifier
|
|
19
|
+
Dynamic: description
|
|
20
|
+
Dynamic: description-content-type
|
|
21
|
+
Dynamic: keywords
|
|
22
|
+
Dynamic: license-file
|
|
23
|
+
Dynamic: requires-dist
|
|
24
|
+
Dynamic: summary
|
|
25
|
+
|
|
26
|
+
# CUSF Standalone Predictor - Python Wrapper
|
|
27
|
+
This is a semi-fork of the [CUSF Standalone Predictor](https://github.com/jonsowman/cusf-standalone-predictor/), which provides a Python wrapper around the predictor binary, and provides a means of gathering the requisite wind data.
|
|
28
|
+
|
|
29
|
+
2018-02 Update: Wind downloader updated to use the [NOMADS GRIB Filter](http://nomads.ncep.noaa.gov/txt_descriptions/grib_filter_doc.shtml), as the OpenDAP interface stopped working. As such, we no longer require PyDAP, but we do now require GDAL to read in the GRIB2 files.
|
|
30
|
+
|
|
31
|
+
2021-03 Update: We have dropped GDAL in favour of cfgrib.
|
|
32
|
+
|
|
33
|
+
2026-06 Update: A range of updates for support of newer libraries (e.g. numpy, fastkml), and better packaging. The minimum supported Python version is now 3.9.
|
|
34
|
+
|
|
35
|
+
## 1. System Dependencies
|
|
36
|
+
The Python package installs its Python dependencies automatically. You still need the system libraries used by the wind-data reader and the standalone C predictor.
|
|
37
|
+
|
|
38
|
+
On a Raspbian/Ubuntu/Debian system, you can get most of the required dependencies using:
|
|
39
|
+
```
|
|
40
|
+
$ sudo apt-get install git cmake build-essential libglib2.0-dev python3-numpy python3-requests python3-dateutil python3-pip libeccodes-data libeccodes0 libgeos-dev libatlas-base-dev
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
On macOS with Homebrew:
|
|
44
|
+
```
|
|
45
|
+
$ brew install cmake glib eccodes geos
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## 2. Install the Python Wrapper
|
|
49
|
+
|
|
50
|
+
### From PyPI
|
|
51
|
+
Install into a virtual environment:
|
|
52
|
+
```
|
|
53
|
+
$ python3 -m venv venv
|
|
54
|
+
$ source venv/bin/activate
|
|
55
|
+
$ python -m pip install --upgrade pip
|
|
56
|
+
$ python -m pip install cusfpredict
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Python 2 is not supported.
|
|
60
|
+
|
|
61
|
+
### From Source, Editable Mode (Only required if you are experimenting with changes in this library)
|
|
62
|
+
For development, clone this repository and install it in editable mode:
|
|
63
|
+
```
|
|
64
|
+
$ git clone https://github.com/darksidelemm/cusf_predictor_wrapper.git
|
|
65
|
+
$ cd cusf_predictor_wrapper
|
|
66
|
+
$ python3 -m venv venv
|
|
67
|
+
$ source venv/bin/activate
|
|
68
|
+
$ python -m pip install --upgrade pip
|
|
69
|
+
$ python -m pip install -e .
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
If you only want to install the source checkout without editable mode, use:
|
|
73
|
+
```
|
|
74
|
+
$ python -m pip install .
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
If Python dependency installation fails, the same dependencies are listed in `requirements.txt` and can be installed explicitly:
|
|
78
|
+
```
|
|
79
|
+
$ python -m pip install -r requirements.txt
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The package depends on Shapely and ecCodes-backed GRIB readers. If installation fails with missing headers or missing shared libraries, install the system dependencies above and retry.
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
## 3. Building the Predictor Binary
|
|
86
|
+
The predictor itself is a binary (`pred`), which is built separately using CMake. The Python package does not currently build or install this binary for you.
|
|
87
|
+
|
|
88
|
+
From within the cusf_predictor_wrapper directory, run the following to build the predictor binary:
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
$ cmake -S src -B src/build
|
|
92
|
+
$ cmake --build src/build
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The `pred` binary then needs to be copied somewhere useful. For the example scripts in `apps`, copy it into that directory:
|
|
96
|
+
```
|
|
97
|
+
$ cp src/build/pred apps/
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
If you are building this utility for use with chasemapper, then you should copy `pred` into the chasemapper directory:
|
|
101
|
+
```
|
|
102
|
+
$ cp src/build/pred ~/chasemapper/
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
A pre-compiled Windows binary of the predictor is available here: http://rfhead.net/horus/cusf_standalone_predictor.zip
|
|
106
|
+
Use at your own risk!
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
## 4. Getting Wind Data
|
|
110
|
+
The predictor binary uses a custom wind data format, extracted from NOAA's Global Forecast System wind models. The `cusfpredict.gfs` Python module pulls down and formats the relevant data from NOAA's [NOMADS](http://nomads.ncep.noaa.gov) server.
|
|
111
|
+
|
|
112
|
+
If you are using this library with ChaseMapper, you will need to adjust the download command in the [chasemapper configuration file](https://github.com/projecthorus/chasemapper/blob/master/horusmapper.cfg.example#L135).
|
|
113
|
+
|
|
114
|
+
An example of running it is as follows:
|
|
115
|
+
```
|
|
116
|
+
$ python3 -m cusfpredict.gfs --lat=-33 --lon=139 --latdelta=10 --londelta=10 -f 24 -m 0p50 -o gfs
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
The command line arguments are as follows:
|
|
120
|
+
```
|
|
121
|
+
Area of interest:
|
|
122
|
+
--lat Latitude (Decimal Degrees) of the centre of the area to gather.
|
|
123
|
+
--lon Longitude (Decimal Degrees) of the centre of the area to gather.
|
|
124
|
+
--latdelta Gather data from lat+/-latdelta
|
|
125
|
+
--londelta Gather data from lon+/-londelta
|
|
126
|
+
|
|
127
|
+
Time of interest:
|
|
128
|
+
-f X Gather data up to X hours into the future, from the start of the most recent model. (Note that this can be up to 8 hours in the past.) Make sure you get enough for the flight!
|
|
129
|
+
|
|
130
|
+
GFS Model Choice:
|
|
131
|
+
-m <model> Choose between either:
|
|
132
|
+
0p50 - 0.5 Degree Spatial, 3-hour Time Resolution
|
|
133
|
+
0p25_1hr - 0.25 Degree Spatial, 1-hour Time Resolution (default)
|
|
134
|
+
|
|
135
|
+
Other settings:
|
|
136
|
+
-v Verbose output
|
|
137
|
+
-o output_dir (Where to save the gfs data to, defaults to ./gfs/)
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
The higher resolution wind model you choose, the larger the amount of data to download, and the longer it will take. It also increases the prediction calculation time (though not significantly).
|
|
141
|
+
|
|
142
|
+
`wind_grabber.sh` is an example script to automatically grab wind data first to a temporary directory, and then to the final gfs directory. This could be run from a cronjob to keep the wind data up-to-date.
|
|
143
|
+
|
|
144
|
+
New wind models become available approximately every 6 hours, approximately 4 hours after the model's nominal time (i.e. the 00Z model becomes available around 04Z). Information on the status of the GFS model generation is available here: http://www.nco.ncep.noaa.gov/pmb/nwprod/prodstat_new/
|
|
145
|
+
|
|
146
|
+
## 5. Using the Predictor
|
|
147
|
+
(Note: This section is intended for users within to run predictions from within their own software. If you are just installing this library for use with chasemapper, you can skip all of this!)
|
|
148
|
+
|
|
149
|
+
The basic usage of the predictor from within Python is as follows:
|
|
150
|
+
```
|
|
151
|
+
import datetime
|
|
152
|
+
from cusfpredict.predict import Predictor
|
|
153
|
+
|
|
154
|
+
pred = Predictor(bin_path='./pred', gfs_path='./gfs')
|
|
155
|
+
|
|
156
|
+
flight_path = pred.predict(
|
|
157
|
+
launch_lat=-34.9499,
|
|
158
|
+
launch_lon=138.5194,
|
|
159
|
+
launch_alt=0.0,
|
|
160
|
+
ascent_rate=5.0,
|
|
161
|
+
descent_rate=5.0,
|
|
162
|
+
burst_alt=30000,
|
|
163
|
+
launch_time=datetime.datetime.now(datetime.timezone.utc)
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Note that the launch time is a datetime object interpreted as UTC, so make sure you convert your launch time as appropriate.
|
|
169
|
+
|
|
170
|
+
The output is a list-of-lists, containing entries of [utctimestamp, lat, lon, alt], i.e.:
|
|
171
|
+
|
|
172
|
+
```
|
|
173
|
+
>>> flight_path
|
|
174
|
+
[[1516702953, -34.9471, 138.517, 250.0], [1516703003, -34.9436, 138.514, 500.0], <etc>, [1516703053, -34.9415, 138.513, 750.0]]
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
There is also a command-line utility, `predict.py`, which allows performing predictions with launch parameter variations:
|
|
178
|
+
```
|
|
179
|
+
usage: predict.py [-h] [-a ASCENTRATE] [-d DESCENTRATE] [-b BURSTALT]
|
|
180
|
+
[--launchalt LAUNCHALT] [--latitude LATITUDE]
|
|
181
|
+
[--longitude LONGITUDE] [--time TIME] [-o OUTPUT]
|
|
182
|
+
[--altitude_deltas ALTITUDE_DELTAS]
|
|
183
|
+
[--time_deltas TIME_DELTAS] [--absolute]
|
|
184
|
+
|
|
185
|
+
optional arguments:
|
|
186
|
+
-h, --help show this help message and exit
|
|
187
|
+
-a ASCENTRATE, --ascentrate ASCENTRATE
|
|
188
|
+
Ascent Rate (m/s). Default 5m/s
|
|
189
|
+
-d DESCENTRATE, --descentrate DESCENTRATE
|
|
190
|
+
Descent Rate (m/s). Default 5m/s
|
|
191
|
+
-b BURSTALT, --burstalt BURSTALT
|
|
192
|
+
Burst Altitude (m). Default 30000m
|
|
193
|
+
--launchalt LAUNCHALT
|
|
194
|
+
Launch Altitude (m). Default 0m
|
|
195
|
+
--latitude LATITUDE Launch Latitude (dd.dddd)
|
|
196
|
+
--longitude LONGITUDE
|
|
197
|
+
Launch Longitude (dd.dddd)
|
|
198
|
+
--time TIME Launch Time (string, UTC). Default = Now
|
|
199
|
+
-o OUTPUT, --output OUTPUT
|
|
200
|
+
Output KML File. Default = prediction.kml
|
|
201
|
+
--altitude_deltas ALTITUDE_DELTAS
|
|
202
|
+
Comma-delimited list of altitude deltas. (metres).
|
|
203
|
+
--time_deltas TIME_DELTAS
|
|
204
|
+
Comma-delimited list of time deltas. (hours)
|
|
205
|
+
--absolute Show absolute altitudes for tracks and placemarks.
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
For example, to predict a radiosonde launch from Adelaide Airport (5m/s ascent, 26km burst, 7.5m/s descent), but to look at what happens if the burst altitude is higher or lower than usual:
|
|
209
|
+
```
|
|
210
|
+
$ python3 predict.py --latitude=-34.9499 --longitude=138.5194 -a 5 -d 7.5 -b 26000 --time "2018-01-27 11:15Z" --altitude_deltas="-2000,0,2000"
|
|
211
|
+
Running using GFS Model: gfs20180127-00z
|
|
212
|
+
2018-01-27T11:15:00+00:00 5.0/24000.0/7.5 - Landing: -34.8585, 138.9600 at 2018-01-27T13:03:33
|
|
213
|
+
2018-01-27T11:15:00+00:00 5.0/26000.0/7.5 - Landing: -34.8587, 138.8870 at 2018-01-27T13:11:01
|
|
214
|
+
2018-01-27T11:15:00+00:00 5.0/28000.0/7.5 - Landing: -34.8598, 138.7990 at 2018-01-27T13:18:22
|
|
215
|
+
KML written to prediction.kml
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
A few other example scripts are located in the 'apps' directory:
|
|
219
|
+
* basic_usage.py - Example showing how to write a predicted flight path out to a KML file
|
|
220
|
+
* sonde_predict.py - A more complex example, where predictions for the next week's of radiosonde flights are run and written to a KML file.
|
|
221
|
+
|
|
222
|
+
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# CUSF Standalone Predictor - Python Wrapper
|
|
2
|
+
This is a semi-fork of the [CUSF Standalone Predictor](https://github.com/jonsowman/cusf-standalone-predictor/), which provides a Python wrapper around the predictor binary, and provides a means of gathering the requisite wind data.
|
|
3
|
+
|
|
4
|
+
2018-02 Update: Wind downloader updated to use the [NOMADS GRIB Filter](http://nomads.ncep.noaa.gov/txt_descriptions/grib_filter_doc.shtml), as the OpenDAP interface stopped working. As such, we no longer require PyDAP, but we do now require GDAL to read in the GRIB2 files.
|
|
5
|
+
|
|
6
|
+
2021-03 Update: We have dropped GDAL in favour of cfgrib.
|
|
7
|
+
|
|
8
|
+
2026-06 Update: A range of updates for support of newer libraries (e.g. numpy, fastkml), and better packaging. The minimum supported Python version is now 3.9.
|
|
9
|
+
|
|
10
|
+
## 1. System Dependencies
|
|
11
|
+
The Python package installs its Python dependencies automatically. You still need the system libraries used by the wind-data reader and the standalone C predictor.
|
|
12
|
+
|
|
13
|
+
On a Raspbian/Ubuntu/Debian system, you can get most of the required dependencies using:
|
|
14
|
+
```
|
|
15
|
+
$ sudo apt-get install git cmake build-essential libglib2.0-dev python3-numpy python3-requests python3-dateutil python3-pip libeccodes-data libeccodes0 libgeos-dev libatlas-base-dev
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
On macOS with Homebrew:
|
|
19
|
+
```
|
|
20
|
+
$ brew install cmake glib eccodes geos
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## 2. Install the Python Wrapper
|
|
24
|
+
|
|
25
|
+
### From PyPI
|
|
26
|
+
Install into a virtual environment:
|
|
27
|
+
```
|
|
28
|
+
$ python3 -m venv venv
|
|
29
|
+
$ source venv/bin/activate
|
|
30
|
+
$ python -m pip install --upgrade pip
|
|
31
|
+
$ python -m pip install cusfpredict
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Python 2 is not supported.
|
|
35
|
+
|
|
36
|
+
### From Source, Editable Mode (Only required if you are experimenting with changes in this library)
|
|
37
|
+
For development, clone this repository and install it in editable mode:
|
|
38
|
+
```
|
|
39
|
+
$ git clone https://github.com/darksidelemm/cusf_predictor_wrapper.git
|
|
40
|
+
$ cd cusf_predictor_wrapper
|
|
41
|
+
$ python3 -m venv venv
|
|
42
|
+
$ source venv/bin/activate
|
|
43
|
+
$ python -m pip install --upgrade pip
|
|
44
|
+
$ python -m pip install -e .
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
If you only want to install the source checkout without editable mode, use:
|
|
48
|
+
```
|
|
49
|
+
$ python -m pip install .
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
If Python dependency installation fails, the same dependencies are listed in `requirements.txt` and can be installed explicitly:
|
|
53
|
+
```
|
|
54
|
+
$ python -m pip install -r requirements.txt
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
The package depends on Shapely and ecCodes-backed GRIB readers. If installation fails with missing headers or missing shared libraries, install the system dependencies above and retry.
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
## 3. Building the Predictor Binary
|
|
61
|
+
The predictor itself is a binary (`pred`), which is built separately using CMake. The Python package does not currently build or install this binary for you.
|
|
62
|
+
|
|
63
|
+
From within the cusf_predictor_wrapper directory, run the following to build the predictor binary:
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
$ cmake -S src -B src/build
|
|
67
|
+
$ cmake --build src/build
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
The `pred` binary then needs to be copied somewhere useful. For the example scripts in `apps`, copy it into that directory:
|
|
71
|
+
```
|
|
72
|
+
$ cp src/build/pred apps/
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
If you are building this utility for use with chasemapper, then you should copy `pred` into the chasemapper directory:
|
|
76
|
+
```
|
|
77
|
+
$ cp src/build/pred ~/chasemapper/
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
A pre-compiled Windows binary of the predictor is available here: http://rfhead.net/horus/cusf_standalone_predictor.zip
|
|
81
|
+
Use at your own risk!
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
## 4. Getting Wind Data
|
|
85
|
+
The predictor binary uses a custom wind data format, extracted from NOAA's Global Forecast System wind models. The `cusfpredict.gfs` Python module pulls down and formats the relevant data from NOAA's [NOMADS](http://nomads.ncep.noaa.gov) server.
|
|
86
|
+
|
|
87
|
+
If you are using this library with ChaseMapper, you will need to adjust the download command in the [chasemapper configuration file](https://github.com/projecthorus/chasemapper/blob/master/horusmapper.cfg.example#L135).
|
|
88
|
+
|
|
89
|
+
An example of running it is as follows:
|
|
90
|
+
```
|
|
91
|
+
$ python3 -m cusfpredict.gfs --lat=-33 --lon=139 --latdelta=10 --londelta=10 -f 24 -m 0p50 -o gfs
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The command line arguments are as follows:
|
|
95
|
+
```
|
|
96
|
+
Area of interest:
|
|
97
|
+
--lat Latitude (Decimal Degrees) of the centre of the area to gather.
|
|
98
|
+
--lon Longitude (Decimal Degrees) of the centre of the area to gather.
|
|
99
|
+
--latdelta Gather data from lat+/-latdelta
|
|
100
|
+
--londelta Gather data from lon+/-londelta
|
|
101
|
+
|
|
102
|
+
Time of interest:
|
|
103
|
+
-f X Gather data up to X hours into the future, from the start of the most recent model. (Note that this can be up to 8 hours in the past.) Make sure you get enough for the flight!
|
|
104
|
+
|
|
105
|
+
GFS Model Choice:
|
|
106
|
+
-m <model> Choose between either:
|
|
107
|
+
0p50 - 0.5 Degree Spatial, 3-hour Time Resolution
|
|
108
|
+
0p25_1hr - 0.25 Degree Spatial, 1-hour Time Resolution (default)
|
|
109
|
+
|
|
110
|
+
Other settings:
|
|
111
|
+
-v Verbose output
|
|
112
|
+
-o output_dir (Where to save the gfs data to, defaults to ./gfs/)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
The higher resolution wind model you choose, the larger the amount of data to download, and the longer it will take. It also increases the prediction calculation time (though not significantly).
|
|
116
|
+
|
|
117
|
+
`wind_grabber.sh` is an example script to automatically grab wind data first to a temporary directory, and then to the final gfs directory. This could be run from a cronjob to keep the wind data up-to-date.
|
|
118
|
+
|
|
119
|
+
New wind models become available approximately every 6 hours, approximately 4 hours after the model's nominal time (i.e. the 00Z model becomes available around 04Z). Information on the status of the GFS model generation is available here: http://www.nco.ncep.noaa.gov/pmb/nwprod/prodstat_new/
|
|
120
|
+
|
|
121
|
+
## 5. Using the Predictor
|
|
122
|
+
(Note: This section is intended for users within to run predictions from within their own software. If you are just installing this library for use with chasemapper, you can skip all of this!)
|
|
123
|
+
|
|
124
|
+
The basic usage of the predictor from within Python is as follows:
|
|
125
|
+
```
|
|
126
|
+
import datetime
|
|
127
|
+
from cusfpredict.predict import Predictor
|
|
128
|
+
|
|
129
|
+
pred = Predictor(bin_path='./pred', gfs_path='./gfs')
|
|
130
|
+
|
|
131
|
+
flight_path = pred.predict(
|
|
132
|
+
launch_lat=-34.9499,
|
|
133
|
+
launch_lon=138.5194,
|
|
134
|
+
launch_alt=0.0,
|
|
135
|
+
ascent_rate=5.0,
|
|
136
|
+
descent_rate=5.0,
|
|
137
|
+
burst_alt=30000,
|
|
138
|
+
launch_time=datetime.datetime.now(datetime.timezone.utc)
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Note that the launch time is a datetime object interpreted as UTC, so make sure you convert your launch time as appropriate.
|
|
144
|
+
|
|
145
|
+
The output is a list-of-lists, containing entries of [utctimestamp, lat, lon, alt], i.e.:
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
>>> flight_path
|
|
149
|
+
[[1516702953, -34.9471, 138.517, 250.0], [1516703003, -34.9436, 138.514, 500.0], <etc>, [1516703053, -34.9415, 138.513, 750.0]]
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
There is also a command-line utility, `predict.py`, which allows performing predictions with launch parameter variations:
|
|
153
|
+
```
|
|
154
|
+
usage: predict.py [-h] [-a ASCENTRATE] [-d DESCENTRATE] [-b BURSTALT]
|
|
155
|
+
[--launchalt LAUNCHALT] [--latitude LATITUDE]
|
|
156
|
+
[--longitude LONGITUDE] [--time TIME] [-o OUTPUT]
|
|
157
|
+
[--altitude_deltas ALTITUDE_DELTAS]
|
|
158
|
+
[--time_deltas TIME_DELTAS] [--absolute]
|
|
159
|
+
|
|
160
|
+
optional arguments:
|
|
161
|
+
-h, --help show this help message and exit
|
|
162
|
+
-a ASCENTRATE, --ascentrate ASCENTRATE
|
|
163
|
+
Ascent Rate (m/s). Default 5m/s
|
|
164
|
+
-d DESCENTRATE, --descentrate DESCENTRATE
|
|
165
|
+
Descent Rate (m/s). Default 5m/s
|
|
166
|
+
-b BURSTALT, --burstalt BURSTALT
|
|
167
|
+
Burst Altitude (m). Default 30000m
|
|
168
|
+
--launchalt LAUNCHALT
|
|
169
|
+
Launch Altitude (m). Default 0m
|
|
170
|
+
--latitude LATITUDE Launch Latitude (dd.dddd)
|
|
171
|
+
--longitude LONGITUDE
|
|
172
|
+
Launch Longitude (dd.dddd)
|
|
173
|
+
--time TIME Launch Time (string, UTC). Default = Now
|
|
174
|
+
-o OUTPUT, --output OUTPUT
|
|
175
|
+
Output KML File. Default = prediction.kml
|
|
176
|
+
--altitude_deltas ALTITUDE_DELTAS
|
|
177
|
+
Comma-delimited list of altitude deltas. (metres).
|
|
178
|
+
--time_deltas TIME_DELTAS
|
|
179
|
+
Comma-delimited list of time deltas. (hours)
|
|
180
|
+
--absolute Show absolute altitudes for tracks and placemarks.
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
For example, to predict a radiosonde launch from Adelaide Airport (5m/s ascent, 26km burst, 7.5m/s descent), but to look at what happens if the burst altitude is higher or lower than usual:
|
|
184
|
+
```
|
|
185
|
+
$ python3 predict.py --latitude=-34.9499 --longitude=138.5194 -a 5 -d 7.5 -b 26000 --time "2018-01-27 11:15Z" --altitude_deltas="-2000,0,2000"
|
|
186
|
+
Running using GFS Model: gfs20180127-00z
|
|
187
|
+
2018-01-27T11:15:00+00:00 5.0/24000.0/7.5 - Landing: -34.8585, 138.9600 at 2018-01-27T13:03:33
|
|
188
|
+
2018-01-27T11:15:00+00:00 5.0/26000.0/7.5 - Landing: -34.8587, 138.8870 at 2018-01-27T13:11:01
|
|
189
|
+
2018-01-27T11:15:00+00:00 5.0/28000.0/7.5 - Landing: -34.8598, 138.7990 at 2018-01-27T13:18:22
|
|
190
|
+
KML written to prediction.kml
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
A few other example scripts are located in the 'apps' directory:
|
|
194
|
+
* basic_usage.py - Example showing how to write a predicted flight path out to a KML file
|
|
195
|
+
* sonde_predict.py - A more complex example, where predictions for the next week's of radiosonde flights are run and written to a KML file.
|
|
196
|
+
|
|
197
|
+
|
|
@@ -10,6 +10,11 @@ import datetime
|
|
|
10
10
|
import os.path
|
|
11
11
|
from shapely.geometry import Point, LineString
|
|
12
12
|
|
|
13
|
+
try:
|
|
14
|
+
from fastkml.enums import AltitudeMode
|
|
15
|
+
except ImportError:
|
|
16
|
+
AltitudeMode = None
|
|
17
|
+
|
|
13
18
|
def available_gfs(gfs_path='./gfs'):
|
|
14
19
|
""" Determine the time extent of the GFS dataset """
|
|
15
20
|
|
|
@@ -30,8 +35,8 @@ def available_gfs(gfs_path='./gfs'):
|
|
|
30
35
|
|
|
31
36
|
_timestamps.sort()
|
|
32
37
|
|
|
33
|
-
start_time = datetime.datetime.
|
|
34
|
-
end_time = datetime.datetime.
|
|
38
|
+
start_time = datetime.datetime.fromtimestamp(_timestamps[0], datetime.timezone.utc)
|
|
39
|
+
end_time = datetime.datetime.fromtimestamp(_timestamps[-1], datetime.timezone.utc)
|
|
35
40
|
|
|
36
41
|
return (start_time, end_time)
|
|
37
42
|
|
|
@@ -56,6 +61,38 @@ def gfs_model_age(gfs_path="./gfs"):
|
|
|
56
61
|
# Geometry and KML related stuff
|
|
57
62
|
ns = '{http://www.opengis.net/kml/2.2}'
|
|
58
63
|
|
|
64
|
+
def _kml_altitude_mode(altitude_mode):
|
|
65
|
+
"""Return an altitude mode value compatible with the installed fastkml."""
|
|
66
|
+
|
|
67
|
+
if AltitudeMode is None or not isinstance(altitude_mode, str):
|
|
68
|
+
return altitude_mode
|
|
69
|
+
|
|
70
|
+
for mode in AltitudeMode:
|
|
71
|
+
if altitude_mode in (mode.name, mode.value):
|
|
72
|
+
return mode
|
|
73
|
+
|
|
74
|
+
return altitude_mode
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _kml_geometry(geometry, **kwargs):
|
|
78
|
+
"""Create a fastkml geometry across old and new fastkml APIs."""
|
|
79
|
+
|
|
80
|
+
if hasattr(fastkml.geometry, "create_kml_geometry"):
|
|
81
|
+
if "altitude_mode" in kwargs:
|
|
82
|
+
kwargs["altitude_mode"] = _kml_altitude_mode(kwargs["altitude_mode"])
|
|
83
|
+
return fastkml.geometry.create_kml_geometry(geometry, ns=ns, **kwargs)
|
|
84
|
+
|
|
85
|
+
return fastkml.geometry.Geometry(ns=ns, geometry=geometry, **kwargs)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _set_placemark_geometry(placemark, geometry, **kwargs):
|
|
89
|
+
kml_geometry = _kml_geometry(geometry, **kwargs)
|
|
90
|
+
|
|
91
|
+
if hasattr(fastkml.geometry, "create_kml_geometry"):
|
|
92
|
+
placemark.kml_geometry = kml_geometry
|
|
93
|
+
else:
|
|
94
|
+
placemark.geometry = kml_geometry
|
|
95
|
+
|
|
59
96
|
def flight_path_to_linestring(flight_path):
|
|
60
97
|
''' Convert a predicted flight path to a LineString geometry object '''
|
|
61
98
|
|
|
@@ -105,9 +142,9 @@ def flight_path_to_geometry(flight_path,
|
|
|
105
142
|
name=comment,
|
|
106
143
|
styles=[flight_track_style])
|
|
107
144
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
145
|
+
_set_placemark_geometry(
|
|
146
|
+
flight_line,
|
|
147
|
+
flight_path_to_linestring(flight_path),
|
|
111
148
|
altitude_mode=altitude_mode,
|
|
112
149
|
extrude=True,
|
|
113
150
|
tessellate=True)
|
|
@@ -136,9 +173,9 @@ def flight_path_landing_placemark(flight_path,
|
|
|
136
173
|
description="",
|
|
137
174
|
styles=[flight_style])
|
|
138
175
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
176
|
+
_set_placemark_geometry(
|
|
177
|
+
flight_placemark,
|
|
178
|
+
Point(flight_path[-1][2], flight_path[-1][1], flight_path[-1][3]),
|
|
142
179
|
altitude_mode='clampToGround')
|
|
143
180
|
|
|
144
181
|
return flight_placemark
|
|
@@ -175,9 +212,9 @@ def flight_path_burst_placemark(flight_path,
|
|
|
175
212
|
current_index = i
|
|
176
213
|
|
|
177
214
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
215
|
+
_set_placemark_geometry(
|
|
216
|
+
flight_placemark,
|
|
217
|
+
Point(flight_path[current_index][2], flight_path[current_index][1], flight_path[current_index][3]),
|
|
181
218
|
altitude_mode=altitude_mode)
|
|
182
219
|
|
|
183
220
|
return flight_placemark
|
|
@@ -200,8 +237,10 @@ def write_flight_path_kml(flight_data,
|
|
|
200
237
|
for _flight in flight_data:
|
|
201
238
|
kml_doc.append(_flight)
|
|
202
239
|
|
|
240
|
+
kml_root.append(kml_doc)
|
|
241
|
+
|
|
203
242
|
with open(filename,'w') as kml_file:
|
|
204
|
-
kml_str =
|
|
243
|
+
kml_str = kml_root.to_string()
|
|
205
244
|
if kml_hack:
|
|
206
245
|
kml_str = kml_str.replace('kml:','').replace(':kml','')
|
|
207
246
|
kml_file.write(kml_str)
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cusfpredict
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Python Wrapper for the CUSF High-Altitude Balloon Predictor
|
|
5
|
+
Keywords: horus balloon prediction gfs
|
|
6
|
+
Classifier: Intended Audience :: Developers
|
|
7
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Requires-Dist: fastkml
|
|
11
|
+
Requires-Dist: requests
|
|
12
|
+
Requires-Dist: numpy
|
|
13
|
+
Requires-Dist: pytz
|
|
14
|
+
Requires-Dist: shapely
|
|
15
|
+
Requires-Dist: python-dateutil
|
|
16
|
+
Requires-Dist: xarray
|
|
17
|
+
Requires-Dist: cfgrib>=0.9.8
|
|
18
|
+
Dynamic: classifier
|
|
19
|
+
Dynamic: description
|
|
20
|
+
Dynamic: description-content-type
|
|
21
|
+
Dynamic: keywords
|
|
22
|
+
Dynamic: license-file
|
|
23
|
+
Dynamic: requires-dist
|
|
24
|
+
Dynamic: summary
|
|
25
|
+
|
|
26
|
+
# CUSF Standalone Predictor - Python Wrapper
|
|
27
|
+
This is a semi-fork of the [CUSF Standalone Predictor](https://github.com/jonsowman/cusf-standalone-predictor/), which provides a Python wrapper around the predictor binary, and provides a means of gathering the requisite wind data.
|
|
28
|
+
|
|
29
|
+
2018-02 Update: Wind downloader updated to use the [NOMADS GRIB Filter](http://nomads.ncep.noaa.gov/txt_descriptions/grib_filter_doc.shtml), as the OpenDAP interface stopped working. As such, we no longer require PyDAP, but we do now require GDAL to read in the GRIB2 files.
|
|
30
|
+
|
|
31
|
+
2021-03 Update: We have dropped GDAL in favour of cfgrib.
|
|
32
|
+
|
|
33
|
+
2026-06 Update: A range of updates for support of newer libraries (e.g. numpy, fastkml), and better packaging. The minimum supported Python version is now 3.9.
|
|
34
|
+
|
|
35
|
+
## 1. System Dependencies
|
|
36
|
+
The Python package installs its Python dependencies automatically. You still need the system libraries used by the wind-data reader and the standalone C predictor.
|
|
37
|
+
|
|
38
|
+
On a Raspbian/Ubuntu/Debian system, you can get most of the required dependencies using:
|
|
39
|
+
```
|
|
40
|
+
$ sudo apt-get install git cmake build-essential libglib2.0-dev python3-numpy python3-requests python3-dateutil python3-pip libeccodes-data libeccodes0 libgeos-dev libatlas-base-dev
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
On macOS with Homebrew:
|
|
44
|
+
```
|
|
45
|
+
$ brew install cmake glib eccodes geos
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## 2. Install the Python Wrapper
|
|
49
|
+
|
|
50
|
+
### From PyPI
|
|
51
|
+
Install into a virtual environment:
|
|
52
|
+
```
|
|
53
|
+
$ python3 -m venv venv
|
|
54
|
+
$ source venv/bin/activate
|
|
55
|
+
$ python -m pip install --upgrade pip
|
|
56
|
+
$ python -m pip install cusfpredict
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Python 2 is not supported.
|
|
60
|
+
|
|
61
|
+
### From Source, Editable Mode (Only required if you are experimenting with changes in this library)
|
|
62
|
+
For development, clone this repository and install it in editable mode:
|
|
63
|
+
```
|
|
64
|
+
$ git clone https://github.com/darksidelemm/cusf_predictor_wrapper.git
|
|
65
|
+
$ cd cusf_predictor_wrapper
|
|
66
|
+
$ python3 -m venv venv
|
|
67
|
+
$ source venv/bin/activate
|
|
68
|
+
$ python -m pip install --upgrade pip
|
|
69
|
+
$ python -m pip install -e .
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
If you only want to install the source checkout without editable mode, use:
|
|
73
|
+
```
|
|
74
|
+
$ python -m pip install .
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
If Python dependency installation fails, the same dependencies are listed in `requirements.txt` and can be installed explicitly:
|
|
78
|
+
```
|
|
79
|
+
$ python -m pip install -r requirements.txt
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The package depends on Shapely and ecCodes-backed GRIB readers. If installation fails with missing headers or missing shared libraries, install the system dependencies above and retry.
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
## 3. Building the Predictor Binary
|
|
86
|
+
The predictor itself is a binary (`pred`), which is built separately using CMake. The Python package does not currently build or install this binary for you.
|
|
87
|
+
|
|
88
|
+
From within the cusf_predictor_wrapper directory, run the following to build the predictor binary:
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
$ cmake -S src -B src/build
|
|
92
|
+
$ cmake --build src/build
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
The `pred` binary then needs to be copied somewhere useful. For the example scripts in `apps`, copy it into that directory:
|
|
96
|
+
```
|
|
97
|
+
$ cp src/build/pred apps/
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
If you are building this utility for use with chasemapper, then you should copy `pred` into the chasemapper directory:
|
|
101
|
+
```
|
|
102
|
+
$ cp src/build/pred ~/chasemapper/
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
A pre-compiled Windows binary of the predictor is available here: http://rfhead.net/horus/cusf_standalone_predictor.zip
|
|
106
|
+
Use at your own risk!
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
## 4. Getting Wind Data
|
|
110
|
+
The predictor binary uses a custom wind data format, extracted from NOAA's Global Forecast System wind models. The `cusfpredict.gfs` Python module pulls down and formats the relevant data from NOAA's [NOMADS](http://nomads.ncep.noaa.gov) server.
|
|
111
|
+
|
|
112
|
+
If you are using this library with ChaseMapper, you will need to adjust the download command in the [chasemapper configuration file](https://github.com/projecthorus/chasemapper/blob/master/horusmapper.cfg.example#L135).
|
|
113
|
+
|
|
114
|
+
An example of running it is as follows:
|
|
115
|
+
```
|
|
116
|
+
$ python3 -m cusfpredict.gfs --lat=-33 --lon=139 --latdelta=10 --londelta=10 -f 24 -m 0p50 -o gfs
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
The command line arguments are as follows:
|
|
120
|
+
```
|
|
121
|
+
Area of interest:
|
|
122
|
+
--lat Latitude (Decimal Degrees) of the centre of the area to gather.
|
|
123
|
+
--lon Longitude (Decimal Degrees) of the centre of the area to gather.
|
|
124
|
+
--latdelta Gather data from lat+/-latdelta
|
|
125
|
+
--londelta Gather data from lon+/-londelta
|
|
126
|
+
|
|
127
|
+
Time of interest:
|
|
128
|
+
-f X Gather data up to X hours into the future, from the start of the most recent model. (Note that this can be up to 8 hours in the past.) Make sure you get enough for the flight!
|
|
129
|
+
|
|
130
|
+
GFS Model Choice:
|
|
131
|
+
-m <model> Choose between either:
|
|
132
|
+
0p50 - 0.5 Degree Spatial, 3-hour Time Resolution
|
|
133
|
+
0p25_1hr - 0.25 Degree Spatial, 1-hour Time Resolution (default)
|
|
134
|
+
|
|
135
|
+
Other settings:
|
|
136
|
+
-v Verbose output
|
|
137
|
+
-o output_dir (Where to save the gfs data to, defaults to ./gfs/)
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
The higher resolution wind model you choose, the larger the amount of data to download, and the longer it will take. It also increases the prediction calculation time (though not significantly).
|
|
141
|
+
|
|
142
|
+
`wind_grabber.sh` is an example script to automatically grab wind data first to a temporary directory, and then to the final gfs directory. This could be run from a cronjob to keep the wind data up-to-date.
|
|
143
|
+
|
|
144
|
+
New wind models become available approximately every 6 hours, approximately 4 hours after the model's nominal time (i.e. the 00Z model becomes available around 04Z). Information on the status of the GFS model generation is available here: http://www.nco.ncep.noaa.gov/pmb/nwprod/prodstat_new/
|
|
145
|
+
|
|
146
|
+
## 5. Using the Predictor
|
|
147
|
+
(Note: This section is intended for users within to run predictions from within their own software. If you are just installing this library for use with chasemapper, you can skip all of this!)
|
|
148
|
+
|
|
149
|
+
The basic usage of the predictor from within Python is as follows:
|
|
150
|
+
```
|
|
151
|
+
import datetime
|
|
152
|
+
from cusfpredict.predict import Predictor
|
|
153
|
+
|
|
154
|
+
pred = Predictor(bin_path='./pred', gfs_path='./gfs')
|
|
155
|
+
|
|
156
|
+
flight_path = pred.predict(
|
|
157
|
+
launch_lat=-34.9499,
|
|
158
|
+
launch_lon=138.5194,
|
|
159
|
+
launch_alt=0.0,
|
|
160
|
+
ascent_rate=5.0,
|
|
161
|
+
descent_rate=5.0,
|
|
162
|
+
burst_alt=30000,
|
|
163
|
+
launch_time=datetime.datetime.now(datetime.timezone.utc)
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Note that the launch time is a datetime object interpreted as UTC, so make sure you convert your launch time as appropriate.
|
|
169
|
+
|
|
170
|
+
The output is a list-of-lists, containing entries of [utctimestamp, lat, lon, alt], i.e.:
|
|
171
|
+
|
|
172
|
+
```
|
|
173
|
+
>>> flight_path
|
|
174
|
+
[[1516702953, -34.9471, 138.517, 250.0], [1516703003, -34.9436, 138.514, 500.0], <etc>, [1516703053, -34.9415, 138.513, 750.0]]
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
There is also a command-line utility, `predict.py`, which allows performing predictions with launch parameter variations:
|
|
178
|
+
```
|
|
179
|
+
usage: predict.py [-h] [-a ASCENTRATE] [-d DESCENTRATE] [-b BURSTALT]
|
|
180
|
+
[--launchalt LAUNCHALT] [--latitude LATITUDE]
|
|
181
|
+
[--longitude LONGITUDE] [--time TIME] [-o OUTPUT]
|
|
182
|
+
[--altitude_deltas ALTITUDE_DELTAS]
|
|
183
|
+
[--time_deltas TIME_DELTAS] [--absolute]
|
|
184
|
+
|
|
185
|
+
optional arguments:
|
|
186
|
+
-h, --help show this help message and exit
|
|
187
|
+
-a ASCENTRATE, --ascentrate ASCENTRATE
|
|
188
|
+
Ascent Rate (m/s). Default 5m/s
|
|
189
|
+
-d DESCENTRATE, --descentrate DESCENTRATE
|
|
190
|
+
Descent Rate (m/s). Default 5m/s
|
|
191
|
+
-b BURSTALT, --burstalt BURSTALT
|
|
192
|
+
Burst Altitude (m). Default 30000m
|
|
193
|
+
--launchalt LAUNCHALT
|
|
194
|
+
Launch Altitude (m). Default 0m
|
|
195
|
+
--latitude LATITUDE Launch Latitude (dd.dddd)
|
|
196
|
+
--longitude LONGITUDE
|
|
197
|
+
Launch Longitude (dd.dddd)
|
|
198
|
+
--time TIME Launch Time (string, UTC). Default = Now
|
|
199
|
+
-o OUTPUT, --output OUTPUT
|
|
200
|
+
Output KML File. Default = prediction.kml
|
|
201
|
+
--altitude_deltas ALTITUDE_DELTAS
|
|
202
|
+
Comma-delimited list of altitude deltas. (metres).
|
|
203
|
+
--time_deltas TIME_DELTAS
|
|
204
|
+
Comma-delimited list of time deltas. (hours)
|
|
205
|
+
--absolute Show absolute altitudes for tracks and placemarks.
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
For example, to predict a radiosonde launch from Adelaide Airport (5m/s ascent, 26km burst, 7.5m/s descent), but to look at what happens if the burst altitude is higher or lower than usual:
|
|
209
|
+
```
|
|
210
|
+
$ python3 predict.py --latitude=-34.9499 --longitude=138.5194 -a 5 -d 7.5 -b 26000 --time "2018-01-27 11:15Z" --altitude_deltas="-2000,0,2000"
|
|
211
|
+
Running using GFS Model: gfs20180127-00z
|
|
212
|
+
2018-01-27T11:15:00+00:00 5.0/24000.0/7.5 - Landing: -34.8585, 138.9600 at 2018-01-27T13:03:33
|
|
213
|
+
2018-01-27T11:15:00+00:00 5.0/26000.0/7.5 - Landing: -34.8587, 138.8870 at 2018-01-27T13:11:01
|
|
214
|
+
2018-01-27T11:15:00+00:00 5.0/28000.0/7.5 - Landing: -34.8598, 138.7990 at 2018-01-27T13:18:22
|
|
215
|
+
KML written to prediction.kml
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
A few other example scripts are located in the 'apps' directory:
|
|
219
|
+
* basic_usage.py - Example showing how to write a predicted flight path out to a KML file
|
|
220
|
+
* sonde_predict.py - A more complex example, where predictions for the next week's of radiosonde flights are run and written to a KML file.
|
|
221
|
+
|
|
222
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
MANIFEST.in
|
|
3
|
+
README.md
|
|
4
|
+
pyproject.toml
|
|
5
|
+
setup.py
|
|
6
|
+
./cusfpredict/__init__.py
|
|
7
|
+
./cusfpredict/gfs.py
|
|
8
|
+
./cusfpredict/predict.py
|
|
9
|
+
./cusfpredict/reader.py
|
|
10
|
+
./cusfpredict/utils.py
|
|
11
|
+
cusfpredict/__init__.py
|
|
12
|
+
cusfpredict/gfs.py
|
|
13
|
+
cusfpredict/predict.py
|
|
14
|
+
cusfpredict/reader.py
|
|
15
|
+
cusfpredict/utils.py
|
|
16
|
+
cusfpredict.egg-info/PKG-INFO
|
|
17
|
+
cusfpredict.egg-info/SOURCES.txt
|
|
18
|
+
cusfpredict.egg-info/dependency_links.txt
|
|
19
|
+
cusfpredict.egg-info/requires.txt
|
|
20
|
+
cusfpredict.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
cusfpredict
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
[tool.poetry]
|
|
2
|
+
name = "cusfpredict"
|
|
3
|
+
version = "0.3.0"
|
|
4
|
+
description = "CUSF Predictor Wrapper & GFS Downloader"
|
|
5
|
+
authors = ["Mark Jessop"]
|
|
6
|
+
|
|
7
|
+
[tool.poetry.dependencies]
|
|
8
|
+
python = "^3.9" # last actively maintained version of Python
|
|
9
|
+
fastkml = "^1"
|
|
10
|
+
requests = "^2.25.1"
|
|
11
|
+
numpy = "^2.0.0"
|
|
12
|
+
pytz = "^2025.1"
|
|
13
|
+
shapely = "^2.0.0"
|
|
14
|
+
python-dateutil = "^2.8.1"
|
|
15
|
+
xarray = "*"
|
|
16
|
+
cfgrib = "^0.9.8"
|
|
17
|
+
|
|
18
|
+
[build-system]
|
|
19
|
+
requires = ["setuptools>=64", "wheel"]
|
|
20
|
+
build-backend = "setuptools.build_meta"
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import re
|
|
3
|
+
from setuptools import setup, find_packages
|
|
4
|
+
|
|
5
|
+
regexp = re.compile(r".*__version__ = [\'\"](.*?)[\'\"]", re.S)
|
|
6
|
+
|
|
7
|
+
init_file = os.path.join(os.path.dirname(__file__), "cusfpredict", "__init__.py")
|
|
8
|
+
with open(init_file, "r") as f:
|
|
9
|
+
module_content = f.read()
|
|
10
|
+
match = regexp.match(module_content)
|
|
11
|
+
if match:
|
|
12
|
+
version = match.group(1)
|
|
13
|
+
else:
|
|
14
|
+
raise RuntimeError(f"Cannot find __version__ in {init_file}")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
with open("README.md", "r") as f:
|
|
18
|
+
readme = f.read()
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
with open("requirements.txt", "r") as f:
|
|
22
|
+
requirements = []
|
|
23
|
+
for line in f.read().split("\n"):
|
|
24
|
+
line = line.strip()
|
|
25
|
+
if line and not line.startswith("#"):
|
|
26
|
+
requirements.append(line)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
if __name__ == "__main__":
|
|
30
|
+
setup(
|
|
31
|
+
name="cusfpredict",
|
|
32
|
+
description="Python Wrapper for the CUSF High-Altitude Balloon Predictor",
|
|
33
|
+
long_description=readme,
|
|
34
|
+
long_description_content_type="text/markdown",
|
|
35
|
+
version=version,
|
|
36
|
+
install_requires=requirements,
|
|
37
|
+
keywords=["horus balloon prediction gfs"],
|
|
38
|
+
package_dir={"": "."},
|
|
39
|
+
packages=find_packages("."),
|
|
40
|
+
classifiers=[
|
|
41
|
+
"Intended Audience :: Developers",
|
|
42
|
+
"Programming Language :: Python :: 3.9"
|
|
43
|
+
]
|
|
44
|
+
)
|
cusfpredict-0.2.1/PKG-INFO
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: cusfpredict
|
|
3
|
-
Version: 0.2.1
|
|
4
|
-
Summary: CUSF Predictor Wrapper & GFS Downloader
|
|
5
|
-
Author: Mark Jessop
|
|
6
|
-
Requires-Python: >=3.6,<4.0
|
|
7
|
-
Classifier: Programming Language :: Python :: 3
|
|
8
|
-
Classifier: Programming Language :: Python :: 3.6
|
|
9
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
10
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
11
|
-
Requires-Dist: cfgrib (>=0.9.8,<0.10.0)
|
|
12
|
-
Requires-Dist: fastkml (>=0.11,<0.12)
|
|
13
|
-
Requires-Dist: numpy (>=1.17,<2.0)
|
|
14
|
-
Requires-Dist: python-dateutil (>=2.8.1,<3.0.0)
|
|
15
|
-
Requires-Dist: pytz (>=2020.5,<2021.0)
|
|
16
|
-
Requires-Dist: requests (>=2.25.1,<3.0.0)
|
|
17
|
-
Requires-Dist: shapely (>=1.7.1,<2.0.0)
|
|
18
|
-
Requires-Dist: xarray (>=0.16.2,<0.17.0)
|
cusfpredict-0.2.1/pyproject.toml
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
[tool.poetry]
|
|
2
|
-
name = "cusfpredict"
|
|
3
|
-
version = "0.2.1"
|
|
4
|
-
description = "CUSF Predictor Wrapper & GFS Downloader"
|
|
5
|
-
authors = ["Mark Jessop"]
|
|
6
|
-
|
|
7
|
-
[tool.poetry.dependencies]
|
|
8
|
-
python = "^3.6"
|
|
9
|
-
fastkml = "^0.11"
|
|
10
|
-
requests = "^2.25.1"
|
|
11
|
-
numpy = "^1.17"
|
|
12
|
-
pytz = "^2020.5"
|
|
13
|
-
shapely = "^1.7.1"
|
|
14
|
-
python-dateutil = "^2.8.1"
|
|
15
|
-
xarray = "^0.16.2"
|
|
16
|
-
cfgrib = "^0.9.8"
|
|
17
|
-
|
|
18
|
-
[tool.poetry.dev-dependencies]
|
|
19
|
-
|
|
20
|
-
[build-system]
|
|
21
|
-
requires = ["setuptools","poetry>=0.12"]
|
|
22
|
-
build-backend = "poetry.masonry.api"
|
cusfpredict-0.2.1/setup.py
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
from setuptools import setup
|
|
3
|
-
|
|
4
|
-
packages = \
|
|
5
|
-
['cusfpredict']
|
|
6
|
-
|
|
7
|
-
package_data = \
|
|
8
|
-
{'': ['*']}
|
|
9
|
-
|
|
10
|
-
install_requires = \
|
|
11
|
-
['cfgrib>=0.9.8,<0.10.0',
|
|
12
|
-
'fastkml>=0.11,<0.12',
|
|
13
|
-
'numpy>=1.17,<2.0',
|
|
14
|
-
'python-dateutil>=2.8.1,<3.0.0',
|
|
15
|
-
'pytz>=2020.5,<2021.0',
|
|
16
|
-
'requests>=2.25.1,<3.0.0',
|
|
17
|
-
'shapely>=1.7.1,<2.0.0',
|
|
18
|
-
'xarray>=0.16.2,<0.17.0']
|
|
19
|
-
|
|
20
|
-
setup_kwargs = {
|
|
21
|
-
'name': 'cusfpredict',
|
|
22
|
-
'version': '0.2.1',
|
|
23
|
-
'description': 'CUSF Predictor Wrapper & GFS Downloader',
|
|
24
|
-
'long_description': None,
|
|
25
|
-
'author': 'Mark Jessop',
|
|
26
|
-
'author_email': None,
|
|
27
|
-
'maintainer': None,
|
|
28
|
-
'maintainer_email': None,
|
|
29
|
-
'url': None,
|
|
30
|
-
'packages': packages,
|
|
31
|
-
'package_data': package_data,
|
|
32
|
-
'install_requires': install_requires,
|
|
33
|
-
'python_requires': '>=3.6,<4.0',
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
setup(**setup_kwargs)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|