diff options
author | Jonas Gunz <himself@jonasgunz.de> | 2024-10-14 02:23:10 +0200 |
---|---|---|
committer | Jonas Gunz <himself@jonasgunz.de> | 2024-10-14 02:23:10 +0200 |
commit | 663edde231af9ad4a782c5438027ef7f839806ea (patch) | |
tree | 3e0d6745e5b1c633a76e404a56b734caddcf6b37 /metchart/skewt.py | |
parent | 9e5f1d17a4b0165bd4a3218ca24a159012ea49bd (diff) | |
download | meteo_toolbox-663edde231af9ad4a782c5438027ef7f839806ea.tar.gz |
package with python
Diffstat (limited to 'metchart/skewt.py')
-rw-r--r-- | metchart/skewt.py | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/metchart/skewt.py b/metchart/skewt.py new file mode 100644 index 0000000..e674d09 --- /dev/null +++ b/metchart/skewt.py @@ -0,0 +1,118 @@ +import matplotlib.gridspec as gridspec +import matplotlib.pyplot as plt + +import numpy as np + +import metpy.calc as mpcalc +from metpy.cbook import get_test_data +from metpy.plots import add_metpy_logo, Hodograph, SkewT +from metpy.units import units + +class Skewt: + def __init__(self, p, T, Td, max_barbs=20, title=None): + self._p = p + self._T = T + self._Td = Td + + self._info_lines = [] + + self.barb_div = int(max(len(p)/max_barbs,1)) + + + # Create a new figure. The dimensions here give a good aspect ratio + self._fig = plt.figure(figsize=(9, 9)) + plt.rcParams["font.family"] = "monospace" + #self._fig = plt.figure() + + if title is not None: + plt.suptitle(title, x=0, y=0, va='bottom', ha='left') + + # Grid for plots + self._gs = gridspec.GridSpec(3, 3) + self._skew = SkewT(self._fig, rotation=45, subplot=self._gs[:, :2]) + + # Plot the data using normal plotting functions, in this case using + # log scaling in Y, as dictated by the typical meteorological plot + self._skew.plot(p, T, 'r') + self._skew.plot(p, Td, 'b') + + plt.xlabel('$T$ $[^o C]$') + plt.ylabel('$p$ $[hPa]$') + + def addWindUV(self, u, v): + self._u = u + self._v = v + + ax = self._fig.add_subplot(self._gs[0, -1]) + h = Hodograph(ax, component_range=max(u + v).magnitude) + h.add_grid(increment=20) + h.plot_colormapped(u, v, self._p) + plt.tight_layout() + plt.xlabel('$m/s$') + plt.ylabel('$m/s$') + + self._skew.plot_barbs(self._p[::self.barb_div], u[::self.barb_div], v[::self.barb_div]) + + def addInfo(self, line): + self._info_lines.append(line) + + def addAnalysis(self, analysis='ccl', shade=False): + f = {'ccl': self._cclAnalysis, 'lcl': self._lclAnalysis} + + lvl, parcel = f[analysis]() + + self._skew.plot(self._p, parcel, 'y') + self._skew.plot(lvl[0], lvl[1], 'o', markerfacecolor='red', linewidth=1) + + # TODO why exception on cape_cin()? + # ValueError: zero-size array to reduction operation minimum which has no identity + # https://github.com/Unidata/MetPy/pull/3132 + try: + cape, cin = mpcalc.cape_cin(self._p, self._T, self._Td, parcel, which_el='top') + self.addInfo(f'CAPE {int(cape.magnitude)} $J/kg$ CIN {int(cin.magnitude)} $J/kg$') + except ValueError: + print('CAPE/CIN Failed with ValueError') + self.addInfo('CAPE #### CIN ####') + + if shade: + self._skew.shade_cape(self._p,self._T,parcel) + self._skew.shade_cin(self._p,self._T,parcel) + + def _cclAnalysis(self): + #p = np.arange(max(self._p).magnitude, min(self._p).magnitude, -50) * units.hPa + + ccl = mpcalc.ccl(self._p,self._T,self._Td) + ccl_ground=mpcalc.dry_lapse(self._p[:1], ccl[1], ccl[0]) + ccl_ground_parcel= mpcalc.parcel_profile(self._p, ccl_ground[0], self._Td[0]) + + return (ccl, ccl_ground_parcel) + + def _lclAnalysis(self): + ground_parcel= mpcalc.parcel_profile(self._p, self._T[0], self._Td[0]) + lcl = mpcalc.lcl(self._p[0],self._T[0],self._Td[0]) + + return (lcl, ground_parcel) + + def _buildInfoBox(self): + ax = self._fig.add_subplot(self._gs[1,-1]) + ax.text(0, 0, '\n'.join(self._info_lines), ha='left', va='center', + size=10, fontfamily='monospace') + ax.axis("off") + + def plot(self, filename=None): + self._buildInfoBox() + + # Add the relevant special lines + #self._skew.ax.set_ylim(max(self._p), min(self._p)) + self._skew.ax.set_ylim(1000, 100) + self._skew.plot_dry_adiabats(linewidth=1) + self._skew.plot_moist_adiabats(linewidth=1) + self._skew.plot_mixing_lines(linewidth=1) + + # Good bounds for aspect ratio + self._skew.ax.set_xlim(-30, 40) + + if filename is not None: + plt.savefig(filename) + else: + plt.show() |