# -*- coding: utf-8 -*-
"""
Tools for post-processing Open Telemac-Mascaret model data extract to OCMW format.
Chris Old
IES, School of Engineering, University of Edinburgh
Sep 2023
"""
# ----------------------------------------------------------------------------
# IMPORTS
# ----------------------------------------------------------------------------
# Standard Python Dependencies
import os
# Non-Standard Python Dependencies
import numpy as np
# Local Module Dependencies
from ocmw.core.fileTools import getListOfFiles, generateGlobalAttributes
from ocmw.core.flowChar import preprocess_ts
from .ocmw_extract import ocmwExtn
from .ocmw_extract import load_ocmw_file, save_ocmw_file
from .ocmw_extract import extract_ts_at_hub
from .ocmw_extract import extract_model_ts_at_surface
from .ocmw_extract import extract_depthavg_ts
from .ocmw_extract import extract_rotav_ts_at_hub
# Other Dependencies
# ----------------------------------------------------------------------------
# GLOBAL VARIABLES
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# CLASS DEFINITIONS
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# FUNCTION DEFINITIONS
# ----------------------------------------------------------------------------
[docs]
def locDataExists(datapath,filename):
"""
Determine whether a data file exists
Parameters
----------
datapath : str
Full path to the data file.
filename : str
Name of data file.
Returns
-------
dataExists : bool
Flag indicating file existence.
"""
dataExists = False
if os.path.isdir(datapath):
if os.path.isfile(datapath+'/'+filename):
dataExists = True
return dataExists
[docs]
def hub_height_data(modelpath,filename,datasrc,dataset,tec,outfile):
"""
Extract TEC hub-height data from a timeseries of model profiles extracted at a specific location.
"""
datapath = modelpath+'/EXTRACT'
if locDataExists(datapath,filename):
analpath = modelpath+'/ANALYSIS'
if not os.path.isdir(analpath):
os.mkdir(analpath)
ofprts = outfile.split('.')
hab = tec.bottomMounted
zhub = tec.hubHeight
rdia = tec.rotorDiam
Cp = tec.Cp
if hab:
rstr = '_hab_'
else:
rstr = '_dbs_'
model_ts = extract_ts_at_hub(datapath,filename,dataset,datasrc,zhub,hab=hab)
ofile = ofprts[0]+rstr+str(np.int32(np.ceil(zhub))).zfill(2)+'m_TS.'+ofprts[1]
save_ocmw_file(analpath,ofile,model_ts)
model_data = preprocess_ts(model_ts,tec=tec)
ofile = ofprts[0]+rstr+str(np.int32(np.ceil(zhub))).zfill(2)+'m_PP.'+ofprts[1]
save_ocmw_file(analpath,ofile,model_data)
pwra_data = extract_rotav_ts_at_hub(datapath,filename,dataset,datasrc,model_data,rdia,zhub,hab=True,pwra=True,Cp=Cp)
ofile = ofprts[0]+rstr+str(np.int32(np.ceil(zhub))).zfill(2)+'m_PWRA.'+ofprts[1]
save_ocmw_file(analpath,ofile,pwra_data)
else:
print('Warning: Location data not avialble in '+modelpath)
model_ts = None
model_data = None
pwra_data = None
return model_ts, model_data, pwra_data
[docs]
def hab_data(modelpath,filename,datasrc,dataset,z,outfile):
"""
Extract data at a specified height-above-bed from a timeseries of model profiles extracted at a specific location.
"""
datapath = modelpath+'/EXTRACT'
if locDataExists(datapath,filename):
analpath = modelpath+'/ANALYSIS'
if not os.path.isdir(analpath):
os.mkdir(analpath)
ofprts = outfile.split('.')
rstr = '_hab_'
model_ts = extract_ts_at_hub(datapath,filename,dataset,datasrc,z,hab=True)
ofile = ofprts[0]+rstr+str(np.int32(np.ceil(z))).zfill(2)+'m_TS.'+ofprts[1]
save_ocmw_file(analpath,ofile,model_ts)
model_data = preprocess_ts(model_ts)
ofile = ofprts[0]+rstr+str(np.int32(np.ceil(z))).zfill(2)+'m_PP.'+ofprts[1]
save_ocmw_file(analpath,ofile,model_data)
else:
print('Warning: Location data not avialble in '+modelpath)
model_ts = None
model_data = None
return model_ts, model_data
[docs]
def dbs_data(modelpath,filename,datasrc,dataset,d,outfile):
"""
Extract data at a specified depth-below-surface from a timeseries of model profiles extracted at a specific location.
"""
datapath = modelpath+'/EXTRACT'
if locDataExists(datapath,filename):
analpath = modelpath+'/ANALYSIS'
if not os.path.isdir(analpath):
os.mkdir(analpath)
ofprts = outfile.split('.')
rstr = '_hab_'
model_ts = extract_ts_at_hub(datapath,filename,dataset,datasrc,d,hab=False)
ofile = ofprts[0]+rstr+str(np.int32(np.ceil(d))).zfill(2)+'m_TS.'+ofprts[1]
save_ocmw_file(analpath,ofile,model_ts)
model_data = preprocess_ts(model_ts)
ofile = ofprts[0]+rstr+str(np.int32(np.ceil(d))).zfill(2)+'m_PP.'+ofprts[1]
save_ocmw_file(analpath,ofile,model_data)
else:
print('Warning: Location data not avialble in '+modelpath)
model_ts = None
model_data = None
return model_ts, model_data
[docs]
def dav_data(modelpath,filename,datasrc,dataset,outfile):
"""
Extract depth-averaged data from a timeseries of model profiles extracted at a specific location.
"""
datapath = modelpath+'/EXTRACT'
if locDataExists(datapath,filename):
analpath = modelpath+'/ANALYSIS'
if not os.path.isdir(analpath):
os.mkdir(analpath)
ofprts = outfile.split('.')
rstr = '_hab_'
model_ts = extract_depthavg_ts(datapath,filename,dataset,datasrc)
d = model_ts['zLoc']
ofile = ofprts[0]+rstr+str(np.int32(np.ceil(d))).zfill(2)+'m_TS.'+ofprts[1]
save_ocmw_file(analpath,ofile,model_ts)
model_data = preprocess_ts(model_ts)
ofile = ofprts[0]+rstr+str(np.int32(np.ceil(d))).zfill(2)+'m_PP.'+ofprts[1]
save_ocmw_file(analpath,ofile,model_data)
else:
print('Warning: Location data not avialble in '+modelpath)
model_ts = None
model_data = None
return model_ts, model_data
[docs]
def srf_data(modelpath,filename,datasrc,dataset,outfile):
"""
Extract data at the sea surface from a timeseries of model profiles extracted at a specific location.
"""
datapath = modelpath+'/EXTRACT'
if locDataExists(datapath,filename):
analpath = modelpath+'/ANALYSIS'
if not os.path.isdir(analpath):
os.mkdir(analpath)
ofprts = outfile.split('.')
rstr = '_hab_'
model_ts = extract_model_ts_at_surface(datapath,filename,dataset,datasrc)
d = model_ts['zLoc']
ofile = ofprts[0]+rstr+str(np.int32(np.ceil(d))).zfill(2)+'m_TS.'+ofprts[1]
save_ocmw_file(analpath,ofile,model_ts)
model_data = preprocess_ts(model_ts)
ofile = ofprts[0]+rstr+str(np.int32(np.ceil(d))).zfill(2)+'m_PP.'+ofprts[1]
save_ocmw_file(analpath,ofile,model_data)
else:
print('Warning: Location data not avialble in '+modelpath)
model_ts = None
model_data = None
return model_ts, model_data
[docs]
def merge_model_daily_files(datapath,srchstr,outfile):
"""
Merge daily model extract data into single a file for post-processing.
"""
files = getListOfFiles(datapath,srchstr+'*'+ocmwExtn)
mrgdata = {}
for i,f in enumerate(files):
d = load_ocmw_file(datapath,f)
if i == 0:
titleStr = 'Merged location data - '+datapath.split('/')[-2]+' model'
mrgdata['globalAttributes'] = generateGlobalAttributes(titleStr)
mrgdata['dataLoc'] = d['dataLoc']
mrgdata['crs'] = d['crs']
mrgdata['meshElem'] = d['meshElem']
mrgdata['timeUnits'] = d['timeUnits']
mrgdata['epoch'] = d['epoch']
times = d['times']
depth = d['depth']
height = d['height']
depAvg_U = d['depAvg_U']
depAvg_V = d['depAvg_V']
if 'z' in d.keys():
if d['vel_east'].shape[0] != times.shape[0]:
z = d['z'].transpose()
vel_east = d['vel_east'].transpose()
vel_north = d['vel_north'].transpose()
vel_up = d['vel_up'].transpose()
else:
z = d['z']
vel_east = d['vel_east']
vel_north = d['vel_north']
vel_up = d['vel_up']
else:
times = np.hstack([times,d['times']])
depth = np.hstack([depth,d['depth']])
height = np.hstack([height,d['height']])
depAvg_U = np.hstack([depAvg_U,d['depAvg_U']])
depAvg_V = np.hstack([depAvg_V,d['depAvg_V']])
if 'z' in d.keys():
if d['vel_east'].shape[0] != times.shape[0]:
z = np.vstack([z,d['z'].transpose()])
vel_east = np.vstack([vel_east,d['vel_east'].transpose()])
vel_north = np.vstack([vel_north,d['vel_north'].transpose()])
vel_up = np.vstack([vel_up,d['vel_up'].transpose()])
else:
z = np.vstack([z,d['z']])
vel_east = np.vstack([vel_east,d['vel_east']])
vel_north = np.vstack([vel_north,d['vel_north']])
vel_up = np.vstack([vel_up,d['vel_up']])
v,indx = np.unique(times,return_index=True)
mrgdata['times'] = times[indx]
mrgdata['depth'] = depth[indx]
mrgdata['height'] = height[indx]
mrgdata['depAvg_U'] = depAvg_U[indx]
mrgdata['depAvg_V'] = depAvg_V[indx]
if 'z' in d.keys():
mrgdata['z'] = z[indx,:]
mrgdata['vel_east'] = vel_east[indx,:]
mrgdata['vel_north'] = vel_north[indx,:]
mrgdata['vel_up'] = vel_up
save_ocmw_file(datapath,outfile,mrgdata)
return mrgdata
[docs]
def merge_model_daily_poly_files(datapath,srchstr,outfile):
"""
Merge daily model data extracted from within a polygon into a single file for post-processing.
"""
files = getListOfFiles(datapath,srchstr+'*'+ocmwExtn)
mrgdata = {}
for i,f in enumerate(files):
d = load_ocmw_file(datapath,f)
if i == 0:
titleStr = 'Merged location data - '+datapath.split('/')[-2]+' model'
mrgdata['globalAttributes'] = generateGlobalAttributes(titleStr)
if 'dataLoc' in d.keys():
mrgdata['dataLoc'] = d['dataLoc']
if 'nodesLoc' in d.keys():
mrgdata['dataLoc'] = d['nodesLoc']
if 'crs' in d.keys():
mrgdata['crs'] = d['crs']
else:
mrgdata['crs'] = 'EPSG:32630'
if 'nodes' in d.keys():
mrgdata['meshNode'] = d['nodes']
mrgdata['timeUnits'] = d['timeUnits']
mrgdata['epoch'] = d['epoch']
times = d['times']
depth = d['depth']
height = d['height']
depAvg_U = d['depAvg_U']
depAvg_V = d['depAvg_V']
if 'z' in d.keys():
z = d['z']
vel_east = d['vel_east']
vel_north = d['vel_north']
vel_up = d['vel_up']
else:
times = np.hstack([times,d['times']])
depth = np.concatenate([depth,d['depth']],axis=1)
height = np.concatenate([height,d['height']],axis=1)
depAvg_U = np.concatenate([depAvg_U,d['depAvg_U']],axis=1)
depAvg_V = np.concatenate([depAvg_V,d['depAvg_V']],axis=1)
if 'z' in d.keys():
z = np.concatenate([z,d['z']],axis=1)
vel_east = np.concatenate([vel_east,d['vel_east']],axis=1)
vel_north = np.concatenate([vel_north,d['vel_north']],axis=1)
vel_up = np.concatenate([vel_up,d['vel_up']],axis=1)
v,indx = np.unique(times,return_index=True)
mrgdata['times'] = times[indx]
mrgdata['depth'] = depth[:,indx]
mrgdata['height'] = height[:,indx]
mrgdata['depAvg_U'] = depAvg_U[:,indx]
mrgdata['depAvg_V'] = depAvg_V[:,indx]
if 'z' in d.keys():
mrgdata['z'] = z[:,indx,:]
mrgdata['vel_east'] = vel_east[:,indx,:]
mrgdata['vel_north'] = vel_north[:,indx,:]
mrgdata['vel_up'] = vel_up[:,indx,:]
save_ocmw_file(datapath,outfile,mrgdata)
return mrgdata
# ----------------------------------------------------------------------------
# MAIN PROCESS
# ----------------------------------------------------------------------------
#--------------------------------------------------------------------------
# INTERFACE
#--------------------------------------------------------------------------