This repository has been archived on 2022-02-01. You can view files and clone it, but cannot push or open issues or pull requests.
openfoam_project/bathymetry/generate/__main__.py

235 lines
6.0 KiB
Python

from pprint import pp
import logging
import configparser
import pathlib
import subprocess
from time import time
import pandas as pd
import numpy as np
from scipy.interpolate import griddata
_t0 = time()
config = configparser.ConfigParser()
config.read('config.ini')
if config['main']['plot'] == 'True': import matplotlib.pyplot as plt
logging.basicConfig(level=config['main']['logging'])
log = logging.getLogger('bathymetry')
# --- Initialization
log.info('Initialization')
folders = {
'data': pathlib.Path(config['data']['root']),
'scad': pathlib.Path(config['scad']['root']),
'stl': pathlib.Path(config['stl']['root']),
'pandas': pathlib.Path(config['pandas']['root']),
}
if config.getboolean('fig', 'enable', fallback=False):
folders['fig'] = pathlib.Path(config.get('fig', 'root'))
for path in folders.values():
path.mkdir(exist_ok=True)
bathy = pd.read_csv(
folders['data'].joinpath(config['data']['bathy']),
sep=' ',
names=('lon', 'lat', 'z'),
)
artha = pd.read_csv(
folders['data'].joinpath(config['data']['artha']),
)
earth_radius = 6371e3
L0 = float(config['main']['L0'])
L1 = float(config['main']['L1'])
direction = float(config['main']['dir'])
artha = pd.concat((artha, pd.DataFrame([
{
'lat': artha.lat.at[0] \
+ np.cos(direction*np.pi/180) * L0/earth_radius * 180/np.pi,
'lon': artha.lon.at[0] \
+ np.sin(direction*np.pi/180) * L0/earth_radius * 180/np.pi \
/ np.cos(artha.lat.at[0] * np.pi/180),
},
{
'lat': artha.lat.at[0] \
- np.cos(direction*np.pi/180) * L1/earth_radius * 180/np.pi,
'lon': artha.lon.at[0] \
- np.sin(direction*np.pi/180) * L1/earth_radius * 180/np.pi \
/ np.cos(artha.lat.at[0] * np.pi/180),
},
], index=[-1, 1])))
# --- Interpolation
log.info('Interpolating data')
N = int(config['main']['N'])
line = pd.DataFrame({
'x': np.linspace(0, L0+L1, N),
'lat': np.linspace(artha.lat.at[-1], artha.lat.at[1], N),
'lon': np.linspace(artha.lon.at[-1], artha.lon.at[1], N),
})
line.set_index('x', inplace=True)
line['z'] = griddata(
bathy[['lon','lat']],
bathy.z,
line[['lon','lat']],
method='linear',
)
# --- Adding blocs
log.info('Adding blocs')
b = config['data']['blocs'].split(',')
blocs = pd.Series([
pd.read_csv(
folders['data'].joinpath(path),
index_col='x',
) for path in b
])
for bloc in blocs:
bloc.index = L0 - bloc.index
#line.z = all_blocs.z.fillna(line.z)
lim = float(config['main']['bathy_max'])
bathy_line = line.z.copy()
#bathy_line = line.z.clip(upper=lim)
bathy_line = bathy_line[(bathy_line.index - L0 < -10) | (bathy_line.index - L0 > 0)]
bathy_line.index = np.where((bathy_line > lim) & (bathy_line.index < L0), bathy_line.index + 10, bathy_line.index)
rubble_line = line.z[(line.z > lim) & (line.index < L0)]
data_dict = {}
for i in range(blocs.size):
data_dict[f'bloc{i}'] = blocs.iat[i].reset_index().values
for name, data in (
('bathy', bathy_line),
('rubble', rubble_line),
):
data_dict[name] = np.concatenate((
data.reset_index().values,
[[data.index.max(), data.min()],
[data.index.min(),data.min()]]
))
# --- Generating SCAD
with open(folders['data'].joinpath(config['data']['base_scad'])) as bsf:
base_scad = bsf.read()
for (name, data) in data_dict.items():
log.info(f'Generating {name}')
log.info('\tGenerating SCAD file')
scad_file = folders['scad'].joinpath(f'{name}.scad')
with open(scad_file, 'w') as osf:
osf.write(base_scad.format(
np.array2string(
data,
threshold=np.inf,
separator=','
)
))
log.info('\tGenerating STL file')
subprocess.run(('openscad', scad_file, '-o',
folders['stl'].joinpath(f'{name}.stl')),
check=True,
capture_output=True)
# --- Saving pandas
log.info('Saving Pandas')
with pd.HDFStore(
folders['pandas'].joinpath(config['pandas']['file']),
mode='w',
complib='blosc',
) as hdf:
for name, data in (
('bathy', bathy_line),
('rubble', rubble_line),
):
hdf.put(name, data)
for i, bloc in blocs.items():
hdf.put(f'bloc{i}', bloc)
_t1 = time()
log.info(f'Program ended successfully after {_t1-_t0:.2f}s')
# --- Plotting
if config['main']['plot'] == 'True':
log.info('Plotting data')
flt = (
((bathy.lon-artha.lon.at[0]).abs() < 0.002) & \
((bathy.lat-artha.lat.at[0]).abs() < 0.002)
)
fig, ax = plt.subplots()
c = ax.tricontourf(
bathy.lon[flt],
bathy.lat[flt],
bathy.z[flt],
#marker='1',
#lw=1,
)
fig.colorbar(c, label='Altitude (m)')
ax.plot(
artha.lon,
artha.lat,
color='k',
marker='+',
lw=1,
label='Studied domain',
)
ax.legend()
ax.grid(alpha=.2)
ax.set(
xlabel='Longitude (°)',
ylabel='Latitude (°)',
aspect='equal',
)
if config.getboolean('fig', 'enable', fallback=False):
fig.savefig(folders['fig'].joinpath(
f'map.{config.get("fig", "format")}'))
fig, ax = plt.subplots(figsize=(6,2))
ax.plot(
bathy_line.index,
bathy_line,
color='k',
lw=1,
zorder=10,
label='Bathymetry',
)
ax.plot(
rubble_line.index,
rubble_line,
color='r',
lw=1,
zorder=11,
label='Armour',
)
blocs.apply(lambda bloc: ax.fill_between(
bloc.index,
bloc.z,
color='k',
zorder=12,
#alpha=.1,
))
ax.set(
xlabel='x (m)',
ylabel='y (m)',
aspect='equal',
xlim=(bathy_line.index.min(), bathy_line.index.max()),
)
ax.grid()
ax.legend()
if config.getboolean('fig', 'enable', fallback=False):
fig.savefig(folders['fig'].joinpath(
f'bathy.{config.get("fig", "format")}'))
plt.show(block=True)