diff --git a/diagnostics/TUTT/TUTT.html b/diagnostics/TUTT/TUTT.html new file mode 100644 index 000000000..a929fb18c --- /dev/null +++ b/diagnostics/TUTT/TUTT.html @@ -0,0 +1,20 @@ +MDTF TUTT diagnostic + + +

Tropical Upper-Troposheric Trough (TUTT) Diagnostics

+

+Tropical upper-tropospheric troughs (TUTTs) are part of summertime stationary waves and +provide a unified framework that can be used to better understand variability of tropical +cyclones (TCs) over different basins. Identifying deficiencies in representing TUTTs has +important implications for the improved regional TC simulation in climate models. A better +understanding of how TUTTs will change as climate warms also increases our confidence in +future TC projection. This diagnostic package is used to evaluate 200-hPa TUTT area in +both climate models and reanalysis datasets. +

+ + + +
TUTT +plot +plot +
diff --git a/diagnostics/TUTT/TUTT.py b/diagnostics/TUTT/TUTT.py new file mode 100644 index 000000000..8c4edd5b5 --- /dev/null +++ b/diagnostics/TUTT/TUTT.py @@ -0,0 +1,89 @@ +# 28 June TUTT.py +# Tropical Upper Tropospheric Trough Diagnostic Package +# +# ================================================================================ +# +# Last update: 28 June, 2021 +# PI: Zhuo Wang, zhuowang@illinois.edu, DAS UIUC) +# Developer/point of contact (Zhuo Wang, Gan Zhang, Chuan-Chieh Chang, and Jiacheng Ye, DAS UIUC) +# +# Tropical upper-tropospheric troughs (TUTTs) are part of summertime stationary waves and +# provide a unified framework that can be used to better understand variability of tropical +# cyclones (TCs) over different basins.Identifying deficiencies in representing TUTTs +# has important implications for the improved regional TC simulation in climate models. A better +# understanding of how TUTTs will change as climate warms also increases our confidence in +# future TC projection. This diagnostic package is used to evaluate 200-hPa TUTT area in +# both climate models and reanalysis datasets. +# +# Version and contact info +# +# - Version: 1.0 +# - Contact info: +# Zhuo Wang (zhuowang@illinois.edu) +# +# ================================================================================ +# Functionality +# +# 1) Calculates geostrophic zonal winds (Ug) using 200-hPa geopotential height with a fixed Coriolis parameter at 15N. +# 2) Identifies positions of the circumglobal contour of the long-term seasonal-mean Ug. The value of Ug can be specified by the user, and usually ranges from 1 to 2 m/s. The zonal-mean latitude of the circumglobal contour is chosen as the reference latitude. +# 3) The TUTT index is estimated from the area where the circumglobal contour of seasonal-mean Ug extends southward of the reference latitude. +# 4) Calculates TUTT strength and central location. +# +# +# ================================================================================ +# +# All scripts of this package can be found under: /diagnostics/TUTT/ +# & observational data under: /obs_data/TUTT/ +# +# 3-D (time-lat-lon) 200 hPa geopotential height fields are required; +# +# Required programming language: Tested in the Python 3.7 envrionment; +# Required libraries: "netCDF4", "skimage", "numpy", "scipy", "shapely.geometry", "cartopy" +# +# ================================================================================ +# Reference: +# Wang, Z., Zhang, G., Dunkerton, T. J., & Jin, F. F. (2020). +# Summertime stationary waves integrate tropical and extratropical impacts on tropical cyclone activity. +# Proceedings of the National Academy of Sciences of the United States of America, 117(37), 22720-22726. https://doi.org/10.1073/pnas.2010547117 +# +# Chuan-Chieh Chang and Zhuo's paper is in preparation... +#Title: Chang, C.-C. and Z. Wang, 2021: Summertime Subtropical Stationary Waves: Variability and Impacts on the Tropical Cyclone Activity + + +# driver file +import os +import glob + +#obs_running=1 # =1 if the user wishes to run the example; =0 if the user wishes to disable it. +#model_running=1 # =1 if the user wishes to run the model data; =0 if the user wishes to disable it. + +missing_file=0 +if len(glob.glob(os.environ["OMEGA_FILE"]))==0: + print("Required HGT200 data missing!") + missing_file=1 + +if missing_file == 1: + print("TUTT Diag Package will NOT be executed!") +else: + try: + os.system("python3 "+os.environ["POD_HOME"]+"/"+"TUTT_calc_obs.py") + print("The TUTT diag based on example data has been successfully conducted!") + except OSError as e: + print('WARNING',e.errno,e.strerror) + print("**************************************************") + print("TUTT_diag_obs.py based on example data is NOT Executed as Expected!") + print("**************************************************") + try: + os.system("python3 "+os.environ["POD_HOME"]+"/"+"TUTT_calc_model.py") + print("The TUTT diag based on model data has been successfully conducted!") + except OSError as e: + print('WARNING',e.errno,e.strerror) + print("**************************************************") + print("TUTT_diag_model.py based on model data is NOT Executed as Expected!") + print("**************************************************") + + print("**************************************************") + print("Tropical Upper-Tropospheric Trough Diagnostics Executed!") + print("**************************************************") + + diff --git a/diagnostics/TUTT/TUTT_calc_model.py b/diagnostics/TUTT/TUTT_calc_model.py new file mode 100644 index 000000000..0a62cd0e9 --- /dev/null +++ b/diagnostics/TUTT/TUTT_calc_model.py @@ -0,0 +1,645 @@ +#Jun 29 2021 +import matplotlib.pyplot as pyplot +import numpy as np +from normalize import normalize +# http://netcdf4-python.googlecode.com/svn/trunk/docs/netCDF4-module.html +from netCDF4 import Dataset, num2date +# http://scikit-image.org/ +from skimage import measure +from shapely.geometry import Polygon, LineString +from scipy.signal import argrelextrema +from scipy.stats.stats import pearsonr +from scipy.interpolate import interp2d +from scipy.interpolate import RectBivariateSpline +import cartopy.crs as ccrs +import cartopy.mpl.ticker as cticker + +lat_coord = os.environ["lat_coord"] +lon_coord = os.environ["lon_coord"] +z200_var = os.environ["z200_var"] +WK_DIR = os.environ["WK_DIR"] +CASENAME = os.environ["CASENAME"] + +def add_cyclic_BL(dat,lon): + if dat.shape[2]!=lon.shape[0]: + print('Dimension error in the input data!') + return + dat1=np.zeros((dat.shape[0],dat.shape[1],dat.shape[2]+1)) + lon1=np.zeros(lon.shape[0]+1) + dat1[:,:,:-1]=dat + dat1[:,:,-1]=dat[:,:,0] + lon1[:-1]=lon + lon1[-1]=lon[0] + return(dat1,lon1) + +######################################### +# Input Data +######################################### +#parameters +#g=9.81 +#CMIP6 models unit is m +#does not need to separate by 9.81 +g=9.81 +#dlat=2.5 +ra=6371000. +omega=7.2921/100000. + +#input file specified +filein=os.environ["Z200_FILE"]; vname=z200_var +print("Input File: "+filein) + +##Sometimes Pacific and Atlantic TUTTs are connected together +##choose the separating longitude option here (Jay) +##ridge_option=1, the script will search the longitude where the geopotential height is the largest between 120W-80W +##the geopotential height is averaged between the subtropics (20-30N) +##Sometimes the ridge may be weak over Central America (due to model biases), so the user can set perferred separating longitude (ridge_option=2) +print("The script will search TUTT boundary based on zonal geostrophic wind (Ug) contour") +UG_N15_target = float(input("Enter a Ug value (suggested between 1.0-2.0): ")) + +print("Sometimes Pacific and Atlantic TUTTs are connected together") +print("Please choose the separating longitude option here") +print("ridge_option=1, the script will search the subtropical ridge over Central America (120W-80W)") +print("ridge_option=2, the dividing longitude is specified by the user") +ridge_option = int(input("Enter a number for ridge_option: ")) +if ridge_option==2: + user_dividing_longitude = int(input("Enter a number between 240-280 (120 W-80 W): ")) + +#Ug (15N) value that determines the HGTy & TUTT contour +lat_target=15 + +#Minimum TUTT areas, measure by the product of the latitude range and the longitude range +#It is a necessary threshold to remove some small wiggles in certain years +min_TUTT=100 + +#Latitude range to search for HGTy contours +latN=90 +latS=-10 + +#The longitude ranges for the two basins. +#lonx_AtlW should be the largest possible eastern boundary of the TUTT(Pac). If a point falls east of +#this longitude, we regard it as related to the Atl TUTT +#lonx_PacE should be the largest possible western boundary of the TUTT(Atl). If a point falls west of +#this longitude, we regard it as related to the Pac TUTT +lonx_PacE=270 +lonx_AtlW=240 + +#ref_lat is shifted southward by lat_shift to avoid the connection of TUTT(Pac) with TUTT(Atl) +#south of the ref. latitude. This, however, may render zero TUTT in some years, especially over Atl +lat_shift=-0.0 + +#time range +#ZW: Something went wrong when I adjusted iyr2 +iyr1 = int(input("Enter start year of data: ")) +iyr2 = int(input("Enter end year of data: ")) +imn1 = int(input("Enter start month you want: ")) +imn2 = int(input("Enter end month you want: ")) +nyr = iyr2-iyr1+1 +nmon = imn2-imn1+1 + +#Jay:choose whether the .txt files will be outputted +output_opt = int(input("Do you want to output general TUTT information as .txt? (area,strength,central location; 1=yes, 2=no): ")) +output_opt2=int(input("Do you want to output detail TUTT information as .txt? (locations of TUTT contour; 1=yes, 2=no): ")) + +#month string info +chmon=['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'] +chmns='JFMAMJJASOND' + +if imn1==imn2: + smon=chmon[imn1-1] +else: + smon=chmns[imn1-1:imn2] + +#plot monthly data in an individual year? +#if Ture, find "# use this when plotting monthly data in individual years" and make changes +#plotting seasonal mean data is possible, but needs some tuning to avoid error messages +plot_yn=True + +#output file for ref. lat +if output_opt==1: + filetxt=WK_DIR+'/model/'+CASENAME+'_tutt_ref.latitude-'+str(iyr1)+'-'+str(iyr2)+smon+'-Ug_'+str(UG_N15_target)+'.txt' + f0=open(filetxt,'w+') + f0.write('Year Ref.Lat Ref.Lat0'+'\n') + +#create an arrary to store TUTT information +#ZW: There may be 3 TUTT regions when analyzing monthly mean data +tutt_index=np.zeros( (nyr, 2) ) #extent +tutt_lon_wt=np.zeros( (nyr, 2) )#area centroid weighted by Ug +tutt_lat_wt=np.zeros( (nyr, 2) ) +tutt_lon=np.zeros( (nyr, 2) ) #area centroid +tutt_lat=np.zeros( (nyr, 2) ) +tutt_int=np.zeros( (nyr, 2) ) #intensity + +#linux-like routine +ncFid = Dataset (filein, mode = "r") + +#read variables in the file; select the vertical level + +lon0 = ncFid.variables[ lon_coord ][:] +lat0 = ncFid.variables[ lat_coord ][:] + +#calculate latlon intervals, assuming regular grid spacing +dlon=lon0[1]-lon0[0] +dlat=lat0[1]-lat0[0] + +#confine the analysis to the northern hemisphere TUTT between 10S to 90N +#ZW: np.argmin is used to find the index of the closest value +ilat1=np.argmin(abs(lat0-latS)) +ilat2=np.argmin(abs(lat0-latN)) + +#switch ilat1 and ilat2 if the data starting from the NP; isign is set to -1 +#to take into account of the geostrophic wind calculation for reversed latitude +isign=1 +if dlat<0: + ii=ilat1 + ilat1=ilat2 + ilat2=ii + isign=-1 + +lat=lat0[ilat1:ilat2] +hgt_all = np.squeeze( ncFid.variables[ vname ][:,ilat1:ilat2,:] ) + +#data from S to N, does not need to be reversed (Jay) +if isign==1: + lat=np.array(lat[:]) + hgt_all=np.array(hgt_all[:,:,:]) + dlat=dlat +#data from N to S, need to be reversed (Jay) +if isign==-1: + lat=np.array(lat[::-1]) + hgt_all=np.array(hgt_all[:,::-1,:]) + dlat=-dlat + +#get date information +time = ncFid.variables[ "time" ][:] +time_units = ncFid.variables[ "time" ].units +datevar=num2date(time,time_units) + +#store date information +tsteps=len(time) +yr_hgt=np.zeros(tsteps) +mon_hgt=np.zeros(tsteps) +for i in range(tsteps): + yr_hgt[i]=datevar[i].year + mon_hgt[i]=datevar[i].month + +#indices of interested time range +D1=np.where((mon_hgt >= imn1) & (mon_hgt <= imn2) & (yr_hgt >= iyr1) & (yr_hgt <= iyr2))[0] +#print(D1) +#D2 saves the indices for the first month in a year +if imn2==imn1: #just one calendar month per year + D2=D1 +else: + D2=D1[0:-1:nmon] + +#get seasonal mean values of HGT +hgt_in=np.zeros([nyr,ilat2-ilat1,lon0.size]) +if imn2==imn1: #just one calendar month per year + hgt_in=hgt_all[D1,:,:]/1 +else: + for i in range(nyr): #seasonal mean + hgt_in[i,:,:]=np.mean(hgt_all[D1,:,:][i*nmon:i*nmon+nmon,:,:], axis=0)/1 + +#meridional gradient of HGT +hgt_y=np.gradient(hgt_in, axis=1)/(dlat/180*np.pi*ra) + +#geostrophic wind +UG=-hgt_y*g/((2.*omega*np.sin(np.pi*lat_target/180.))) +#get gradient value that correspond to UG_N15_target value +#For a reserved latitude mesh, dlat<0 and this is taken into account in hgt_y +hgty_target=-UG_N15_target/g*(2.*omega*np.sin(np.pi*lat_target/180.)) + +#add cyclic points for longtitude dim +hgt_in, lon = add_cyclic_BL(hgt_in, lon0 ) +hgt_y, lon = add_cyclic_BL(hgt_y, lon0 ) +#Jay: make the final longitude index to be 360, instead of 0 +lon[len(lon0)]=360.0 + +#plot_yn=True +#ZW# UG, lon = addcyclic(UG, lon0 ) +lons, lats = np.meshgrid(lon, lat) + +#set up the plotting window +if plot_yn: + fig, axes = pyplot.subplots(figsize=(8,4)) + ilat=np.argsort(lat) + ilon=np.argsort(lon) + axes = pyplot.axes(projection=ccrs.PlateCarree(central_longitude=180)) + axes.set_extent([0, 355, -5, 55], crs=ccrs.PlateCarree()) + clevs=np.arange(11840,12610,40.) + im0 = axes.contourf(lon0,lat,np.mean(hgt_in[:,:,0:len(lon0)],axis=0) ,clevs,cmap = pyplot.get_cmap('RdBu_r'),extend='both',transform=ccrs.PlateCarree()) +# print(lat,np.sum(np.isnan(hgt_in))) +# im1 = axes.contour(lon, lat, np.mean(hgt_in,axis=0) , 20,linewidths=0.5,cmap = pyplot.get_cmap('RdBu_r'),extend='both',transform=ccrs.PlateCarree()) + + +#ZW: define the ref_lat0 based on the long-term mean +contour_yn=False +hgt_ym=np.mean(hgt_y,axis=0) #long-term mean +contours= measure.find_contours(hgt_ym, hgty_target) +if len(contours) != 0: + #identify the longest contour, candidate for circumglobal contour + #length is measured by number of grid points along a contour + contour=max(contours, key=len) + #only keep the longest contour, which may be circum-global + #ZW: contour[:,1] saves longitude indices in the reversed order + #check if the contour is circum-global + if len(contour) >= lon.size and contour[-1,1]+contour[0,1] == lon.size-1: + #convert coordinates to latlon + lonx0=lon[0]+dlon*contour[:, 1] + latx0=lat[0]+dlat*contour[:, 0] + #reverse the order so that lonx goes from W to E + if lonx0[1]>lonx0[2]: + lonx=lonx0[::-1] + latx=latx0[::-1] + else: + lonx=lonx0 + latx=latx0 + + print("Found contours in the long-term mean") + contour_yn=True + + #reference latitude, weighted avarage of the latitude of HGTy contour + #An alternate is to define ref_lat based on the latitude of the zonal mean Ug + #The difference in TUTT between the two ref_lat is a constant number and does + #not affect the corr/composite analysis + #ref_lon0 is the same as ref_lon, but a different array is created for clarity + ref_lon0=lon + dlonx=np.abs(np.gradient(lonx)) + #calculate ref_lat as an weighted average; ref_lat is then shift by "lat_shift" degree + ref_lat0=np.ones(lon.size)*np.sum(latx*dlonx)/np.sum(dlonx) - lat_shift + +#ref_lat0[:]=20.160798378056562 + +#set UG=np.nan north of ref_lat0 +ref_j0=np.argmin(abs(lat-ref_lat0[0])) +ref_0N=np.argmin(abs(lat-0)) +UG[:,ref_j0+1:,:]=np.NaN #only consider data between 0N and ref_lat +UG[:,:ref_0N,:]=np.NaN +UG[np.where(UG= lon.size and contour[-1,1]+contour[0,1] == lon.size-1: + #convert coordinates to lat-lon; find_contours provides desending lon values + #ZW: lonx0=dlat*contour[:, 1] + #ZW: latx0=latN-dlat*contour[:, 0] + lonx0=lon[0]+dlon*contour[:, 1] + latx0=lat[0]+dlat*contour[:, 0] + + #reverse the order so that lonx goes from W to E + if lonx0[1]>lonx0[2]: + lonx=lonx0[::-1] + latx=latx0[::-1] + else: + lonx=lonx0 + latx=latx0 + + print("Found contours") + contour_yn=True + + # Plot the contour on the basemap + + if plot_yn: + axes.plot(lonx, latx, linewidth=1, color='gray',transform=ccrs.PlateCarree()) + +#output TUTT contour position + length=np.zeros((1)) + length[0]=len(lonx) + ref_lat_out=np.zeros((len(lonx))) + hgt_along_ref_lat=np.zeros((len(lonx))) + for ii in range(len(lonx)): +# print(ref_lat0) + ref_lat_out[ii]=ref_lat0[0] + if output_opt2==1: + np.savetxt(WK_DIR+'/model/'+CASENAME+'_TUTT_ref_lat_'+str(it+iyr1)+'-Ug_'+str(UG_N15_target)+'.txt',ref_lat_out) + np.savetxt(WK_DIR+'/model/'+CASENAME+'_TUTT_contour_length_'+str(it+iyr1)+'-Ug_'+str(UG_N15_target)+'.txt',length) + np.savetxt(WK_DIR+'/model/'+CASENAME+'_TUTT_contour_lon_'+str(it+iyr1)+'-Ug_'+str(UG_N15_target)+'.txt',lonx) + np.savetxt(WK_DIR+'/model/'+CASENAME+'_TUTT_contour_lat_'+str(it+iyr1)+'-Ug_'+str(UG_N15_target)+'.txt',latx) +#try to print TUTT lon/lat? (Jay) + print('output TUTT position',it+iyr1,lonx.shape,latx.shape) + + #reference longtitude, weighted avarage of the longtiude of HGTy contour + #ref_lat varies from year to year, different from ref_lat0 + ref_lon=lon + dlonx=np.abs(np.gradient(lonx)) + #calculate ref_lat as an weighted average; ref_lat is then shift by one degree + ref_lat=np.ones(lon.size)*np.sum(latx*dlonx)/np.sum(dlonx) - lat_shift + #save the reference latitude + f0.write(str(iyr1+it-1)+' '+str(ref_lat[0])+' '+str(ref_lat0[0])+'\n') + + #coordinates of the circumglobal HGTy contour + line_hgty_coord=np.zeros((lonx.size,2)) + if contour_yn: + line_hgty_coord[:,0]=lonx + line_hgty_coord[:,1]=latx + line_hgty=LineString(line_hgty_coord) + + #coordinates of reference lat circle + line_latref_coord=np.zeros((ref_lon.size,2)) + if contour_yn: + #line_latref_coord[:,0]=ref_lon #Gan's original for year-to-year varying ref_lat + #line_latref_coord[:,1]=ref_lat #Gan's original + line_latref_coord[:,0]=ref_lon0 #ZW added + line_latref_coord[:,1]=ref_lat0 #ZW added + line_latref=LineString(line_latref_coord) + + itutt=0 + #check if there is enclosed TUTT region + if line_hgty.intersects(line_latref) and contour_yn: + print("Found Intersection point(s)") + intersect_point = line_hgty.intersection(line_latref) + + #index of intersection points + icount=0 + ind=np.zeros(len(list(intersect_point)),dtype=np.int) + for intsec in intersect_point: + #intsec.x,intsec.y save the lon/lat of the intersection points + # find the point closest to the intersection points on the HGTy contour + dist=np.square(lonx-intsec.x)+np.square(latx-intsec.y) + ind[icount]=np.asarray(np.where(dist == min( dist))[0][0]) + #highlight the intersection point + #m1.scatter((lonx[ind[icount]]),latx[ind[icount]],50,marker='o',color='g', zorder=9) + icount=icount+1 + #order the indices and remove redundant; lonx[ind] is the longitude of intersections + ind=np.sort(np.unique(ind)) + + #ZW added: If there are only two intersections, there are three possible scenarios: + #1)TUTT(Pac)>0 and TUTT(Atl)=0 if both intersection points fall over the Pac + #2)TUTT(Pac)=0 and TUTT(Atl)>0 if both intersection points fall over the Atl + #3)TUTT(Pac)>0 and TUTT(Atl)>0 if one falls over the Pac and the other over the Atl + #lonx_PacE and lonx_AtlW are used to determine the basin boundaries. + #If lonxW falls west of lonx_PacE, we regard it as related to the Pac TUTT + #If lonxE falls east of lonx_AtlW, we regard it as related to the Atl TUTT + #In the 3rd scenario, the northmost "local maximum latitude" point btw the two + #intersection points is used to separate TUTT(Pac) and TUTT(Atl). A local max function + #needs to be used as the true intersection points have the maximum lat (equal to ref_lat) + #This point is added as an interaction point btw the existing two to divide the basins. + if len(ind)==2: + lonxW=lonx[ind[0]] + lonxE=lonx[ind[1]] + print('lonxW='+str(lonxW)+' lonxE='+str(lonxE)) + if lonxWlonx_AtlW): #lonxW falls over Pac and lonxE over Atl + print('lonxW falls over Pac and lonxE over Atl') + ind0=ind + ind=np.zeros(len(ind0)+1,dtype=np.int) + ind[0]=ind0[0] + ind[2]=ind0[1] + + if ridge_option==1: +##Jay: get HGT values between 20-30N to search ridge maximum + f=interp2d(lon,lat,hgt_in[it,:,:],kind='cubic',copy=False,bounds_error=True) + for ii in range(len(ref_lat_out)): + hgt_along_ref_lat[ii]=(f(lonx[ii],20)+f(lonx[ii],21)+f(lonx[ii],22)+f(lonx[ii],23)+f(lonx[ii],24)+f(lonx[ii],25)+f(lonx[ii],26)+f(lonx[ii],27)+f(lonx[ii],28)+f(lonx[ii],29)+f(lonx[ii],30))/11 + + max_hgt=0 + for ii in range(len(ref_lat_out)): + if hgt_along_ref_lat[ii]>max_hgt and lonx[ii]>=240 and lonx[ii]<=280: + max_hgt=hgt_along_ref_lat[ii] +# hgt_along_ref_lat_temp=hgt_along_ref_lat[ind0[0]+1:ind0[1]] +# hgt_lmax=argrelextrema(hgt_along_ref_lat_temp,np.greater) + #add the HGT maximum point along the reference lat as a dividing point + ind[1]=np.where(hgt_along_ref_lat==max_hgt)[0] + print('The dividing longitude based on HGT maximum between 20-30 N: '+str(lonx[ind[1]])) + if ridge_option==2: + temp=np.array(abs(lonx-user_dividing_longitude)) + min_diff=np.amin(temp,axis=0) + ind[1]=np.where(temp==min_diff)[0] + print('The dividing longitude set by user: '+str(lonx[ind[1]])) + +#output dividing longitude + lat_0_30N=np.zeros((13)) + dividing_longitude=np.zeros((13)) + for ii in range(13): + lat_0_30N[ii]=0+ii*2.5 + dividing_longitude[ii]=lonx[ind[1]] + if output_opt2==1: + np.savetxt(WK_DIR+'/model/'+CASENAME+'_lat_0_30N.txt',lat_0_30N) + np.savetxt(WK_DIR+'/model/'+CASENAME+'_dividing_longitude_'+str(it+iyr1)+'.txt',dividing_longitude) + + elif lonxEmax_hgt and lonx[ii]>=240 and lonx[ii]<=280: + max_hgt=hgt_along_ref_lat[ii] + ind[2]=np.where(hgt_along_ref_lat==max_hgt)[0] + print('The dividing longitude based on HGT maximum between 20-30 N: '+str(lonx[ind[2]])) + if ridge_option==2: + temp=np.array(abs(lonx-user_dividing_longitude)) + min_diff=np.amin(temp,axis=0) + ind[2]=np.where(temp==min_diff)[0] + print('The dividing longitude set by user: '+str(lonx[ind[2]])) + + lat_0_30N=np.zeros((13)) + dividing_longitude=np.zeros((13)) + for ii in range(13): + lat_0_30N[ii]=0+ii*2.5 + dividing_longitude[ii]=lonx[ind[2]] + if output_opt2==1: + np.savetxt(WK_DIR+'/model/'+CASENAME+'_lat_0_30N.txt',lat_0_30N) + np.savetxt(WK_DIR+'/model/'+CASENAME+'_dividing_longitude_'+str(it+iyr1)+'.txt',dividing_longitude) + + else: + print('TUTT over one of the basins is zero') + print(ind) + print(lonxW,lonxE,lonx_PacE,lonx_AtlW) + else: + print('2+ intersections mean more than one TUTT identified') + + #EOT by ZW + + #extend the longitude range for the calculation of TUTT indices + #the Atlantic TUTT can extend eastward and beyond Prime Meridian + #ZW: lonx_circum=np.append(lonx, lonx[1:180]+360) + #ZW: latx_circum=np.append(latx, latx[1:180]) + lonx_circum=np.append(lonx, lonx+360) #ZW + latx_circum=np.append(latx, latx) #ZW + ind_circum=np.append(ind, ind[0]+lonx.size) + lon_circum=np.append(lon,lon+360) + + #ZW: prepare arrays to calculate tutt_int, tutt_lon and tutt_lat + lat_south=np.min(latx_circum) #southmost latitude of lat_circum + ref_south=np.argmin(abs(lat-lat_south)) + UG[it_ind,:ref_south,:]=np.NaN #set UG south of ref_south to NaN + UG_tmp=UG[it_ind] + Ones_tmp=UG_tmp-UG_tmp+1.0 + UG_circum=np.concatenate((UG_tmp,UG_tmp),axis=1) + UGx_circum=np.concatenate((UG_tmp*lons[:,:-1],UG_tmp*(lons[:,:-1]+360)),axis=1) + UGy_circum=np.concatenate((UG_tmp*lats[:,:-1],UG_tmp*lats[:,:-1]),axis=1) + AREAx_circum=np.concatenate((Ones_tmp*lons[:,:-1],Ones_tmp*(lons[:,:-1]+360)),axis=1) + AREAy_circum=np.concatenate((Ones_tmp*lats[:,:-1],Ones_tmp*lats[:,:-1]),axis=1) + + for i in range(len(ind)): + # approximation of arcs, including both TUTT and the ridges + poly_coord1=np.zeros((ind_circum[i+1]-ind_circum[i]+1,2)) + poly_coord1[:,0]=lonx_circum[ ind_circum[i]:ind_circum[i+1]+1 ] + poly_coord1[:,1]=latx_circum[ ind_circum[i]:ind_circum[i+1]+1 ] + #longtitude and latitude range of the arcs + dy_test=np.amax(poly_coord1[:,1]) - np.amin(poly_coord1[:,1]) + dx_test=np.amax(poly_coord1[:,0]) - np.amin(poly_coord1[:,0]) + #print(i, ind_circum[i], ind_circum[i+1]+1) + #must be south of the reference latitude, north of 5S, and covers a large area + #ZW: if all(poly_coord1[1:-2,1]<=ref_lat[0]) and all(poly_coord1[1:-2,1]>=-5) \ + if all(poly_coord1[1:-2,1]<=ref_lat0[0]) and all(poly_coord1[1:-2,1]>=-5) \ + and dx_test*dy_test>=min_TUTT: + #construct a polygon with poly_coord1 as vertices. The ref lat. is the north edge +#Jay: set the latitude in poly_coord1 higher than reference latitude equals to reference latitude + for ii in range(len(poly_coord1[:,0])): + if poly_coord1[ii,1] > ref_lat0[0]: + poly_coord1[ii,1]=ref_lat0[0] + +#Jay: scenario 1, the starting latitude and ending latitude of poly_coord1 both lower than reference latitude + if poly_coord1[0,1] < ref_lat0[0] and poly_coord1[len(poly_coord1[:,0])-1,1] < ref_lat0[0]: + poly_coord1_new=np.zeros((len(poly_coord1[:,0])+2,2)) + poly_coord1_new[0,0]=poly_coord1[0,0] + poly_coord1_new[0,1]=ref_lat0[0] + poly_coord1_new[len(poly_coord1[:,0])+1,0]=poly_coord1[len(poly_coord1[:,0])-1,0] + poly_coord1_new[len(poly_coord1[:,0])+1,1]=ref_lat0[0] + poly_coord1_new[1:len(poly_coord1[:,0])+1,:]=poly_coord1[:,:] + +#Jay: scenario 2, the starting latitude is lower than reference latitude + elif poly_coord1[0,1] < ref_lat0[0]: + poly_coord1_new=np.zeros((len(poly_coord1[:,0])+1,2)) + poly_coord1_new[0,0]=poly_coord1[0,0] + poly_coord1_new[0,1]=ref_lat0[0] + poly_coord1_new[1:len(poly_coord1[:,0])+1,:]=poly_coord1[:,:] + +#Jay: scenario 3, the ending latitude is lower than reference latitude + elif poly_coord1[len(poly_coord1[:,0])-1,1] < ref_lat0[0]: + poly_coord1_new=np.zeros((len(poly_coord1[:,0])+1,2)) + poly_coord1_new[len(poly_coord1[:,0]),0]=poly_coord1[len(poly_coord1[:,0])-1,0] + poly_coord1_new[len(poly_coord1[:,0]),1]=ref_lat0[0] + poly_coord1_new[0:len(poly_coord1[:,0]),:]=poly_coord1[:,:] + else: + poly_coord1_new=np.array((poly_coord1)) + + + mm=Polygon(poly_coord1_new) + + # Area approximation by scaling with cos, Python don't have good functions to + # calculate the area of spherical polygons + tutt_area=mm.area*np.cos(np.pi*np.mean(poly_coord1[:,1])/180. ) + print(tutt_area) + #store TUTT index. Ideally there should be two TUTTs, Pac(0) and Atl(1) + tutt_index[ int(yr_hgt[Dx[it_ind]])-iyr1, itutt ] = tutt_area + + #ZW:calculate the other TUTT indices + i1=np.argmin(abs(lon_circum-lonx_circum[ind_circum[i]])) + i2=np.argmin(abs(lon_circum-lonx_circum[ind_circum[i+1]]))+1 + Ugmean=np.nanmean(UG_circum[:,i1:i2]) + tutt_lon_wt[it_ind,itutt]=np.nanmean(UGx_circum[:,i1:i2])/Ugmean + tutt_lat_wt[it_ind,itutt]=np.nanmean(UGy_circum[:,i1:i2])/Ugmean + tutt_lon[it_ind,itutt]=np.nanmean(AREAx_circum[:,i1:i2]) + tutt_lat[it_ind,itutt]=np.nanmean(AREAy_circum[:,i1:i2]) + + # print to check + itutt=itutt+1 + +##ZW# print tutt index +for iy in range(iyr1,iyr2+1): + print(iy,tutt_index[iy-iyr1,:]) + +#calculate the corr. between Atl and Pac +rr=np.corrcoef(tutt_index.T)[0,1] +print('Corr = '+str(rr)) + +if plot_yn: + axes.plot(ref_lon0, ref_lat0, linewidth=2, linestyle="--",color='w',transform=ccrs.PlateCarree()) + + axes.coastlines() + lon_grid = np.arange(lon[ilon][0],lon[ilon][-1],40) +# lat_grid = np.arange(lat[ilat][0],lat[ilat][-1],20) + lat_grid = np.arange(-5,55,15) + # set x labels + axes.set_xticks(lon_grid, crs=ccrs.PlateCarree()) + axes.set_xticklabels(lon_grid, rotation=0, fontsize=14) + lon_formatter = cticker.LongitudeFormatter() + axes.xaxis.set_major_formatter(lon_formatter) + # set y labels + axes.set_yticks(lat_grid, crs=ccrs.PlateCarree()) + axes.set_yticklabels(lat_grid, rotation=0, fontsize=14) + lat_formatter = cticker.LatitudeFormatter() + axes.yaxis.set_major_formatter(lat_formatter) + # colorbar + fig.colorbar(im0, ax=axes, orientation="horizontal", pad=0.15,shrink=.9,aspect=45) + axes.set_title('TUTT contour',loc='center',fontsize=16) + fig.tight_layout() +# fig.savefig("TUTT_contour_GFDL.png", format='png',bbox_inches='tight') + fig.savefig(WK_DIR+"/model/"+CASENAME+"_TUTT_contour_model.png", format='png',bbox_inches='tight') + + +if output_opt==1: + fileout=WK_DIR+'/model/'+CASENAME+'_tutt_area-'+str(iyr1)+'-'+str(iyr2)+smon+'-Ug_'+str(UG_N15_target)+'.txt' + f1=open(fileout,'w+') + f1.write('Year Pac Atl'+'\n') + for iy in range(iyr1,iyr2+1): + f1.write(str(iy)+' '+str(tutt_index[iy-iyr1,0])+' '+str(tutt_index[iy-iyr1,1])+'\n') + f1.close() + + fileout=WK_DIR+'/model/'+CASENAME+'_tutt_intensity-'+str(iyr1)+'-'+str(iyr2)+smon+'-Ug_'+str(UG_N15_target)+'.txt' + f1=open(fileout,'w+') + f1.write('Year Pac Atl'+'\n') + for iy in range(iyr1,iyr2+1): + f1.write(str(iy)+' '+str(tutt_int[iy-iyr1,0])+' '+str(tutt_int[iy-iyr1,1])+'\n') + f1.close() + + fileout=WK_DIR+'/model/'+CASENAME+'_tutt_UG.wt_lon-'+str(iyr1)+'-'+str(iyr2)+smon+'-Ug_'+str(UG_N15_target)+'.txt' + f1=open(fileout,'w+') + f1.write('Year Pac Atl'+'\n') + for iy in range(iyr1,iyr2+1): + f1.write(str(iy)+' '+str(tutt_lon_wt[iy-iyr1,0])+' '+str(tutt_lon_wt[iy-iyr1,1])+'\n') + f1.close() + + fileout=WK_DIR+'/model/'+CASENAME+'_tutt_UG.wt_lat-'+str(iyr1)+'-'+str(iyr2)+smon+'-Ug_'+str(UG_N15_target)+'.txt' + f1=open(fileout,'w+') + f1.write('Year Pac Atl'+'\n') + for iy in range(iyr1,iyr2+1): + f1.write(str(iy)+' '+str(tutt_lat_wt[iy-iyr1,0])+' '+str(tutt_lat_wt[iy-iyr1,1])+'\n') + f1.close() + + fileout=WK_DIR+'/model/'+CASENAME+'_tutt_Area_lon-'+str(iyr1)+'-'+str(iyr2)+smon+'-Ug_'+str(UG_N15_target)+'.txt' + f1=open(fileout,'w+') + f1.write('Year Pac Atl'+'\n') + for iy in range(iyr1,iyr2+1): + f1.write(str(iy)+' '+str(tutt_lon[iy-iyr1,0])+' '+str(tutt_lon[iy-iyr1,1])+'\n') + f1.close() + + fileout=WK_DIR+'/model/'+CASENAME+'_tutt_Area_lat-'+str(iyr1)+'-'+str(iyr2)+smon+'-Ug_'+str(UG_N15_target)+'.txt' + f1=open(fileout,'w+') + f1.write('Year Pac Atl'+'\n') + for iy in range(iyr1,iyr2+1): + f1.write(str(iy)+' '+str(tutt_lat[iy-iyr1,0])+' '+str(tutt_lat[iy-iyr1,1])+'\n') + f1.close() + + print('Normal End!') diff --git a/diagnostics/TUTT/TUTT_clac_obs.py b/diagnostics/TUTT/TUTT_clac_obs.py new file mode 100644 index 000000000..4d5005b13 --- /dev/null +++ b/diagnostics/TUTT/TUTT_clac_obs.py @@ -0,0 +1,647 @@ +#29 Jun 2021 +import matplotlib.pyplot as pyplot +#from mpl_toolkits.basemap import Basemap +#from mpl_toolkits.basemap import addcyclic +import numpy as np +from normalize import normalize +# http://netcdf4-python.googlecode.com/svn/trunk/docs/netCDF4-module.html +from netCDF4 import Dataset, num2date +# http://scikit-image.org/ +from skimage import measure +# conda install -c scitools shapely +from shapely.geometry import Polygon, LineString +from scipy.signal import argrelextrema +from scipy.stats.stats import pearsonr +from scipy.interpolate import interp2d +from scipy.interpolate import RectBivariateSpline +import cartopy.crs as ccrs +import cartopy.mpl.ticker as cticker +import os + +lat_coord = os.environ["lat_coord"] +lon_coord = os.environ["lon_coord"] +Z200_var = os.environ["Z200_var"] +OBS_DATA = os.environ["OBS_DATA"] + +def add_cyclic_BL(dat,lon): + if dat.shape[2]!=lon.shape[0]: + print('Dimension error in the input data!') + return + dat1=np.zeros((dat.shape[0],dat.shape[1],dat.shape[2]+1)) + lon1=np.zeros(lon.shape[0]+1) + dat1[:,:,:-1]=dat + dat1[:,:,-1]=dat[:,:,0] + lon1[:-1]=lon + lon1[-1]=lon[0] + return(dat1,lon1) + +######################################### +# Input Data +######################################### +#parameters +#g=9.81 +#CMIP6 models unit is m +#does not need to separate by 9.81 +g=9.81 +#dlat=2.5 +ra=6371000. +omega=7.2921/100000. + +#input file specified +filein=OBS_DATA+'/hgt_monthly_Reanalysis.nc'; vname='hgt' +print("Input File: "+filein) + +##Sometimes Pacific and Atlantic TUTTs are connected together +##choose the separating longitude option here (Jay) +##ridge_option=1, the script will search the longitude where the geopotential height is the largest between 120W-80W +##the geopotential height is averaged between the subtropics (20-30N) +##Sometimes the ridge may be weak over Central America (due to model biases), so the user can set perferred separating longitude (ridge_option=2) +print("The script will search TUTT boundary based on zonal geostrophic wind (Ug) contour") +UG_N15_target = float(input("Enter a Ug value (suggested between 1.0-2.0): ")) + +print("Sometimes Pacific and Atlantic TUTTs are connected together") +print("Please choose the separating longitude option here") +print("ridge_option=1, the script will search the subtropical ridge over Central America (120W-80W)") +print("ridge_option=2, the dividing longitude is specified by the user") +ridge_option = int(input("Enter a number for ridge_option: ")) +if ridge_option==2: + user_dividing_longitude = int(input("Enter a number between 240-280 (120 W-80 W): ")) + +#Ug (15N) value that determines the HGTy & TUTT contour +lat_target=15 + +#Minimum TUTT areas, measure by the product of the latitude range and the longitude range +#It is a necessary threshold to remove some small wiggles in certain years +min_TUTT=100 + +#Latitude range to search for HGTy contours +latN=90 +latS=-10 + +#The longitude ranges for the two basins. +#lonx_AtlW should be the largest possible eastern boundary of the TUTT(Pac). If a point falls east of +#this longitude, we regard it as related to the Atl TUTT +#lonx_PacE should be the largest possible western boundary of the TUTT(Atl). If a point falls west of +#this longitude, we regard it as related to the Pac TUTT +lonx_PacE=270 +lonx_AtlW=240 + +#ref_lat is shifted southward by lat_shift to avoid the connection of TUTT(Pac) with TUTT(Atl) +#south of the ref. latitude. This, however, may render zero TUTT in some years, especially over Atl +lat_shift=-0.0 + +#time range +#ZW: Something went wrong when I adjusted iyr2 +iyr1 = int(input("Enter start year of data: ")) +iyr2 = int(input("Enter end year of data: ")) +imn1 = int(input("Enter start month you want: ")) +imn2 = int(input("Enter end month you want: ")) +nyr = iyr2-iyr1+1 +nmon = imn2-imn1+1 + +#Jay:choose whether the .txt files will be outputted +output_opt = int(input("Do you want to output general TUTT information as .txt? (area,strength,central location; 1=yes, 2=no): ")) +output_opt2=int(input("Do you want to output detail TUTT information as .txt? (locations of TUTT contour; 1=yes, 2=no): ")) + +#month string info +chmon=['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'] +chmns='JFMAMJJASOND' + +if imn1==imn2: + smon=chmon[imn1-1] +else: + smon=chmns[imn1-1:imn2] + +#plot monthly data in an individual year? +#if Ture, find "# use this when plotting monthly data in individual years" and make changes +#plotting seasonal mean data is possible, but needs some tuning to avoid error messages +plot_yn=True + +#output file for ref. lat +if output_opt==1: + filetxt=WK_DIR+'/obs/tutt_ref.latitude-'+str(iyr1)+'-'+str(iyr2)+smon+'-Ug_'+str(UG_N15_target)+'.txt' + f0=open(filetxt,'w+') + f0.write('Year Ref.Lat Ref.Lat0'+'\n') + +#create an arrary to store TUTT information +#ZW: There may be 3 TUTT regions when analyzing monthly mean data +tutt_index=np.zeros( (nyr, 2) ) #extent +tutt_lon_wt=np.zeros( (nyr, 2) )#area centroid weighted by Ug +tutt_lat_wt=np.zeros( (nyr, 2) ) +tutt_lon=np.zeros( (nyr, 2) ) #area centroid +tutt_lat=np.zeros( (nyr, 2) ) +tutt_int=np.zeros( (nyr, 2) ) #intensity + +#linux-like routine +ncFid = Dataset (filein, mode = "r") + +#read variables in the file; select the vertical level + +lon0 = ncFid.variables[ "lon" ][:] +lat0 = ncFid.variables[ "lat" ][:] + +#calculate latlon intervals, assuming regular grid spacing +dlon=lon0[1]-lon0[0] +dlat=lat0[1]-lat0[0] + +#confine the analysis to the northern hemisphere TUTT between 10S to 90N +#ZW: np.argmin is used to find the index of the closest value +ilat1=np.argmin(abs(lat0-latS)) +ilat2=np.argmin(abs(lat0-latN)) + +#switch ilat1 and ilat2 if the data starting from the NP; isign is set to -1 +#to take into account of the geostrophic wind calculation for reversed latitude +isign=1 +if dlat<0: + ii=ilat1 + ilat1=ilat2 + ilat2=ii + isign=-1 + +lat=lat0[ilat1:ilat2] +hgt_all = np.squeeze( ncFid.variables[ vname ][:,ilat1:ilat2,:] ) + +#data from S to N, does not need to be reversed (Jay) +if isign==1: + lat=np.array(lat[:]) + hgt_all=np.array(hgt_all[:,:,:]) + dlat=dlat +#data from N to S, need to be reversed (Jay) +if isign==-1: + lat=np.array(lat[::-1]) + hgt_all=np.array(hgt_all[:,::-1,:]) + dlat=-dlat + +#get date information +time = ncFid.variables[ "time" ][:] +time_units = ncFid.variables[ "time" ].units +datevar=num2date(time,time_units) + +#store date information +tsteps=len(time) +yr_hgt=np.zeros(tsteps) +mon_hgt=np.zeros(tsteps) +for i in range(tsteps): + yr_hgt[i]=datevar[i].year + mon_hgt[i]=datevar[i].month + +#indices of interested time range +D1=np.where((mon_hgt >= imn1) & (mon_hgt <= imn2) & (yr_hgt >= iyr1) & (yr_hgt <= iyr2))[0] +#print(D1) +#D2 saves the indices for the first month in a year +if imn2==imn1: #just one calendar month per year + D2=D1 +else: + D2=D1[0:-1:nmon] + +#get seasonal mean values of HGT +hgt_in=np.zeros([nyr,ilat2-ilat1,lon0.size]) +if imn2==imn1: #just one calendar month per year + hgt_in=hgt_all[D1,:,:]/1 +else: + for i in range(nyr): #seasonal mean + hgt_in[i,:,:]=np.mean(hgt_all[D1,:,:][i*nmon:i*nmon+nmon,:,:], axis=0)/1 + +#meridional gradient of HGT +hgt_y=np.gradient(hgt_in, axis=1)/(dlat/180*np.pi*ra) + +#geostrophic wind +UG=-hgt_y*g/((2.*omega*np.sin(np.pi*lat_target/180.))) +#get gradient value that correspond to UG_N15_target value +#For a reserved latitude mesh, dlat<0 and this is taken into account in hgt_y +hgty_target=-UG_N15_target/g*(2.*omega*np.sin(np.pi*lat_target/180.)) + +#add cyclic points for longtitude dim +hgt_in, lon = add_cyclic_BL(hgt_in, lon0 ) +hgt_y, lon = add_cyclic_BL(hgt_y, lon0 ) +#Jay: make the final longitude index to be 360, instead of 0 +lon[len(lon0)]=360.0 + +#plot_yn=True +#ZW# UG, lon = addcyclic(UG, lon0 ) +lons, lats = np.meshgrid(lon, lat) + +#set up the plotting window +if plot_yn: + fig, axes = pyplot.subplots(figsize=(8,4)) + ilat=np.argsort(lat) + ilon=np.argsort(lon) + axes = pyplot.axes(projection=ccrs.PlateCarree(central_longitude=180)) + axes.set_extent([0, 355, -5, 55], crs=ccrs.PlateCarree()) + clevs=np.arange(11840,12610,40.) + im0 = axes.contourf(lon0,lat,np.mean(hgt_in[:,:,0:len(lon0)],axis=0) ,clevs,cmap = pyplot.get_cmap('RdBu_r'),extend='both',transform=ccrs.PlateCarree()) +# print(lat,np.sum(np.isnan(hgt_in))) +# im1 = axes.contour(lon, lat, np.mean(hgt_in,axis=0) , 20,linewidths=0.5,cmap = pyplot.get_cmap('RdBu_r'),extend='both',transform=ccrs.PlateCarree()) + + +#ZW: define the ref_lat0 based on the long-term mean +contour_yn=False +hgt_ym=np.mean(hgt_y,axis=0) #long-term mean +contours= measure.find_contours(hgt_ym, hgty_target) +if len(contours) != 0: + #identify the longest contour, candidate for circumglobal contour + #length is measured by number of grid points along a contour + contour=max(contours, key=len) + #only keep the longest contour, which may be circum-global + #ZW: contour[:,1] saves longitude indices in the reversed order + #check if the contour is circum-global + if len(contour) >= lon.size and contour[-1,1]+contour[0,1] == lon.size-1: + #convert coordinates to latlon + lonx0=lon[0]+dlon*contour[:, 1] + latx0=lat[0]+dlat*contour[:, 0] + #reverse the order so that lonx goes from W to E + if lonx0[1]>lonx0[2]: + lonx=lonx0[::-1] + latx=latx0[::-1] + else: + lonx=lonx0 + latx=latx0 + + print("Found contours in the long-term mean") + contour_yn=True + + #reference latitude, weighted avarage of the latitude of HGTy contour + #An alternate is to define ref_lat based on the latitude of the zonal mean Ug + #The difference in TUTT between the two ref_lat is a constant number and does + #not affect the corr/composite analysis + #ref_lon0 is the same as ref_lon, but a different array is created for clarity + ref_lon0=lon + dlonx=np.abs(np.gradient(lonx)) + #calculate ref_lat as an weighted average; ref_lat is then shift by "lat_shift" degree + ref_lat0=np.ones(lon.size)*np.sum(latx*dlonx)/np.sum(dlonx) - lat_shift + +#ref_lat0[:]=20.160798378056562 + +#set UG=np.nan north of ref_lat0 +ref_j0=np.argmin(abs(lat-ref_lat0[0])) +ref_0N=np.argmin(abs(lat-0)) +UG[:,ref_j0+1:,:]=np.NaN #only consider data between 0N and ref_lat +UG[:,:ref_0N,:]=np.NaN +UG[np.where(UG= lon.size and contour[-1,1]+contour[0,1] == lon.size-1: + #convert coordinates to lat-lon; find_contours provides desending lon values + #ZW: lonx0=dlat*contour[:, 1] + #ZW: latx0=latN-dlat*contour[:, 0] + lonx0=lon[0]+dlon*contour[:, 1] + latx0=lat[0]+dlat*contour[:, 0] + + #reverse the order so that lonx goes from W to E + if lonx0[1]>lonx0[2]: + lonx=lonx0[::-1] + latx=latx0[::-1] + else: + lonx=lonx0 + latx=latx0 + + print("Found contours") + contour_yn=True + + # Plot the contour on the basemap + + if plot_yn: + axes.plot(lonx, latx, linewidth=1, color='gray',transform=ccrs.PlateCarree()) + +#output TUTT contour position + length=np.zeros((1)) + length[0]=len(lonx) + ref_lat_out=np.zeros((len(lonx))) + hgt_along_ref_lat=np.zeros((len(lonx))) + for ii in range(len(lonx)): +# print(ref_lat0) + ref_lat_out[ii]=ref_lat0[0] + if output_opt2==1: + np.savetxt(WK_DIR+'/obs/TUTT_ref_lat_'+str(it+iyr1)+'-Ug_'+str(UG_N15_target)+'.txt',ref_lat_out) + np.savetxt(WK_DIR+'/obs/TUTT_contour_length_'+str(it+iyr1)+'-Ug_'+str(UG_N15_target)+'.txt',length) + np.savetxt(WK_DIR+'/obs/TUTT_contour_lon_'+str(it+iyr1)+'-Ug_'+str(UG_N15_target)+'.txt',lonx) + np.savetxt(WK_DIR+'/obs/TUTT_contour_lat_'+str(it+iyr1)+'-Ug_'+str(UG_N15_target)+'.txt',latx) +#try to print TUTT lon/lat? (Jay) + print('output TUTT position',it+iyr1,lonx.shape,latx.shape) + + #reference longtitude, weighted avarage of the longtiude of HGTy contour + #ref_lat varies from year to year, different from ref_lat0 + ref_lon=lon + dlonx=np.abs(np.gradient(lonx)) + #calculate ref_lat as an weighted average; ref_lat is then shift by one degree + ref_lat=np.ones(lon.size)*np.sum(latx*dlonx)/np.sum(dlonx) - lat_shift + #save the reference latitude + f0.write(str(iyr1+it-1)+' '+str(ref_lat[0])+' '+str(ref_lat0[0])+'\n') + + #coordinates of the circumglobal HGTy contour + line_hgty_coord=np.zeros((lonx.size,2)) + if contour_yn: + line_hgty_coord[:,0]=lonx + line_hgty_coord[:,1]=latx + line_hgty=LineString(line_hgty_coord) + + #coordinates of reference lat circle + line_latref_coord=np.zeros((ref_lon.size,2)) + if contour_yn: + #line_latref_coord[:,0]=ref_lon #Gan's original for year-to-year varying ref_lat + #line_latref_coord[:,1]=ref_lat #Gan's original + line_latref_coord[:,0]=ref_lon0 #ZW added + line_latref_coord[:,1]=ref_lat0 #ZW added + line_latref=LineString(line_latref_coord) + + itutt=0 + #check if there is enclosed TUTT region + if line_hgty.intersects(line_latref) and contour_yn: + print("Found Intersection point(s)") + intersect_point = line_hgty.intersection(line_latref) + + #index of intersection points + icount=0 + ind=np.zeros(len(list(intersect_point)),dtype=np.int) + for intsec in intersect_point: + #intsec.x,intsec.y save the lon/lat of the intersection points + # find the point closest to the intersection points on the HGTy contour + dist=np.square(lonx-intsec.x)+np.square(latx-intsec.y) + ind[icount]=np.asarray(np.where(dist == min( dist))[0][0]) + #highlight the intersection point + #m1.scatter((lonx[ind[icount]]),latx[ind[icount]],50,marker='o',color='g', zorder=9) + icount=icount+1 + #order the indices and remove redundant; lonx[ind] is the longitude of intersections + ind=np.sort(np.unique(ind)) + + #ZW added: If there are only two intersections, there are three possible scenarios: + #1)TUTT(Pac)>0 and TUTT(Atl)=0 if both intersection points fall over the Pac + #2)TUTT(Pac)=0 and TUTT(Atl)>0 if both intersection points fall over the Atl + #3)TUTT(Pac)>0 and TUTT(Atl)>0 if one falls over the Pac and the other over the Atl + #lonx_PacE and lonx_AtlW are used to determine the basin boundaries. + #If lonxW falls west of lonx_PacE, we regard it as related to the Pac TUTT + #If lonxE falls east of lonx_AtlW, we regard it as related to the Atl TUTT + #In the 3rd scenario, the northmost "local maximum latitude" point btw the two + #intersection points is used to separate TUTT(Pac) and TUTT(Atl). A local max function + #needs to be used as the true intersection points have the maximum lat (equal to ref_lat) + #This point is added as an interaction point btw the existing two to divide the basins. + if len(ind)==2: + lonxW=lonx[ind[0]] + lonxE=lonx[ind[1]] + print('lonxW='+str(lonxW)+' lonxE='+str(lonxE)) + if lonxWlonx_AtlW): #lonxW falls over Pac and lonxE over Atl + print('lonxW falls over Pac and lonxE over Atl') + ind0=ind + ind=np.zeros(len(ind0)+1,dtype=np.int) + ind[0]=ind0[0] + ind[2]=ind0[1] + + if ridge_option==1: +##Jay: get HGT values between 20-30N to search ridge maximum + f=interp2d(lon,lat,hgt_in[it,:,:],kind='cubic',copy=False,bounds_error=True) + for ii in range(len(ref_lat_out)): + hgt_along_ref_lat[ii]=(f(lonx[ii],20)+f(lonx[ii],21)+f(lonx[ii],22)+f(lonx[ii],23)+f(lonx[ii],24)+f(lonx[ii],25)+f(lonx[ii],26)+f(lonx[ii],27)+f(lonx[ii],28)+f(lonx[ii],29)+f(lonx[ii],30))/11 + + max_hgt=0 + for ii in range(len(ref_lat_out)): + if hgt_along_ref_lat[ii]>max_hgt and lonx[ii]>=240 and lonx[ii]<=280: + max_hgt=hgt_along_ref_lat[ii] +# hgt_along_ref_lat_temp=hgt_along_ref_lat[ind0[0]+1:ind0[1]] +# hgt_lmax=argrelextrema(hgt_along_ref_lat_temp,np.greater) + #add the HGT maximum point along the reference lat as a dividing point + ind[1]=np.where(hgt_along_ref_lat==max_hgt)[0] + print('The dividing longitude based on HGT maximum between 20-30 N: '+str(lonx[ind[1]])) + if ridge_option==2: + temp=np.array(abs(lonx-user_dividing_longitude)) + min_diff=np.amin(temp,axis=0) + ind[1]=np.where(temp==min_diff)[0] + print('The dividing longitude set by user: '+str(lonx[ind[1]])) + +#output dividing longitude + lat_0_30N=np.zeros((13)) + dividing_longitude=np.zeros((13)) + for ii in range(13): + lat_0_30N[ii]=0+ii*2.5 + dividing_longitude[ii]=lonx[ind[1]] + if output_opt2==1: + np.savetxt(WK_DIR+'/obs/lat_0_30N.txt',lat_0_30N) + np.savetxt(WK_DIR+'/obs/dividing_longitude_'+str(it+iyr1)+'.txt',dividing_longitude) + + elif lonxEmax_hgt and lonx[ii]>=240 and lonx[ii]<=280: + max_hgt=hgt_along_ref_lat[ii] + ind[2]=np.where(hgt_along_ref_lat==max_hgt)[0] + print('The dividing longitude based on HGT maximum between 20-30 N: '+str(lonx[ind[2]])) + if ridge_option==2: + temp=np.array(abs(lonx-user_dividing_longitude)) + min_diff=np.amin(temp,axis=0) + ind[2]=np.where(temp==min_diff)[0] + print('The dividing longitude set by user: '+str(lonx[ind[2]])) + + lat_0_30N=np.zeros((13)) + dividing_longitude=np.zeros((13)) + for ii in range(13): + lat_0_30N[ii]=0+ii*2.5 + dividing_longitude[ii]=lonx[ind[2]] + if output_opt2==1: + np.savetxt(WK_DIR+'/obs/lat_0_30N.txt',lat_0_30N) + np.savetxt(WK_DIR+'/obs/dividing_longitude_'+str(it+iyr1)+'.txt',dividing_longitude) + + else: + print('TUTT over one of the basins is zero') + print(ind) + print(lonxW,lonxE,lonx_PacE,lonx_AtlW) + else: + print('2+ intersections mean more than one TUTT identified') + + #EOT by ZW + + #extend the longitude range for the calculation of TUTT indices + #the Atlantic TUTT can extend eastward and beyond Prime Meridian + #ZW: lonx_circum=np.append(lonx, lonx[1:180]+360) + #ZW: latx_circum=np.append(latx, latx[1:180]) + lonx_circum=np.append(lonx, lonx+360) #ZW + latx_circum=np.append(latx, latx) #ZW + ind_circum=np.append(ind, ind[0]+lonx.size) + lon_circum=np.append(lon,lon+360) + + #ZW: prepare arrays to calculate tutt_int, tutt_lon and tutt_lat + lat_south=np.min(latx_circum) #southmost latitude of lat_circum + ref_south=np.argmin(abs(lat-lat_south)) + UG[it_ind,:ref_south,:]=np.NaN #set UG south of ref_south to NaN + UG_tmp=UG[it_ind] + Ones_tmp=UG_tmp-UG_tmp+1.0 + UG_circum=np.concatenate((UG_tmp,UG_tmp),axis=1) + UGx_circum=np.concatenate((UG_tmp*lons[:,:-1],UG_tmp*(lons[:,:-1]+360)),axis=1) + UGy_circum=np.concatenate((UG_tmp*lats[:,:-1],UG_tmp*lats[:,:-1]),axis=1) + AREAx_circum=np.concatenate((Ones_tmp*lons[:,:-1],Ones_tmp*(lons[:,:-1]+360)),axis=1) + AREAy_circum=np.concatenate((Ones_tmp*lats[:,:-1],Ones_tmp*lats[:,:-1]),axis=1) + + for i in range(len(ind)): + # approximation of arcs, including both TUTT and the ridges + poly_coord1=np.zeros((ind_circum[i+1]-ind_circum[i]+1,2)) + poly_coord1[:,0]=lonx_circum[ ind_circum[i]:ind_circum[i+1]+1 ] + poly_coord1[:,1]=latx_circum[ ind_circum[i]:ind_circum[i+1]+1 ] + #longtitude and latitude range of the arcs + dy_test=np.amax(poly_coord1[:,1]) - np.amin(poly_coord1[:,1]) + dx_test=np.amax(poly_coord1[:,0]) - np.amin(poly_coord1[:,0]) + #print(i, ind_circum[i], ind_circum[i+1]+1) + #must be south of the reference latitude, north of 5S, and covers a large area + #ZW: if all(poly_coord1[1:-2,1]<=ref_lat[0]) and all(poly_coord1[1:-2,1]>=-5) \ + if all(poly_coord1[1:-2,1]<=ref_lat0[0]) and all(poly_coord1[1:-2,1]>=-5) \ + and dx_test*dy_test>=min_TUTT: + #construct a polygon with poly_coord1 as vertices. The ref lat. is the north edge +#Jay: set the latitude in poly_coord1 higher than reference latitude equals to reference latitude + for ii in range(len(poly_coord1[:,0])): + if poly_coord1[ii,1] > ref_lat0[0]: + poly_coord1[ii,1]=ref_lat0[0] + +#Jay: scenario 1, the starting latitude and ending latitude of poly_coord1 both lower than reference latitude + if poly_coord1[0,1] < ref_lat0[0] and poly_coord1[len(poly_coord1[:,0])-1,1] < ref_lat0[0]: + poly_coord1_new=np.zeros((len(poly_coord1[:,0])+2,2)) + poly_coord1_new[0,0]=poly_coord1[0,0] + poly_coord1_new[0,1]=ref_lat0[0] + poly_coord1_new[len(poly_coord1[:,0])+1,0]=poly_coord1[len(poly_coord1[:,0])-1,0] + poly_coord1_new[len(poly_coord1[:,0])+1,1]=ref_lat0[0] + poly_coord1_new[1:len(poly_coord1[:,0])+1,:]=poly_coord1[:,:] + +#Jay: scenario 2, the starting latitude is lower than reference latitude + elif poly_coord1[0,1] < ref_lat0[0]: + poly_coord1_new=np.zeros((len(poly_coord1[:,0])+1,2)) + poly_coord1_new[0,0]=poly_coord1[0,0] + poly_coord1_new[0,1]=ref_lat0[0] + poly_coord1_new[1:len(poly_coord1[:,0])+1,:]=poly_coord1[:,:] + +#Jay: scenario 3, the ending latitude is lower than reference latitude + elif poly_coord1[len(poly_coord1[:,0])-1,1] < ref_lat0[0]: + poly_coord1_new=np.zeros((len(poly_coord1[:,0])+1,2)) + poly_coord1_new[len(poly_coord1[:,0]),0]=poly_coord1[len(poly_coord1[:,0])-1,0] + poly_coord1_new[len(poly_coord1[:,0]),1]=ref_lat0[0] + poly_coord1_new[0:len(poly_coord1[:,0]),:]=poly_coord1[:,:] + else: + poly_coord1_new=np.array((poly_coord1)) + + + mm=Polygon(poly_coord1_new) + + # Area approximation by scaling with cos, Python don't have good functions to + # calculate the area of spherical polygons + tutt_area=mm.area*np.cos(np.pi*np.mean(poly_coord1[:,1])/180. ) + print(tutt_area) + #store TUTT index. Ideally there should be two TUTTs, Pac(0) and Atl(1) + tutt_index[ int(yr_hgt[Dx[it_ind]])-iyr1, itutt ] = tutt_area + + #ZW:calculate the other TUTT indices + i1=np.argmin(abs(lon_circum-lonx_circum[ind_circum[i]])) + i2=np.argmin(abs(lon_circum-lonx_circum[ind_circum[i+1]]))+1 + Ugmean=np.nanmean(UG_circum[:,i1:i2]) + tutt_lon_wt[it_ind,itutt]=np.nanmean(UGx_circum[:,i1:i2])/Ugmean + tutt_lat_wt[it_ind,itutt]=np.nanmean(UGy_circum[:,i1:i2])/Ugmean + tutt_lon[it_ind,itutt]=np.nanmean(AREAx_circum[:,i1:i2]) + tutt_lat[it_ind,itutt]=np.nanmean(AREAy_circum[:,i1:i2]) + + # print to check + itutt=itutt+1 + +##ZW# print tutt index +for iy in range(iyr1,iyr2+1): + print(iy,tutt_index[iy-iyr1,:]) + +#calculate the corr. between Atl and Pac +rr=np.corrcoef(tutt_index.T)[0,1] +print('Corr = '+str(rr)) + +if plot_yn: + axes.plot(ref_lon0, ref_lat0, linewidth=2, linestyle="--",color='w',transform=ccrs.PlateCarree()) + + axes.coastlines() + lon_grid = np.arange(lon[ilon][0],lon[ilon][-1],40) +# lat_grid = np.arange(lat[ilat][0],lat[ilat][-1],20) + lat_grid = np.arange(-5,55,15) + # set x labels + axes.set_xticks(lon_grid, crs=ccrs.PlateCarree()) + axes.set_xticklabels(lon_grid, rotation=0, fontsize=14) + lon_formatter = cticker.LongitudeFormatter() + axes.xaxis.set_major_formatter(lon_formatter) + # set y labels + axes.set_yticks(lat_grid, crs=ccrs.PlateCarree()) + axes.set_yticklabels(lat_grid, rotation=0, fontsize=14) + lat_formatter = cticker.LatitudeFormatter() + axes.yaxis.set_major_formatter(lat_formatter) + # colorbar + fig.colorbar(im0, ax=axes, orientation="horizontal", pad=0.15,shrink=.9,aspect=45) + axes.set_title('TUTT contour',loc='center',fontsize=16) + fig.tight_layout() + fig.savefig(WK_DIR+"/obs/TUTT_contour_obs.png", format='png',bbox_inches='tight') + + +if output_opt==1: + fileout=WK_DIR+'/obs/tutt_area-'+str(iyr1)+'-'+str(iyr2)+smon+'-Ug_'+str(UG_N15_target)+'.txt' + f1=open(fileout,'w+') + f1.write('Year Pac Atl'+'\n') + for iy in range(iyr1,iyr2+1): + f1.write(str(iy)+' '+str(tutt_index[iy-iyr1,0])+' '+str(tutt_index[iy-iyr1,1])+'\n') + f1.close() + + fileout=WK_DIR+'/obs/tutt_intensity-'+str(iyr1)+'-'+str(iyr2)+smon+'-Ug_'+str(UG_N15_target)+'.txt' + f1=open(fileout,'w+') + f1.write('Year Pac Atl'+'\n') + for iy in range(iyr1,iyr2+1): + f1.write(str(iy)+' '+str(tutt_int[iy-iyr1,0])+' '+str(tutt_int[iy-iyr1,1])+'\n') + f1.close() + + fileout=WK_DIR+'/obs/tutt_UG.wt_lon-'+str(iyr1)+'-'+str(iyr2)+smon+'-Ug_'+str(UG_N15_target)+'.txt' + f1=open(fileout,'w+') + f1.write('Year Pac Atl'+'\n') + for iy in range(iyr1,iyr2+1): + f1.write(str(iy)+' '+str(tutt_lon_wt[iy-iyr1,0])+' '+str(tutt_lon_wt[iy-iyr1,1])+'\n') + f1.close() + + fileout=WK_DIR+'/obs/tutt_UG.wt_lat-'+str(iyr1)+'-'+str(iyr2)+smon+'-Ug_'+str(UG_N15_target)+'.txt' + f1=open(fileout,'w+') + f1.write('Year Pac Atl'+'\n') + for iy in range(iyr1,iyr2+1): + f1.write(str(iy)+' '+str(tutt_lat_wt[iy-iyr1,0])+' '+str(tutt_lat_wt[iy-iyr1,1])+'\n') + f1.close() + + fileout=WK_DIR+'/obs/tutt_Area_lon-'+str(iyr1)+'-'+str(iyr2)+smon+'-Ug_'+str(UG_N15_target)+'.txt' + f1=open(fileout,'w+') + f1.write('Year Pac Atl'+'\n') + for iy in range(iyr1,iyr2+1): + f1.write(str(iy)+' '+str(tutt_lon[iy-iyr1,0])+' '+str(tutt_lon[iy-iyr1,1])+'\n') + f1.close() + + fileout=WK_DIR+'/obs/tutt_Area_lat-'+str(iyr1)+'-'+str(iyr2)+smon+'-Ug_'+str(UG_N15_target)+'.txt' + f1=open(fileout,'w+') + f1.write('Year Pac Atl'+'\n') + for iy in range(iyr1,iyr2+1): + f1.write(str(iy)+' '+str(tutt_lat[iy-iyr1,0])+' '+str(tutt_lat[iy-iyr1,1])+'\n') + f1.close() + + print('Normal End!') diff --git a/diagnostics/TUTT/doc/TUTT.rst b/diagnostics/TUTT/doc/TUTT.rst new file mode 100644 index 000000000..44d9f47fe --- /dev/null +++ b/diagnostics/TUTT/doc/TUTT.rst @@ -0,0 +1,132 @@ +Tropical Upper Tropospheric Trough Diagnostic Documentation +================================ + +Last update: 7/2/2021 + +The summertime stationary waves consist of two upper-level monsoon anticyclones and two mid-ocean troughs in the subtropics (Fig. 1). The latter are also known as tropical upper-tropospheric troughs (TUTTs). The summertime stationary waves are modulated by various climate modes (e.g., the ENSO, AMO, PDO and PMM) and are associated with monsoon variability (Chang et al. 2021). In addition, TUTTs are the preferred regions for extratropical Rossby wave breaking. Wang et al. (2020) showed that summertime stationary waves integrate tropical and extratropical impacts on tropical cyclone activity. In particular, a TUTT index provides a useful metric to represent the collective impacts (Table 1) and can be used to assess climate model representation of subtropical stationary waves. + +As shown in Fig. 1, a TUTT is characterized by enhanced westerly flow in its south. A TUTT index is defined based on the geostrophic zonal flow as described below. This diagnostic package can be used to evaluate 200-hPa TUTT area in both climate models and reanalysis datasets. + + +Version & Contact info +---------------------- + +.. '-' starts items in a bulleted list: + https://docutils.sourceforge.io/docs/user/rst/quickref.html#bullet-lists + +- Version/revision information: version 1.0 (7/2/2021) +- PI: Zhuo Wang, zhuowang@illinois.edu, DAS UIUC) +- Developer/point of contact (Zhuo Wang, Gan Zhang, Chuan-Chieh Chang, and Jiacheng Ye/Zhuo Wang, zhuowang@illinois.edu, DAS UIUC) + +.. Underline with '^'s to make a third-level heading. + +Open source copyright agreement +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The MDTF framework is distributed under the LGPLv3 license (see LICENSE.txt). + +Functionality +------------- + +The package consists of the following functionalities: + +1. Calculates constant-f geostrophic zonal winds (Ug) using 200-hPa geopotential height for a fixed Coriolis parameter at 15N. + +2. Identifies the circumglobal contour of the long-term seasonal mean Ug = 1.0 m/s. The zonal-mean latitude of this circumglobal contour is chosen as the reference latitude. The value of Ug can be adjusted by the user, usually ranging from 0.5 to 2.0 m/s. A small positive number is used because the associated Ug contour is more robust than the zero contour. + +3. The TUTT index is defined as the area where the circumglobal contour of seasonal mean Ug extends southward of the reference latitude. Two TUTT areas are calculated, one for the North Pacific and one for the North Atlantic. + +4. In addition to TUTT area, the centroid locations of TUTTs (i.e., latitude and longitude) are also calculated. + +5. The reference latitude, area, and centroid location of two TUTTs are output as .txt files, and figure is plotted showing the year-to-year variability TUTTs (Fig. 2). + + +(**) cropping.py can be referenced if code is needed to either shift the grid of your data +or to crop your data to a specified region + +As a module of the MDTF code package, all scripts of this package can be found under +``mdtf/MDTF_$ver/diagnostics/TUTT + +Required programming language and libraries +------------------------------------------- + +Python3 packages: "netCDF4", "skimage", "numpy", "scipy", "shapely.geometry", "cartopy" + +Required model input variables +------------------------------- + +Monthly mean 200-hPa geopotential height field for multiple years (e.g., 1979.01-2018.12) in the netCDF format is the only required input variable. Horizontal resolution of the geopotential height field can be decided by the user, but it is recommended to use a resolution of 2.0 degrees or coarse to ensure the smoothness of the Ug contours. Note that the longitude index of the data goes from west to east (0-360E). + + +References +---------- + +.. _ref-Muñoz1: + +Wang, Z., Zhang, G., Dunkerton, T. J., & Jin, F. F. (2020). Summertime stationary waves integrate tropical and extratropical impacts on tropical cyclone activity. Proceedings of the National Academy of Sciences of the United States of America, 117(37), 22720-22726. https://doi.org/10.1073/pnas.2010547117 + +Chang, C.-C., Z. Wang and coauthrs, 2021: Summertime Subtropical Stationary Waves: Variability and Impacts on the Tropical Cyclone Activity. In preparation. + + + +More about this diagnostic +-------------------------- + +1. Weak westerly wind sometimes extends southward of the equator and connects to the westerlies over the Southern Hemisphere in reanalysis datasets. We therefore choose to use the zonal geostrophic wind with a fixed Coriolis parameter instead of the total zonal wind. +2. Pacific TUTT and Atlantic TUTT sometimes are connected to each other in some CMIP models. This happens during the years when the 200-hPa anticyclone over the Central America is weak, especially in the CMIP models that underestimate the North American monsoon strength. The longitude of 95W is used to divide the two TUTTs in this situation. + +.. figure:: fig1_update.png + :align: center + :width: 20% + + Figure 1. The 200-hPa wind vectors and streamlines during June-August in 1967 (Krishnamurti 1970). The colored lines highlight the monsoon anticyclones and TUTTs. + + +.. figure:: fig2.png + :align: center + :width: 25 % + +Figure 2. (a) Long-term mean 200-hPa geopotential height (shading; units: m), the reference latitude for TUTTs (white dashed line), and the contours of 𝑢g=1.0 𝑚 𝑠* for individual years from 1979-2018; (b) the time series of the normalized TUTT_Pac and TUTT_Atl indices. The correlation between TUTT_Atl and TUTT_Pac is shown at the upper right corner of panel (b) (From Wang et al. 2020). + +.. figure:: table1.png + :align: center + :width: 20 % + + Table 1. Correlation coefficients between different TUTT indices and the TC activity indices over three basins during JASO 1979–2018. The correlations between the Nino3.4 index and TC indices are also shown for comparison. TCF: tropical cyclone frequency; HURR: hurricane frequency; ACE: accumulated cyclone energy. Asterisk denotes correlations below the 95% confidence level. (From Wang et al. 2020). + + +Descriptions of outputted .txt files: + +TUTT_contour_lat_1958-Ug_2.0.txt/TUTT_contour_lon_1958-Ug_2.0.txt +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The coordinates (latitude and longitude) of TUTT contour given by 200 hPa zonal geostrophic wind (Ug) at value 2 m/s. + +TUTT_ref_lat_1958-Ug_2.0.txt/TUTT_contour_lon_1958-Ug_2.0.txt +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The coordinates (latitude and longitude) of reference latitude. + + +TUTT_contour_length_1958-Ug_2.0.txt +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Length (i.e., number of points) of TUTT contour. + +tutt_Area_lat-1958-1958JASO-Ug_2.0.txt/tutt_Area_lon-1958-1958JASO-Ug_2.0.txt +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The central locations (latitude and longitude) of Pacific and Atlantic TUTTs. When calculating averaged latitude/longitude, each grid point has the same weighting. + +tutt_UG.wt_lat-1958-1958JASO-Ug_2.0.txt/tutt_UG.wt_lon-1958-1958JASO-Ug_2.0.txt +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The central locations (latitude and longitude) of Pacific and Atlantic TUTTs. When calculating averaged latitude/longitude, each grid point is weighted by the value of Ug. + + +tutt_area-1958-1958JASO-Ug_2.0.txt +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The area of Pacific and Atlantic TUTTs. + +tutt_intensity-1958-1958JASO-Ug_2.0.txt +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The intensity/strength of Pacific and Atlantic TUTTs. + +tutt_ref.latitude-1958-1958JASO-Ug_2.0.txt +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The value of reference latitude. diff --git a/diagnostics/TUTT/doc/TUTT_contour_lat_1979-Ug_2.0.txt b/diagnostics/TUTT/doc/TUTT_contour_lat_1979-Ug_2.0.txt new file mode 100644 index 000000000..c9405a9a3 --- /dev/null +++ b/diagnostics/TUTT/doc/TUTT_contour_lat_1979-Ug_2.0.txt @@ -0,0 +1,181 @@ +1.986025906818202102e+01 +2.000000000000000000e+01 +2.009701783673772724e+01 +2.040416000615651981e+01 +2.054955811467154447e+01 +2.080230704805966724e+01 +2.108429511917613297e+01 +2.134403352905899709e+01 +2.154997208984958590e+01 +2.194465799153343966e+01 +2.223770278892072838e+01 +2.250000000000000000e+01 +2.260433513763692304e+01 +2.290043161870631394e+01 +2.322870186306197127e+01 +2.356656348636681031e+01 +2.374474606808932720e+01 +2.436949379839469287e+01 +2.446283057423888607e+01 +2.452159725070647767e+01 +2.461156603191544434e+01 +2.474283407137463797e+01 +2.474616236135624803e+01 +2.488499247951678939e+01 +2.500000000000000000e+01 +2.501129809621711786e+01 +2.500000000000000000e+01 +2.489592757949308321e+01 +2.500000000000000000e+01 +2.508242761712963897e+01 +2.517606842717046334e+01 +2.523930082015014875e+01 +2.519566730389420428e+01 +2.518826398603285099e+01 +2.524994471511596572e+01 +2.530120807141884853e+01 +2.538483131971030105e+01 +2.559314403087980594e+01 +2.585296001318504722e+01 +2.607328019041668199e+01 +2.634751866021399280e+01 +2.634559023651019061e+01 +2.610518625724944286e+01 +2.572097503030155963e+01 +2.578611902284783497e+01 +2.571324923387667383e+01 +2.548477104337790422e+01 +2.531692949325994846e+01 +2.531335360858789585e+01 +2.526052336624672279e+01 +2.521312649711472886e+01 +2.523743727061857811e+01 +2.534659588302495337e+01 +2.540448016622305261e+01 +2.545714043055988185e+01 +2.558503785069719072e+01 +2.574356222846560627e+01 +2.591279438358502318e+01 +2.608622595364185770e+01 +2.627116290547209587e+01 +2.647848083874131220e+01 +2.674573115706766657e+01 +2.705080719007162315e+01 +2.731938621981836945e+01 +2.750000000000000000e+01 +2.756565105197720555e+01 +2.774571143367249704e+01 +2.792401893998550122e+01 +2.811111014922200013e+01 +2.831148338817079235e+01 +2.851281537931672005e+01 +2.869944193902644258e+01 +2.886082236392628175e+01 +2.899109213858344702e+01 +2.906919322695818408e+01 +2.911727334276552881e+01 +2.912966379599937028e+01 +2.907177535320264639e+01 +2.889718263075366878e+01 +2.859262618194573236e+01 +2.813204953109655548e+01 +2.750612024461165106e+01 +2.750000000000000000e+01 +2.745750492890039851e+01 +2.500000000000000000e+01 +2.399886019060601683e+01 +2.250000000000000000e+01 +2.234536696966224412e+01 +2.104847102509509327e+01 +2.000000000000000000e+01 +1.990229363079320990e+01 +1.855387893073654837e+01 +1.750000000000000000e+01 +1.732252607029835545e+01 +1.523188566127551624e+01 +1.500000000000000000e+01 +1.431174567735363112e+01 +1.250000000000000000e+01 +1.208487789937227319e+01 +1.145573200806676439e+01 +1.100052604953834390e+01 +1.067217909753877336e+01 +1.051873306898688654e+01 +1.042327635854732648e+01 +1.037751161251652476e+01 +1.038236024734609231e+01 +1.041592195335698534e+01 +1.052458532457496077e+01 +1.066350940523076929e+01 +1.086101543060811991e+01 +1.106802793086506753e+01 +1.127167834044380257e+01 +1.147026918365929049e+01 +1.168184841957132036e+01 +1.194641892848535036e+01 +1.222243256394234834e+01 +1.247933939322625108e+01 +1.250000000000000000e+01 +1.268256052518900390e+01 +1.291755000187844260e+01 +1.317345268120014978e+01 +1.344348988277339529e+01 +1.371430794942480347e+01 +1.395685439824464780e+01 +1.417888125164395774e+01 +1.437036667204294815e+01 +1.459451537599615278e+01 +1.476049705282296287e+01 +1.491122607316001236e+01 +1.500000000000000000e+01 +1.504157638165976252e+01 +1.514528761178619121e+01 +1.525632054341177124e+01 +1.548032042867475511e+01 +1.567531756037045199e+01 +1.618265961621010973e+01 +1.573636563167896796e+01 +1.500000000000000000e+01 +1.479245969724008702e+01 +1.477090318701112537e+01 +1.458825231374745712e+01 +1.446188575461374271e+01 +1.414311834532644951e+01 +1.388447557942924604e+01 +1.449990234002684986e+01 +1.500000000000000000e+01 +1.575350947281338065e+01 +1.683825707587893206e+01 +1.747464985881720878e+01 +1.750000000000000000e+01 +1.758742271904822729e+01 +1.815010287760036789e+01 +1.822252874689671032e+01 +1.786026333972624869e+01 +1.750000000000000000e+01 +1.723553197789316016e+01 +1.672534301699839077e+01 +1.648619240882763037e+01 +1.627795951944261788e+01 +1.619950102192695951e+01 +1.616697736849962297e+01 +1.607489969559567911e+01 +1.610426771519227884e+01 +1.619034795149785566e+01 +1.641090057830893301e+01 +1.674341718306047255e+01 +1.713078923581528912e+01 +1.750000000000000000e+01 +1.751313394714490101e+01 +1.777431270453679701e+01 +1.790517239120057269e+01 +1.806890768240830170e+01 +1.820384481255693032e+01 +1.837668498113607285e+01 +1.862397596026533364e+01 +1.885631930252694488e+01 +1.900672163003863346e+01 +1.923168501835696276e+01 +1.941741010362622788e+01 +1.963937616453407742e+01 +1.986025906818202102e+01 diff --git a/diagnostics/TUTT/doc/TUTT_contour_length_1979-Ug_2.0.txt b/diagnostics/TUTT/doc/TUTT_contour_length_1979-Ug_2.0.txt new file mode 100644 index 000000000..a1abf7d34 --- /dev/null +++ b/diagnostics/TUTT/doc/TUTT_contour_length_1979-Ug_2.0.txt @@ -0,0 +1 @@ +1.810000000000000000e+02 diff --git a/diagnostics/TUTT/doc/TUTT_contour_lon_1979-Ug_2.0.txt b/diagnostics/TUTT/doc/TUTT_contour_lon_1979-Ug_2.0.txt new file mode 100644 index 000000000..9d669e000 --- /dev/null +++ b/diagnostics/TUTT/doc/TUTT_contour_lon_1979-Ug_2.0.txt @@ -0,0 +1,181 @@ +0.000000000000000000e+00 +1.202358759731234850e+00 +2.500000000000000000e+00 +5.000000000000000000e+00 +7.500000000000000000e+00 +1.000000000000000000e+01 +1.250000000000000000e+01 +1.500000000000000000e+01 +1.750000000000000000e+01 +2.000000000000000000e+01 +2.250000000000000000e+01 +2.409164607668155966e+01 +2.500000000000000000e+01 +2.750000000000000000e+01 +3.000000000000000000e+01 +3.250000000000000000e+01 +3.500000000000000000e+01 +3.750000000000000000e+01 +4.000000000000000000e+01 +4.250000000000000000e+01 +4.500000000000000000e+01 +4.750000000000000000e+01 +5.000000000000000000e+01 +5.250000000000000000e+01 +5.474304275649711116e+01 +5.500000000000000000e+01 +5.526801832582294338e+01 +5.750000000000000000e+01 +5.875023442947536267e+01 +6.000000000000000000e+01 +6.250000000000000000e+01 +6.500000000000000000e+01 +6.750000000000000000e+01 +7.000000000000000000e+01 +7.250000000000000000e+01 +7.500000000000000000e+01 +7.750000000000000000e+01 +8.000000000000000000e+01 +8.250000000000000000e+01 +8.500000000000000000e+01 +8.750000000000000000e+01 +9.000000000000000000e+01 +9.250000000000000000e+01 +9.500000000000000000e+01 +9.750000000000000000e+01 +1.000000000000000000e+02 +1.025000000000000000e+02 +1.050000000000000000e+02 +1.075000000000000000e+02 +1.100000000000000000e+02 +1.125000000000000000e+02 +1.150000000000000000e+02 +1.175000000000000000e+02 +1.200000000000000000e+02 +1.225000000000000000e+02 +1.250000000000000000e+02 +1.275000000000000000e+02 +1.300000000000000000e+02 +1.325000000000000000e+02 +1.350000000000000000e+02 +1.375000000000000000e+02 +1.400000000000000000e+02 +1.425000000000000000e+02 +1.450000000000000000e+02 +1.465421064856791702e+02 +1.475000000000000000e+02 +1.500000000000000000e+02 +1.525000000000000000e+02 +1.550000000000000000e+02 +1.575000000000000000e+02 +1.600000000000000000e+02 +1.625000000000000000e+02 +1.650000000000000000e+02 +1.675000000000000000e+02 +1.700000000000000000e+02 +1.725000000000000000e+02 +1.750000000000000000e+02 +1.775000000000000000e+02 +1.800000000000000000e+02 +1.825000000000000000e+02 +1.850000000000000000e+02 +1.875000000000000000e+02 +1.875209779280447435e+02 +1.875000000000000000e+02 +1.866128024864255792e+02 +1.850000000000000000e+02 +1.827558466409126368e+02 +1.825000000000000000e+02 +1.800000000000000000e+02 +1.776567677146772724e+02 +1.775000000000000000e+02 +1.750000000000000000e+02 +1.726641782430362468e+02 +1.725000000000000000e+02 +1.700000000000000000e+02 +1.696859048900813889e+02 +1.700000000000000000e+02 +1.714188764821868745e+02 +1.725000000000000000e+02 +1.750000000000000000e+02 +1.775000000000000000e+02 +1.800000000000000000e+02 +1.825000000000000000e+02 +1.850000000000000000e+02 +1.875000000000000000e+02 +1.900000000000000000e+02 +1.925000000000000000e+02 +1.950000000000000000e+02 +1.975000000000000000e+02 +2.000000000000000000e+02 +2.025000000000000000e+02 +2.050000000000000000e+02 +2.075000000000000000e+02 +2.100000000000000000e+02 +2.125000000000000000e+02 +2.150000000000000000e+02 +2.175000000000000000e+02 +2.176903938775956817e+02 +2.200000000000000000e+02 +2.225000000000000000e+02 +2.250000000000000000e+02 +2.275000000000000000e+02 +2.300000000000000000e+02 +2.325000000000000000e+02 +2.350000000000000000e+02 +2.375000000000000000e+02 +2.400000000000000000e+02 +2.425000000000000000e+02 +2.450000000000000000e+02 +2.466170161512711161e+02 +2.475000000000000000e+02 +2.500000000000000000e+02 +2.525000000000000000e+02 +2.550000000000000000e+02 +2.575000000000000000e+02 +2.600000000000000000e+02 +2.625000000000000000e+02 +2.645163365682304288e+02 +2.650000000000000000e+02 +2.675000000000000000e+02 +2.700000000000000000e+02 +2.725000000000000000e+02 +2.750000000000000000e+02 +2.775000000000000000e+02 +2.800000000000000000e+02 +2.811569598270448296e+02 +2.825000000000000000e+02 +2.850000000000000000e+02 +2.875000000000000000e+02 +2.880069402873401714e+02 +2.900000000000000000e+02 +2.925000000000000000e+02 +2.950000000000000000e+02 +2.975000000000000000e+02 +2.990231202873446819e+02 +3.000000000000000000e+02 +3.025000000000000000e+02 +3.050000000000000000e+02 +3.075000000000000000e+02 +3.100000000000000000e+02 +3.125000000000000000e+02 +3.150000000000000000e+02 +3.175000000000000000e+02 +3.200000000000000000e+02 +3.225000000000000000e+02 +3.250000000000000000e+02 +3.275000000000000000e+02 +3.298705213958058948e+02 +3.300000000000000000e+02 +3.325000000000000000e+02 +3.350000000000000000e+02 +3.375000000000000000e+02 +3.400000000000000000e+02 +3.425000000000000000e+02 +3.450000000000000000e+02 +3.475000000000000000e+02 +3.500000000000000000e+02 +3.525000000000000000e+02 +3.550000000000000000e+02 +3.575000000000000000e+02 +3.600000000000000000e+02 diff --git a/diagnostics/TUTT/doc/TUTT_example.png b/diagnostics/TUTT/doc/TUTT_example.png new file mode 100644 index 000000000..80a79a143 Binary files /dev/null and b/diagnostics/TUTT/doc/TUTT_example.png differ diff --git a/diagnostics/TUTT/doc/TUTT_ref_lat_1979-Ug_2.0.txt b/diagnostics/TUTT/doc/TUTT_ref_lat_1979-Ug_2.0.txt new file mode 100644 index 000000000..43562efd4 --- /dev/null +++ b/diagnostics/TUTT/doc/TUTT_ref_lat_1979-Ug_2.0.txt @@ -0,0 +1,181 @@ +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 +2.016079837805656183e+01 diff --git a/diagnostics/TUTT/doc/dividing_longitude_1979.txt b/diagnostics/TUTT/doc/dividing_longitude_1979.txt new file mode 100644 index 000000000..3edb0baab --- /dev/null +++ b/diagnostics/TUTT/doc/dividing_longitude_1979.txt @@ -0,0 +1,13 @@ +2.400000000000000000e+02 +2.400000000000000000e+02 +2.400000000000000000e+02 +2.400000000000000000e+02 +2.400000000000000000e+02 +2.400000000000000000e+02 +2.400000000000000000e+02 +2.400000000000000000e+02 +2.400000000000000000e+02 +2.400000000000000000e+02 +2.400000000000000000e+02 +2.400000000000000000e+02 +2.400000000000000000e+02 diff --git a/diagnostics/TUTT/doc/fig1.png b/diagnostics/TUTT/doc/fig1.png new file mode 100644 index 000000000..70608eb31 Binary files /dev/null and b/diagnostics/TUTT/doc/fig1.png differ diff --git a/diagnostics/TUTT/doc/fig1_update.png b/diagnostics/TUTT/doc/fig1_update.png new file mode 100644 index 000000000..70608eb31 Binary files /dev/null and b/diagnostics/TUTT/doc/fig1_update.png differ diff --git a/diagnostics/TUTT/doc/fig2.png b/diagnostics/TUTT/doc/fig2.png new file mode 100644 index 000000000..ac3353b9d Binary files /dev/null and b/diagnostics/TUTT/doc/fig2.png differ diff --git a/diagnostics/TUTT/doc/table1.pdf b/diagnostics/TUTT/doc/table1.pdf new file mode 100644 index 000000000..dbcc06f1f Binary files /dev/null and b/diagnostics/TUTT/doc/table1.pdf differ diff --git a/diagnostics/TUTT/doc/table1.png b/diagnostics/TUTT/doc/table1.png new file mode 100644 index 000000000..74bfffd1e Binary files /dev/null and b/diagnostics/TUTT/doc/table1.png differ diff --git a/diagnostics/TUTT/doc/tutt_Area_lat-1979-1979JASO-Ug_2.0.txt b/diagnostics/TUTT/doc/tutt_Area_lat-1979-1979JASO-Ug_2.0.txt new file mode 100644 index 000000000..403e4e6d4 --- /dev/null +++ b/diagnostics/TUTT/doc/tutt_Area_lat-1979-1979JASO-Ug_2.0.txt @@ -0,0 +1,2 @@ +Year Pac Atl +1979 16.569148936170212 18.571428571428573 diff --git a/diagnostics/TUTT/doc/tutt_Area_lon-1979-1979JASO-Ug_2.0.txt b/diagnostics/TUTT/doc/tutt_Area_lon-1979-1979JASO-Ug_2.0.txt new file mode 100644 index 000000000..3b1d7534f --- /dev/null +++ b/diagnostics/TUTT/doc/tutt_Area_lon-1979-1979JASO-Ug_2.0.txt @@ -0,0 +1,2 @@ +Year Pac Atl +1979 207.04787234042553 289.83516483516485 diff --git a/diagnostics/TUTT/doc/tutt_UG.wt_lat-1979-1979JASO-Ug_2.0.txt b/diagnostics/TUTT/doc/tutt_UG.wt_lat-1979-1979JASO-Ug_2.0.txt new file mode 100644 index 000000000..72474105f --- /dev/null +++ b/diagnostics/TUTT/doc/tutt_UG.wt_lat-1979-1979JASO-Ug_2.0.txt @@ -0,0 +1,2 @@ +Year Pac Atl +1979 17.634707343481693 18.998723699860186 diff --git a/diagnostics/TUTT/doc/tutt_UG.wt_lon-1979-1979JASO-Ug_2.0.txt b/diagnostics/TUTT/doc/tutt_UG.wt_lon-1979-1979JASO-Ug_2.0.txt new file mode 100644 index 000000000..3bf0258ba --- /dev/null +++ b/diagnostics/TUTT/doc/tutt_UG.wt_lon-1979-1979JASO-Ug_2.0.txt @@ -0,0 +1,2 @@ +Year Pac Atl +1979 209.62735386335711 283.11888339796485 diff --git a/diagnostics/TUTT/doc/tutt_area-1979-1979JASO-Ug_2.0.txt b/diagnostics/TUTT/doc/tutt_area-1979-1979JASO-Ug_2.0.txt new file mode 100644 index 000000000..827f0bd4c --- /dev/null +++ b/diagnostics/TUTT/doc/tutt_area-1979-1979JASO-Ug_2.0.txt @@ -0,0 +1,2 @@ +Year Pac Atl +1979 544.0315239891869 404.7156477172561 diff --git a/diagnostics/TUTT/doc/tutt_intensity-1979-1979JASO-Ug_2.0.txt b/diagnostics/TUTT/doc/tutt_intensity-1979-1979JASO-Ug_2.0.txt new file mode 100644 index 000000000..97b86dacc --- /dev/null +++ b/diagnostics/TUTT/doc/tutt_intensity-1979-1979JASO-Ug_2.0.txt @@ -0,0 +1,2 @@ +Year Pac Atl +1979 0.0 0.0 diff --git a/diagnostics/TUTT/doc/tutt_ref.latitude-1979-1979JASO-Ug_2.0.txt b/diagnostics/TUTT/doc/tutt_ref.latitude-1979-1979JASO-Ug_2.0.txt new file mode 100644 index 000000000..3c2675a65 --- /dev/null +++ b/diagnostics/TUTT/doc/tutt_ref.latitude-1979-1979JASO-Ug_2.0.txt @@ -0,0 +1,2 @@ +Year Ref.Lat Ref.Lat0 +1978 20.160798378056562 20.160798378056562 diff --git a/diagnostics/TUTT/settings.jsonc b/diagnostics/TUTT/settings.jsonc new file mode 100644 index 000000000..f9d57e966 --- /dev/null +++ b/diagnostics/TUTT/settings.jsonc @@ -0,0 +1,38 @@ +{ + "settings": { + "long_name": "Tropical Upper-Tropospheric Trough (TUTT) Diagnostic Package", + "driver": "TUTT.py", + "realm": "atmos", + "description": "This diagnostic package is used to evaluate 200-hPa TUTT area in both climate models and reanalysis datasets.", + "runtime_requirements": { + "python3": ["netCDF4", "skimage", "numpy", "scipy", "shapely.geometry", "cartopy"] + } + }, + "data": { + "frequency": "month" + }, + "dimensions": { + "lat": { + "standard_name": "latitude", + "units": "degrees_north" + }, + "lon": { + "standard_name": "longitude", + "units": "degrees_east" + }, + "time": { + "standard_name": "time", + "units": "mon" + } + }, + "varlist": { + "Z200": { + "path_variable": "Z200_FILE", + "standard_name": "geopotential_height_200_mbar", + "freq": "mon", + "requirement": "required", + "units": "m", + "dimensions": ["time", "lat", "lon"] + } + } +}