diff options
author | Jonas Gunz <himself@jonasgunz.de> | 2024-10-15 00:05:51 +0200 |
---|---|---|
committer | Jonas Gunz <himself@jonasgunz.de> | 2024-10-15 00:05:51 +0200 |
commit | 244e7a27a9a6dca97e0a21bd29bd49e463e243e5 (patch) | |
tree | 8ff73800edf228df24ed219d926aa6c0813d6847 | |
parent | 185a43cede974de9ac18bec6312f892a7929346f (diff) | |
parent | 32863e21fa16e949fc20c4588e84b90916265367 (diff) | |
download | meteo_toolbox-244e7a27a9a6dca97e0a21bd29bd49e463e243e5.tar.gz |
Merge branch 'package_python'
-rw-r--r-- | .gitignore | 139 | ||||
-rw-r--r-- | examples/config.yaml (renamed from config.yaml) | 0 | ||||
-rw-r--r-- | metchart/aggregator/__init__.py (renamed from aggregator/__init__.py) | 0 | ||||
-rwxr-xr-x | metchart/aggregator/dwd_icon.py (renamed from aggregator/dwd_icon.py) | 2 | ||||
-rw-r--r-- | metchart/aggregator/misc.py (renamed from misc.py) | 0 | ||||
-rwxr-xr-x | metchart/aggregator/wyoming_sounding.py (renamed from aggregator/wyoming_sounding.py) | 2 | ||||
-rw-r--r-- | metchart/misc.py | 23 | ||||
-rw-r--r-- | metchart/modifier/__init__.py (renamed from modifier/__init__.py) | 0 | ||||
-rw-r--r-- | metchart/modifier/merge.py (renamed from modifier/merge.py) | 2 | ||||
-rw-r--r-- | metchart/plotter/__init__.py (renamed from plotter/__init__.py) | 0 | ||||
-rw-r--r-- | metchart/plotter/debug_data.py (renamed from plotter/debug_data.py) | 0 | ||||
-rwxr-xr-x | metchart/plotter/horizontal.py (renamed from plotter/horizontal.py) | 2 | ||||
-rwxr-xr-x | metchart/plotter/meteogram.py (renamed from plotter/meteogram.py) | 4 | ||||
-rwxr-xr-x | metchart/plotter/vertical_from_grib.py (renamed from plotter/vertical_from_grib.py) | 2 | ||||
-rwxr-xr-x | metchart/run.py | 110 | ||||
-rw-r--r-- | metchart/skewt.py (renamed from skewt.py) | 0 | ||||
-rw-r--r-- | pyproject.toml | 25 | ||||
-rw-r--r-- | requirements.txt | 5 | ||||
-rwxr-xr-x | run.py | 106 | ||||
-rw-r--r-- | testsetup.sh | 6 |
20 files changed, 310 insertions, 118 deletions
@@ -5,3 +5,142 @@ __pycache__ *.png *.idx web/data/ + +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ diff --git a/config.yaml b/examples/config.yaml index 4f2a23b..4f2a23b 100644 --- a/config.yaml +++ b/examples/config.yaml diff --git a/aggregator/__init__.py b/metchart/aggregator/__init__.py index e69de29..e69de29 100644 --- a/aggregator/__init__.py +++ b/metchart/aggregator/__init__.py diff --git a/aggregator/dwd_icon.py b/metchart/aggregator/dwd_icon.py index 6df905c..ed5c149 100755 --- a/aggregator/dwd_icon.py +++ b/metchart/aggregator/dwd_icon.py @@ -13,7 +13,7 @@ import subprocess import xarray as xr -import misc +from . import misc BASE='https://opendata.dwd.de/weather/nwp' diff --git a/misc.py b/metchart/aggregator/misc.py index 6594d0f..6594d0f 100644 --- a/misc.py +++ b/metchart/aggregator/misc.py diff --git a/aggregator/wyoming_sounding.py b/metchart/aggregator/wyoming_sounding.py index 111e219..617d462 100755 --- a/aggregator/wyoming_sounding.py +++ b/metchart/aggregator/wyoming_sounding.py @@ -12,7 +12,7 @@ import numpy as np from metpy.units import units import metpy.calc as mpcalc -import misc +from .. import misc def get_current_run(): date=(datetime.date.today() - datetime.timedelta(days = 1)).strftime('%Y-%m-%d') diff --git a/metchart/misc.py b/metchart/misc.py new file mode 100644 index 0000000..6594d0f --- /dev/null +++ b/metchart/misc.py @@ -0,0 +1,23 @@ +import os +import numpy as np +import datetime + +def np_time_convert(dt64, func=datetime.datetime.utcfromtimestamp): + unix_epoch = np.datetime64(0, 's') + one_second = np.timedelta64(1, 's') + seconds_since_epoch = (dt64 - unix_epoch) / one_second + + return func(seconds_since_epoch) + +def np_time_convert_offset(init, step): + return np_time_convert(init) + np_time_convert(step, func=lambda x: datetime.timedelta(seconds=x)) + +def np_time_list_convert_offset(init, steps): + return list(map(lambda x: np_time_convert_offset(init, x), steps)) + +def create_output_dir(path, clear=False): + if not os.path.exists(path): + os.makedirs(path) + elif clear: + raise Exception('clear not implemented') + diff --git a/modifier/__init__.py b/metchart/modifier/__init__.py index e69de29..e69de29 100644 --- a/modifier/__init__.py +++ b/metchart/modifier/__init__.py diff --git a/modifier/merge.py b/metchart/modifier/merge.py index 692287d..1fb7fda 100644 --- a/modifier/merge.py +++ b/metchart/modifier/merge.py @@ -1,4 +1,4 @@ -import xarray as xr +import xarray as xr def run(data): return xr.merge(data) diff --git a/plotter/__init__.py b/metchart/plotter/__init__.py index e69de29..e69de29 100644 --- a/plotter/__init__.py +++ b/metchart/plotter/__init__.py diff --git a/plotter/debug_data.py b/metchart/plotter/debug_data.py index 560d13c..560d13c 100644 --- a/plotter/debug_data.py +++ b/metchart/plotter/debug_data.py diff --git a/plotter/horizontal.py b/metchart/plotter/horizontal.py index 57317ef..7b35def 100755 --- a/plotter/horizontal.py +++ b/metchart/plotter/horizontal.py @@ -8,7 +8,7 @@ import numpy as np import matplotlib.pyplot as plt from metpy.plots import MapPanel, PanelContainer, RasterPlot, ContourPlot -import misc +from . import misc config = { 'source': 'dwd_icon-eu/combined.grib2', diff --git a/plotter/meteogram.py b/metchart/plotter/meteogram.py index 724e9b2..8335247 100755 --- a/plotter/meteogram.py +++ b/metchart/plotter/meteogram.py @@ -8,7 +8,7 @@ import matplotlib.pyplot as plt import metpy.calc as mpcalc -import misc +from .. import misc HEIGHT = 13 @@ -68,7 +68,7 @@ def _add_convective_clouds(ax, data): ax.set_ylabel('Convective Clouds Height [km]') ax.bar(data.valid_time, alpha=0.5, bottom=data.HBAS_CON.metpy.convert_units('km').transpose(), - height=(data.hcct.metpy.convert_units('km')-data.HBAS_CON.metpy.convert_units('km')).transpose(), + height=(data.HTOP_CON.metpy.convert_units('km')-data.HBAS_CON.metpy.convert_units('km')).transpose(), align='edge', width=np.timedelta64(3, 'h')) def _add_precip(ax, data): diff --git a/plotter/vertical_from_grib.py b/metchart/plotter/vertical_from_grib.py index 81f93bf..d341389 100755 --- a/plotter/vertical_from_grib.py +++ b/metchart/plotter/vertical_from_grib.py @@ -13,7 +13,7 @@ import numpy as np import skewt -import misc +from . import misc config = { 'source':'dwd_icon-eu/combined.grib2', diff --git a/metchart/run.py b/metchart/run.py new file mode 100755 index 0000000..17a0a97 --- /dev/null +++ b/metchart/run.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python3 + +import sys +import yaml +import json +import matplotlib.pyplot as plt +import matplotlib as mpl +from matplotlib.colors import LinearSegmentedColormap + +from metpy.units import units + +def create_aggregators(cfg): + ret = {} + for aggregator in cfg: + aggconf = cfg[aggregator] + classname = aggconf['module'] + del aggconf['module'] + + module = __import__(classname, fromlist=[None]) + + ret[aggregator] = module.load_data(name=aggregator, **aggconf) + + return ret + +def create_modifiers(aggregators, cfg): + # naming is scuffed + ret = {} + for modifier in cfg: + mod = cfg[modifier] + modname = mod['module'] + del mod['module'] + + if 'aggregator' in mod: + if type(mod['aggregator']) == list: + mod['data'] = [] + for ag in mod['aggregator']: + mod['data'].append(aggregators[ag]) + + del mod['aggregator'] + else: + mod['data'] = aggregators[mod['aggregator']] + del mod['aggregator'] + + pymod = __import__(modname, fromlist=[None]) + ret[modifier] = pymod.run(**mod) + + return ret + +def main(): + mpl.use('agg') + + # Define custom gpm and gpdm units. The default gpm in metpy is aliased to meter. + # We need the correct definition + units.define('_gpm = 9.80665 * J/kg') + units.define('_gpdm = 10 * _gpm') + + # Define custom colormap + clcov_cmap = { + 'red': ( + (0.0, 0.0, 0.0), + (0.1, 0.9, 0.9), + (1.0, 0.3, 0.3), + ), + 'green': ( + (0.0, 0.5, 0.5), + (0.1, 0.9, 0.9), + (1.0, 0.3, 0.3), + ), + 'blue': ( + (0.0, 0.9, 0.9), + (0.1, 0.9, 0.9), + (1.0, 0.3, 0.3), + ), + } + + mpl.colormaps.register(LinearSegmentedColormap('clcov', clcov_cmap)) + + FILE = 'config.yaml' + if len(sys.argv) > 1: + FILE = sys.argv[1] + + conf = None + with open(FILE, 'r') as f: + conf = yaml.safe_load(f) + + aggregators = create_aggregators(conf['aggregator']) + + if 'modifier' in conf: + aggregators.update(create_modifiers(aggregators, conf['modifier'])) + + index = [] + + for plotter in conf['plotter']: + modname = plotter['module'] + del plotter['module'] + + if 'aggregator' in plotter: + plotter['data'] = aggregators[plotter['aggregator']] + del plotter['aggregator'] + + mod = __import__(modname, fromlist=[None]) + index.extend(mod.run(**plotter)) + + plt.close('all') + + with open(conf['index'], 'w') as f: + f.write(json.dumps(index, indent=4)) + +if __name__ == '__main__': + main() diff --git a/skewt.py b/metchart/skewt.py index e674d09..e674d09 100644 --- a/skewt.py +++ b/metchart/skewt.py diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..3dbfe5c --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,25 @@ +[project] +name = "metchart" +version = "0.0.1" +dependencies = [ + "metpy", + "xarray", + "cfgrib", + "pyyaml", + "cartopy" +] +description = "declarative weather chart plotter" +readme = "Readme.md" +license = {"file" = "LICENSE"} + +[project.scripts] +metchart = "metchart.run:main" + +[tool.setuptools.packages.find] +include = [ + "metchart" +] + +[build-system] +requires = ['setuptools >= 61.0'] +build-backend = "setuptools.build_meta" diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 5b491b3..0000000 --- a/requirements.txt +++ /dev/null @@ -1,5 +0,0 @@ -metpy -xarray -cfgrib -pyyaml -cartopy @@ -1,106 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import yaml -import json -import matplotlib.pyplot as plt -import matplotlib as mpl -from matplotlib.colors import LinearSegmentedColormap - -from metpy.units import units - -def create_aggregators(cfg): - ret = {} - for aggregator in cfg: - aggconf = cfg[aggregator] - classname = aggconf['module'] - del aggconf['module'] - - module = __import__(classname, fromlist=[None]) - - ret[aggregator] = module.load_data(name=aggregator, **aggconf) - - return ret - -def create_modifiers(aggregators, cfg): - # naming is scuffed - ret = {} - for modifier in cfg: - mod = cfg[modifier] - modname = mod['module'] - del mod['module'] - - if 'aggregator' in mod: - if type(mod['aggregator']) == list: - mod['data'] = [] - for ag in mod['aggregator']: - mod['data'].append(aggregators[ag]) - - del mod['aggregator'] - else: - mod['data'] = aggregators[mod['aggregator']] - del mod['aggregator'] - - pymod = __import__(modname, fromlist=[None]) - ret[modifier] = pymod.run(**mod) - - return ret - -mpl.use('agg') - -# Define custom gpm and gpdm units. The default gpm in metpy is aliased to meter. -# We need the correct definition -units.define('_gpm = 9.80665 * J/kg') -units.define('_gpdm = 10 * _gpm') - -# Define custom colormap -clcov_cmap = { - 'red': ( - (0.0, 0.0, 0.0), - (0.1, 0.9, 0.9), - (1.0, 0.3, 0.3), - ), - 'green': ( - (0.0, 0.5, 0.5), - (0.1, 0.9, 0.9), - (1.0, 0.3, 0.3), - ), - 'blue': ( - (0.0, 0.9, 0.9), - (0.1, 0.9, 0.9), - (1.0, 0.3, 0.3), - ), -} - -mpl.colormaps.register(LinearSegmentedColormap('clcov', clcov_cmap)) - -FILE = 'config.yaml' -if len(sys.argv) > 1: - FILE = sys.argv[1] - -conf = None -with open(FILE, 'r') as f: - conf = yaml.safe_load(f) - -aggregators = create_aggregators(conf['aggregator']) - -if 'modifier' in conf: - aggregators.update(create_modifiers(aggregators, conf['modifier'])) - -index = [] - -for plotter in conf['plotter']: - modname = plotter['module'] - del plotter['module'] - - if 'aggregator' in plotter: - plotter['data'] = aggregators[plotter['aggregator']] - del plotter['aggregator'] - - mod = __import__(modname, fromlist=[None]) - index.extend(mod.run(**plotter)) - - plt.close('all') - -with open(conf['index'], 'w') as f: - f.write(json.dumps(index, indent=4)) diff --git a/testsetup.sh b/testsetup.sh new file mode 100644 index 0000000..abe19dc --- /dev/null +++ b/testsetup.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +[ ! -f venv/bin/activate ] && python -m virtualenv venv +source venv/bin/activate + +pip install -e . |