#!/usr/bin/env python # Wenchang Yang (wenchang@princeton.edu) # Wed Apr 9 01:50:48 PM EDT 2025 if __name__ == '__main__': import sys,os try: from misc.timer import Timer tt = Timer(f'[{os.getcwd()}] start ' + ' '.join(sys.argv)) except: pass import sys, os.path, os, glob, datetime import xarray as xr, numpy as np, pandas as pd, matplotlib.pyplot as plt #more imports wython = '/tigress/wenchang/wython' if wython not in sys.path: sys.path.append(wython); print('added to python path:', wython) #from misc import get_kws_from_argv # if __name__ == '__main__': try: tt.check('end import') except: pass # #start from here ifile = 'tracks.hurdat2.1851-2024.nc' ds = xr.open_dataset(ifile) #all storms (ST) ofile = ifile.replace('tracks', 'nST') if os.path.exists(ofile) and 'od' not in sys.argv: nST = xr.open_dataarray(ofile) print('[loaded]:', ofile) else: L = ds.lat.count('stage')>0 #any storm that has valid track points nST = L.sum('storm') nST.to_dataset(name='nST').to_netcdf(ofile) print('[saved]:', ofile) #named storms (NM) ofile = ifile.replace('tracks', 'nNM') if os.path.exists(ofile) and 'od' not in sys.argv: nNM = xr.open_dataarray(ofile) print('[loaded]:', ofile) else: L = ~ds.stormName.isin(['UNNAMED', '']) #any storm that has a valid name nNM = L.sum('storm') nNM.to_dataset(name='nNM').to_netcdf(ofile) print('[saved]:', ofile) #TS ofile = ifile.replace('tracks', 'nTS') if os.path.exists(ofile) and 'od' not in sys.argv: nTS = xr.open_dataarray(ofile) print('[loaded]:', ofile) else: L1 = ds.stormStatus.isin(['TS', 'HU']).any('stage') # any storm that has track points of status TS or HU #L2 = (ds.windmax>=17).any('stage') nTS = L1.sum('storm') nTS.to_dataset(name='nTS').to_netcdf(ofile) print('[saved]:', ofile) #TS plus: TS with wind max > 17m/s for at least 2 days ofile = ifile.replace('tracks', 'nTSplus') if os.path.exists(ofile) and 'od1' not in sys.argv: nTSplus = xr.open_dataarray(ofile) print('[loaded]:', ofile) else: L1 = ds.stormStatus.isin(['TS', 'HU']).any('stage') # any storm that has track points of status TS or HU L2 = (ds.windmax>17).sum('stage') > 8 # nTSplus = (L1 & L2).sum('storm') nTSplus.to_dataset(name='nTSplus').to_netcdf(ofile) print('[saved]:', ofile) #HU ofile = ifile.replace('tracks', 'nHU') if os.path.exists(ofile) and 'od' not in sys.argv: nHU = xr.open_dataarray(ofile) print('[loaded]:', ofile) else: L1 = ds.stormStatus=='HU' #any storm that has track points of status HU #L2 = ds.windmax_knot>=64 nHU = L1.any('stage').sum('storm') nHU.to_dataset(name='nHU').to_netcdf(ofile) print('[saved]:', ofile) #MH ofile = ifile.replace('tracks', 'nMH') if os.path.exists(ofile) and 'od' not in sys.argv: nMH = xr.open_dataarray(ofile) print('[loaded]:', ofile) else: L1 = ds.stormStatus=='HU' #any storm that has track points of status TS or HU L2 = ds.windmax_knot>96 #any storm that has track points of windmax_knot > 96 nMH = (L1 & L2).any('stage').sum('storm') nMH.to_dataset(name='nMH').to_netcdf(ofile) print('[saved]:', ofile) if __name__ == '__main__': from wyconfig import * #my plot settings if 'long' in sys.argv: yearslice = slice(1851, 2024) else: yearslice = slice(1980, 2024) if yearslice is not None: nST = nST.sel(year=yearslice) nNM = nNM.sel(year=yearslice) nTS = nTS.sel(year=yearslice) nTSplus = nTSplus.sel(year=yearslice) nHU = nHU.sel(year=yearslice) nMH = nMH.sel(year=yearslice) fig, ax = plt.subplots(figsize=(8,4)) marker = 'o' if yearslice.start==1980 else None marker_namedStorm = '^' if yearslice.start==1980 else None nST.plot(label='all storms', marker=marker, fillstyle='none') if 'long' not in sys.argv: nNM.plot(label='named storms', marker=marker_namedStorm, fillstyle='none') nTS.plot(label='TS', marker=marker, fillstyle='none') if 'long' not in sys.argv: nTSplus.plot(label='TS2days17', marker=marker_namedStorm, fillstyle='none') nHU.plot(label='HU', marker=marker, fillstyle='none') nMH.plot(label='MH', marker=marker, fillstyle='none') ax.legend(loc='upper left') ax.set_title('HURDAT2 storms') ax.set_ylabel('#') #savefig if 'savefig' in sys.argv or 's' in sys.argv: figname = __file__.replace('.py', f'.png') if yearslice is not None: figname = figname.replace('.png', f'__{yearslice.start}-{yearslice.stop}.png') if 'overwritefig' in sys.argv or 'o' in sys.argv: wysavefig(figname, overwritefig=True) else: wysavefig(figname) try: tt.check(f'**Done**') except: pass print() if 'notshowfig' in sys.argv or 'n' in sys.argv: pass else: if 'plt' in globals(): plt.show()