#!/usr/bin/env python # Wenchang Yang (wenchang@princeton.edu) # Thu Apr 16 10:27:14 AM EDT 2026 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 #from xtc.distance import gcdistance import xtc import math # if __name__ == '__main__': try: tt.check('end import') except: pass # #start from here """ #the first get_circule_points func is from Google Gemini, replaced by the np version def get_circle_points(lat, lon, radius_km, num_points=100): R = 6371.0 # Earth's radius in km lat1, lon1 = math.radians(lat), math.radians(lon) d_div_R = radius_km / R circle_lats, circle_lons = [], [] for theta in np.linspace(0, 2 * np.pi, num_points): lat2 = math.asin(math.sin(lat1) * math.cos(d_div_R) + math.cos(lat1) * math.sin(d_div_R) * math.cos(theta)) lon2 = lon1 + math.atan2(math.sin(theta) * math.sin(d_div_R) * math.cos(lat1), math.cos(d_div_R) - math.sin(lat1) * math.sin(lat2)) circle_lats.append(math.degrees(lat2)) circle_lons.append(math.degrees(lon2)) return circle_lats, circle_lons """ def get_circle_points(lat, lon, radius_km, num_points=100): R = 6371.0 # Earth's radius in km lat1, lon1 = np.radians(lat), np.radians(lon) d_div_R = radius_km / R theta = np.linspace(0, 2 * np.pi, num_points) circle_lats = np.arcsin(np.sin(lat1) * np.cos(d_div_R) + np.cos(lat1) * np.sin(d_div_R) * np.cos(theta)) circle_lons = lon1 + np.arctan2(np.sin(theta) * np.sin(d_div_R) * np.cos(lat1), np.cos(d_div_R) - np.sin(lat1) * np.sin(circle_lats)) return np.degrees(circle_lats), np.degrees(circle_lons) R = get_kws_from_argv('R', 150) #km, threshold of distance to TC center R = int(R) """ location = get_kws_from_argv('location', 'MulletPond') # 'EasternLake' if location == 'MulletPond': lat0, lon0 = 29.925333, 275.662083 elif location == 'EasternLake': lat0, lon0 = 30.311627, 273.906765 """ locations = [('MulletPond', 29.925333, 275.662083), ('EasternLake', 30.311627, 273.906765)] wind = get_kws_from_argv('wind', 33) if wind is not None: wind = int(wind) ifile = '/projects/w/wenchang/analysis/TC/HIRAM/amipLMR2019SST0850ic_tigercpu_intelmpi_18_540PE/netcdf/tc_tracks.TS.ens01.0850-1999.nc' ds = xr.open_dataset(ifile) if ds.en.size == 1: ds = ds.squeeze('en', drop=True) if __name__ == '__main__': from wyconfig import * #my plot settings from geoplots import mapplot fig,ax = plt.subplots(figsize=(8,4)) for location,lat0,lon0 in locations: print(location) color = 'C0' if location == 'MulletPond' else 'C1' d = xtc.tc_distance(ds, lat0, lon0, units='km') #d = tc_distance(ds, 29.9253, 275.662, units='km') if wind is not None: L = ((d<=R)&(ds.windmax>wind)).any('stage') else: L = (d<=R).any('stage') ntc = xtc.tc_count(ds.where(L)).sum('time').item() lon = ds.lon ds['lon'] = lon.where(~((lon<0).any('stage')), other=lon+360) ds.where(L).tc.trackplot(ezplot=True, lw=0.5, alpha=0.5, color=color, ax=ax) ax.plot(lon0, lat0, marker='x', color=color) lats, lons = get_circle_points(lat0, lon0, radius_km=R) ax.plot(lons, lats, color=color, label=f'{location}, {ntc} TC{wind}') mapplot() ax.set_title('HiRAM last millennium simulation TC tracks passing two locations') ax.legend(loc='upper left', frameon=True) #savefig if 'savefig' in sys.argv or 's' in sys.argv: figname = __file__.replace('.py', f'.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()