aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Jonas Gunz <himself@jonasgunz.de> 2024-10-15 00:05:51 +0200
committerGravatar Jonas Gunz <himself@jonasgunz.de> 2024-10-15 00:05:51 +0200
commit244e7a27a9a6dca97e0a21bd29bd49e463e243e5 (patch)
tree8ff73800edf228df24ed219d926aa6c0813d6847
parent185a43cede974de9ac18bec6312f892a7929346f (diff)
parent32863e21fa16e949fc20c4588e84b90916265367 (diff)
downloadmeteo_toolbox-244e7a27a9a6dca97e0a21bd29bd49e463e243e5.tar.gz
Merge branch 'package_python'
-rw-r--r--.gitignore139
-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-xmetchart/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-xmetchart/aggregator/wyoming_sounding.py (renamed from aggregator/wyoming_sounding.py)2
-rw-r--r--metchart/misc.py23
-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-xmetchart/plotter/horizontal.py (renamed from plotter/horizontal.py)2
-rwxr-xr-xmetchart/plotter/meteogram.py (renamed from plotter/meteogram.py)4
-rwxr-xr-xmetchart/plotter/vertical_from_grib.py (renamed from plotter/vertical_from_grib.py)2
-rwxr-xr-xmetchart/run.py110
-rw-r--r--metchart/skewt.py (renamed from skewt.py)0
-rw-r--r--pyproject.toml25
-rw-r--r--requirements.txt5
-rwxr-xr-xrun.py106
-rw-r--r--testsetup.sh6
20 files changed, 310 insertions, 118 deletions
diff --git a/.gitignore b/.gitignore
index 77f7ec4..d753af1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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
diff --git a/run.py b/run.py
deleted file mode 100755
index 28362d9..0000000
--- a/run.py
+++ /dev/null
@@ -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 .