AJMR-Python-Baird/NTC_DFM/NTC_PlottingD3D_2023.py

334 lines
13 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
@author: AJMR
Plotting and animation script for NTC
Febuary 01, 2023
"""
import os
import pandas as pd
import numpy as np
import geopandas as gp
import pytz
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import dfm_tools as dfmt
from dfm_tools.get_nc import get_netdata, get_ncmodeldata, plot_netmapdata
from dfm_tools.get_nc_helpers import get_ncvarproperties, get_stationid_fromstationlist, get_varnamefromattrs
import cartopy.crs as ccrs
import contextily as ctx
from shapely.geometry import Point, MultiPoint
from shapely.ops import nearest_points
import pathlib as pl
import xarray as xr
from datetime import timedelta
import datetime as datetime
#%% Read Model Log
runLog = pd.read_excel('C:/Users/arey/files/Projects/Newtown/Model Log NTC.xlsx', 'ModelLog')
dataPath = "FlowFM_map.nc"
histPath = "FlowFM_his.nc"
#%% Load in Water Level Data
# Field Gauge-EAST
FFG_pd = pd.read_csv("//srv-ott3/Projects/11934.201 Newtown Creek TPP Privileged and Confidential/03_Data/02_Physical/00_ProcessingCode/NetCDF/Gauge/FieldFacility.csv")
FFG_pd['DateTime'] = pd.to_datetime(FFG_pd.Date_time)
FFG_pd.set_index(FFG_pd['DateTime'], inplace=True)
# Put in UTC from Eastern Time (with DST!)
FFG_pd = FFG_pd.tz_localize(
pytz.timezone('US/Eastern'), ambiguous='infer').tz_convert(pytz.utc)
# National Grid Gauge-WEST
NGG1_pd = pd.read_csv("//srv-ott3/Projects/11934.201 Newtown Creek TPP Privileged and Confidential/03_Data/02_Physical/00_ProcessingCode/NetCDF/Gauge/NationalGrid1.csv")
NGG1_pd['DateTime'] = pd.to_datetime(NGG1_pd.Date_time)
NGG1_pd.set_index(NGG1_pd['DateTime'], inplace=True)
# Put in UTC from Eastern Time (with DST!)
NGG1_pd = NGG1_pd.tz_localize(
pytz.timezone('US/Eastern'), ambiguous='NaT').tz_convert(pytz.utc)
# Drop ambiguous times
NGG1_pd = NGG1_pd.dropna()
NGG2_pd = pd.read_csv("//srv-ott3/Projects/11934.201 Newtown Creek TPP Privileged and Confidential/03_Data/02_Physical/00_ProcessingCode/NetCDF/Gauge/NationalGrid2.csv")
NGG2_pd['DateTime'] = pd.to_datetime(NGG2_pd.datetime)
NGG2_pd.set_index(NGG2_pd['DateTime'], inplace=True)
# Put in UTC from Eastern Time (with DST!)
NGG2_pd = NGG2_pd.tz_localize(
pytz.timezone('US/Eastern'), ambiguous='NaT').tz_convert(pytz.utc)
# Drop ambiguous times
NGG2_pd = NGG2_pd.dropna()
#%% Read in time series
modelPlot = [102, 104]
Delft_WL = [None] * (max(modelPlot)+1)
# Note, this uses the standard netcdf lib + xarray
for i in modelPlot:
file_nc_hist = pl.Path(runLog['Run Location'][i],
'FlowFM', 'dflowfm', 'output', 'FlowFM_his.nc')
# Hist file path
file_nc_hist = file_nc_hist.as_posix()
# Open hist file dataset
data_xr = xr.open_mfdataset(file_nc_hist, preprocess=dfmt.preprocess_hisnc)
# Get Variables
vars_pd = get_ncvarproperties(data_xr)
# Get stations
stations_pd = data_xr['stations'].to_dataframe()
# Convert to Pandas
Delft_WL[i] = data_xr.waterlevel.sel(stations=['West_WL', 'East_WL']).to_pandas()
# Put in UTC if needed
if i == 104 or i == 105 or i >= 135:
Delft_WL[i] = Delft_WL[i].tz_localize(
pytz.timezone('EST')).tz_convert(pytz.utc)
else:
Delft_WL[i] = Delft_WL[i].tz_localize(
pytz.timezone('UTC'))
#%% Read in EFDC Data to dataframe
efdc_df = pd.read_csv(
'//ott-athena.baird.com/D/11934.201_Newtown_Creek_TPP/EFDC_MNR/2015_8/READ_FROM_EFDC_GRAPHICS_OUT_BIN.CSV')
#%% Read in EFDC grid
efdc_grid_df = pd.read_csv('//ott-athena.baird.com/D/11934.201_Newtown_Creek_TPP/EFDC_MNR/GRID_FILES/NC_ER_lxly_20140129.inp',
delim_whitespace=True, skiprows=4,
names=['I', 'J', 'X', 'Y', 'CUE', 'CVE', 'CUN', 'CVN'])
efdc_grid_gdf = gp.GeoDataFrame(
efdc_grid_df, geometry=gp.points_from_xy(efdc_grid_df.X, efdc_grid_df.Y), crs="EPSG:32118")
#%% Merge EFDC outputs with grid locations and add datetimes
efdc_merged = pd.merge(efdc_df, efdc_grid_df, how='left', left_on=['I_MOD','J_MOD'],
right_on = ['I','J']).drop(columns=[
' DUMPID', 'END_hr', 'I_MOD', 'J_MOD', 'I_MOD', 'X', 'Y', 'CUE', 'CVE', 'CUN', 'CVN'])
efdc_merged['date'] = pd.to_datetime([datetime.datetime(2015, 8, 1, 0, 0, 0) +
timedelta(hours=h) for h in efdc_merged['ST_hr']])
efdc_merged.set_index('date', inplace=True)
#Convert to UTC
efdc_merged.index = efdc_merged.index.tz_localize(
pytz.timezone('EST')).tz_convert(pytz.utc)
efdc_merged_gdf = gp.GeoDataFrame(
efdc_merged, geometry=efdc_merged['geometry'], crs="EPSG:32118")
del efdc_merged
#%% Find nearest grid point to station FFG
nearest_geoms = nearest_points(Point(
data_xr.waterlevel.sel(stations=['East_WL']).station_x_coordinate.values[0],
data_xr.waterlevel.sel(stations=['East_WL']).station_y_coordinate.values[0]),
MultiPoint(efdc_grid_gdf.geometry))
stationFFG_gdf = efdc_merged_gdf.loc[efdc_merged_gdf['geometry'] == nearest_geoms[1]]
#%% Find nearest grid point to station NGG
nearest_geoms = nearest_points(Point(
data_xr.waterlevel.sel(stations=['West_WL']).station_x_coordinate.values[0],
data_xr.waterlevel.sel(stations=['West_WL']).station_y_coordinate.values[0]),
MultiPoint(efdc_grid_gdf.geometry))
stationNGG_gdf = efdc_merged_gdf.loc[efdc_merged_gdf['geometry'] == nearest_geoms[1]]
#%% Plot Time Series
modelPlot = [102, 104]
fig, axes = plt.subplots(nrows=2, ncols=1, figsize=(9, 8),
sharex=True)
# Plot Data
FFG_pd['Water Surface Elevation (ft)'].shift(
0, timedelta(days=1)).multiply(0.3048).plot(ax=axes[0],
color='k', label='Field Facility Gauge')
#Plot EFDC
stationFFG_gdf['WSE_m'].plot(ax=axes[0], label='EFDC 2019')
# Plot Delft3D
for i in modelPlot:
Delft_WL[i]['East_WL'].plot(ax=axes[0],
label='Delft3D: ' + runLog['Plotting Legend Entry'][i])
# Set axis
axes[0].set_xlim(Delft_WL[modelPlot[0]].index[0],
Delft_WL[modelPlot[0]].index[-1])
axes[0].set_ylim(-1.5, 2.5)
axes[0].legend(loc='upper right')
# Plot Data
NGG2_pd['water_surface_elevation'].shift(
0, timedelta(hours=1)).multiply(0.3048).plot(ax=axes[1],
color='k', label='National Grid Gauge')
#Plot EFDC
stationNGG_gdf['WSE_m'].plot(ax=axes[1], label='EFDC')
# Plot Delft
for i in modelPlot:
Delft_WL[i]['West_WL'].plot(ax=axes[1],
label='Delft3D: ' + runLog['Plotting Legend Entry'][i])
# Set axis
axes[1].set_xlim(Delft_WL[modelPlot[0]].index[0],
Delft_WL[modelPlot[0]].index[-1])
axes[1].set_ylim(-1.5, 2.5)
axes[1].legend(loc='upper right')
plt.show()
fig.savefig('C:/Users/arey/files/Projects/Newtown/Figures2023/TS_2023.png',
bbox_inches='tight', dpi=400)
#%% Plot scatters
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(10, 6))
fig.patch.set_facecolor('white')
interpTimes = pd.date_range(Delft_WL[modelPlot[0]].index[0],
Delft_WL[modelPlot[0]].index[-1],
freq="20min")
# Compare EFDC and Data
axes[0].scatter(np.interp(interpTimes, FFG_pd.index,
FFG_pd['Water Surface Elevation (ft)']*0.3048),
np.interp(interpTimes, stationFFG_gdf.index,
stationFFG_gdf['WSE_m']), s=1,
label='EFDC 2019')
for i in modelPlot:
# Compare Delft3D and Data
axes[0].scatter(np.interp(interpTimes, FFG_pd.index,
FFG_pd['Water Surface Elevation (ft)']*0.3048),
np.interp(interpTimes, Delft_WL[i].index,
Delft_WL[i]['East_WL']), s=1,
label='Delft3D: ' + runLog['Plotting Legend Entry'][i])
linepts = np.array([-1.5, 1.5])
axes[0].plot(linepts, linepts, color='k')
axes[0].legend(loc='lower right')
axes[0].set_xlim(-1.5, 1.5)
axes[0].set_ylim(-1.5, 1.5)
axes[0].set_aspect('equal', 'box')
# Compare EFDC and Data
modelInterp = np.interp(interpTimes, stationNGG_gdf.index.shift(
0, timedelta(hours=1)),
stationNGG_gdf['WSE_m'])
dataInterp = np.interp(interpTimes, NGG2_pd.index,
NGG2_pd['water_surface_elevation']*0.3048)
axes[1].scatter(dataInterp, modelInterp, s=1,
label='EFDC 2019')
print(np.sqrt(np.mean((modelInterp-dataInterp)**2)))
corr_matrix = np.corrcoef(dataInterp, modelInterp)
print(corr_matrix[0, 1]**2)
for i in modelPlot:
# Compare Delft3D and Data
modelInterp = np.interp(interpTimes, Delft_WL[i].index.shift(
0, timedelta(hours=1)),
Delft_WL[i]['West_WL'])
dataInterp = np.interp(interpTimes, NGG2_pd.index,
NGG2_pd['water_surface_elevation']*0.3048)
axes[1].scatter(dataInterp, modelInterp, s=1,
label='Delft3D: ' + runLog['Plotting Legend Entry'][i])
print(np.sqrt(np.mean((modelInterp-dataInterp)**2)))
corr_matrix = np.corrcoef(dataInterp, modelInterp)
print(corr_matrix[0, 1]**2)
axes[1].plot(linepts, linepts, color='k')
axes[1].legend(loc='lower right')
axes[1].set_aspect('equal', 'box')
plt.show()
fig.savefig('C:/Users/arey/files/Projects/Newtown/Figures2023/FFG_Scatter2023.png',
bbox_inches='tight', dpi=400)
#%% Read in YSI ADCP
# %% Load in moored data
df_moored_data = pd.read_excel('//srv-ott3/Projects/11934.201 Newtown Creek TPP Privileged and Confidential/03_Data/02_Physical/05 Currents/NC_CurrentMeter_All_Phase1_all_data_2013_07_16/NC_CurrentMeter_All_Phase1_all_moored_2013_05_20.xlsx',
sheet_name='mag_all_moored')
# Shift col names to put second back in
colIN = list(df_moored_data.columns)
colOUT = colIN[0:6] + ['second'] + colIN[6:-1]
df_moored_data.columns = colOUT
### Moored current meter locations from here:
### file://srv-ott3/Projects/11934.201%20Newtown%20Creek%20TPP%20%E2%80%93%20Privileged%20and%20Confidential/03_Data/01_BkgrdReports/NC_DRAFT_DSR_Submittal_No_3_2013-07-03.pdf
### Table 3-1, PDF page 65
### Locations change between deployment 1-9 and 10/11
### YSI from 2021 FRMR report Pg 385
df_moored = pd.DataFrame(
{'depOrig': ['NC083CM', 'NC081CM', 'NC082CM', 'NC086CM', 'EK023CM',
'NC310', 'NC313', 'NC316', 'NC318', 'EK108', 'EB043'],
'depCurr': ['NC086CM', 'NC087CM', 'NC088CM', 'NC089CM', 'EK023CM',
'NC310', 'NC313', 'NC316', 'NC318', 'EK108', 'EB043'],
'Northing': [208519.95, 206083.24, 203835.10, 201381.55, 200827.33,
208809.66, 205547.85, 203870.2, 201684.6, 200860.91, 200336.12],
'Easting': [996198.97, 1000959.45, 1004387.42, 1005283.07, 1004644.90,
996586.22, 1001028.85, 1004501.4, 1005027.4, 1004516.53, 1005535.44],
'bedElev': [-16, -17, -20, -18, -20, 0, 0, 0, 0, 0, 0]})
gdf_moored_loc = gp.GeoDataFrame(
df_moored, geometry=gp.points_from_xy(df_moored.Easting, df_moored.Northing), crs="EPSG:2263")
gdf_moored_loc.geometry = gdf_moored_loc.geometry.to_crs("EPSG:32118")
# Loop through Station IDs for deployments 1-9 and assign locations
# for d in range(1,10):
# depMask = df_moored_data['deployment'] == ('dep' + str(d))
# for stationIDX, station in enumerate(df_moored['depOrig']):
# stationMask = (df_moored_data['station'] == station) & depMask
#
# # Assign geography to station plus deployment
# df_moored_data.loc[stationMask, 'Northing'] = df_moored.loc[stationIDX, 'Northing']
# df_moored_data.loc[stationMask, 'Easting'] = df_moored.loc[stationIDX, 'Easting']
# Loop through Station IDs for deployments 10-11 and assign locations
for d in range(1,12):
depMask = df_moored_data['deployment'] == 'dep' + str(d)
for stationIDX, station in enumerate(df_moored['depCurr']):
stationMask = (df_moored_data['station'] == station) & depMask
# Assign geography to station plus deployment
df_moored_data.loc[stationMask, 'Northing'] = df_moored.loc[stationIDX, 'Northing']
df_moored_data.loc[stationMask, 'Easting'] = df_moored.loc[stationIDX, 'Easting']
# Create geodataframe and convert to USSP
gdf_moored = gp.GeoDataFrame(
df_moored_data, geometry=gp.points_from_xy(df_moored_data.Easting, df_moored_data.Northing), crs="EPSG:2263")
#convert data to CRS of D3D
gdf_moored.geometry = gdf_moored.geometry.to_crs("EPSG:32118")
gdf_moored['date'] = pd.to_datetime(gdf_moored['year'].astype(str) + '-' +
gdf_moored['month'].astype(str).str.zfill(2) + '-' +
gdf_moored['day'].astype(str).str.zfill(2) + ' ' +
gdf_moored['hour'].astype(str).str.zfill(2) + ':' +
gdf_moored['minute'].astype(str).str.zfill(2))
#%% Velocity validation