Commit 616133fb authored by Mike Bedington's avatar Mike Bedington

Merge branch 'dev' of gitlab.ecosystem-modelling.pml.ac.uk:fvcom/pyfvcom into dev

parents 257e1649 7e8e66bb
Pipeline #777 failed with stage
......@@ -645,9 +645,6 @@ class OpenBoundary:
coarse_depths = np.tile(coarse.grid.depth, [coarse.dims.lat, coarse.dims.lon, 1]).transpose(2, 0, 1)
coarse_depths = np.ma.masked_array(coarse_depths, mask=getattr(coarse.data, coarse_name)[0, ...].mask)
coarse_depths = np.max(coarse_depths, axis=0)
# Fix all depths which are shallower than the shallowest coarse depth. This is more straightforward as
# it's a single minimum across all the open boundary positions.
z[z < coarse.grid.depth.min()] = coarse.grid.depth.min()
# Go through each open boundary position and if its depth is deeper than the closest coarse data,
# squash the open boundary water column into the coarse water column.
for idx, node in enumerate(zip(x, y, z)):
......@@ -657,6 +654,9 @@ class OpenBoundary:
# Squash the FVCOM water column into the coarse water column.
# TODO: Is the sign of the offset right here?
z[idx, :] = (node[2] / node[2].max()) * coarse_depths[lat_index, lon_index] - 1 # offset by a bit
# Fix all depths which are shallower than the shallowest coarse depth. This is more straightforward as
# it's a single minimum across all the open boundary positions.
z[z < coarse.grid.depth.min()] = coarse.grid.depth.min()
# Make arrays of lon, lat, depth and time. Need to make the coordinates match the coarse data shape and then
# flatten the lot. We should be able to do the interpolation in one shot this way, but we have to be
......
......@@ -933,8 +933,9 @@ class Model(Domain):
from PML's Western Channel Observatory L4 buoy data. These are: 'Z4_c', 'Z5c', 'Z5n', 'Z5p', 'Z6c', 'Z6n' and
'Z6p'.
If `sediment' is True, then the variables in the sediment are added. Cohesive sediments are expected to have names like
'mud_*' and non-cohesive sediments names like 'sand_*'.
If `sediment' is supplied, then the variables in the sediment are added. Cohesive sediments are expected to have
names like 'mud_*' and non-cohesive sediments names like 'sand_*'.
TO DO: Add Regs formula for calculating spm from flux
"""
......@@ -1108,7 +1109,7 @@ class Model(Domain):
# Now drop all those indices from the relevant river data.
for field in self.obj_iter(self.river):
if field != 'time':
setattr(self.river, field, np.delete(getattr(self.river, field), self.__flatten_list(boundary_river_indices), axis=-1))
setattr(self.river, field, np.delete(getattr(self.river, field), flatten_list(boundary_river_indices), axis=-1))
# Update the dimension too.
self.dims.river -= len(boundary_river_indices)
......@@ -1163,7 +1164,7 @@ class Model(Domain):
- O3_c : dissolved inorganic carbon [time, river]
- O3_bioalk : bio-alkalinity [time, river]
- Z4_c : mesozooplankton carbon [time, river]
If using sediments then any objects of the self.river whos name matches 'mud_*' or 'sand_*' will be added
If using sediments then any objects of the self.river whose name matches 'mud_*' or 'sand_*' will be added
to the output.
Uses self.river.source for the 'title' global attribute in the netCDF and self.river.history for the 'info'
......@@ -1250,16 +1251,19 @@ class Model(Domain):
if muddy_sediment_names:
for this_sediment in muddy_sediment_names:
atts = {'long_name': '{} - muddy stuff'.format(this_sediment), 'units': 'kgm^-3'}
river.add_variable(this_sediment, getattr(self.river, this_sediment), ['time', 'rivers'], attributes=atts, ncopts=ncopts)
river.add_variable(this_sediment, getattr(self.river, this_sediment), ['time', 'rivers'],
attributes=atts, ncopts=ncopts)
if sandy_sediment_names:
for this_sediment in sandy_sediment_names:
atts = {'long_name': '{} - sandy stuff'.format(this_sediment), 'units': 'kgm^-3'}
river.add_variable(this_sediment, getattr(self.river, this_sediment), ['time', 'rivers'], attributes=atts, ncopts=ncopts)
river.add_variable(this_sediment, getattr(self.river, this_sediment), ['time', 'rivers'],
attributes=atts, ncopts=ncopts)
def write_river_namelist(self, output_file, forcing_file, vertical_distribution='uniform'):
"""
Write an FVCOM river namelist file.
Parameters
----------
......@@ -1276,12 +1280,13 @@ class Model(Domain):
f.write(' &NML_RIVER\n')
f.write(' RIVER_NAME = ''{}'',\n'.format(self.river.names[ri]))
f.write(' RIVER_FILE = ''{}'',\n'.format(forcing_file))
f.write(' RIVER_GRID_LOCATION = {:d},\n'.format(self.river.node[ri]))
f.write(' RIVER_GRID_LOCATION = {:d},\n'.format(self.river.node[ri] + 1))
f.write(' RIVER_VERTICAL_DISTRIBUTION = {}\n'.format(vertical_distribution))
f.write(' /\n')
def read_nemo_rivers(self, nemo_file, remove_baltic=True):
"""
Read a NEMO river netCDF file.
Parameters
----------
......@@ -1559,31 +1564,39 @@ class Model(Domain):
f.write(' PROBE_VAR_NAME = "{}"\n'.format(long_name))
f.write('/\n')
def read_regular(self, regular, variables):
"""
Read regularly gridded model data and provides a RegularReader object which mimics a FileReader object.
def read_regular(self, *args, **kwargs):
read_regular.__doc__
self.regular = read_regular(*args, noisy=self.noisy, **kwargs)
Parameters
----------
regular : str, pathlib.Path
Files to read.
variables : list
Variables to extract. Variables missing in the files raise an error.
Provides
--------
A RegularReader object with the requested variables loaded.
def read_regular(regular, variables, noisy=False):
"""
Read regularly gridded model data and provides a RegularReader object which mimics a FileReader object.
"""
Parameters
----------
regular : str, pathlib.Path
Files to read.
variables : list
Variables to extract. Variables missing in the files raise an error.
noisy : bool, optional
Set to True to enable verbose output. Defaults to False.
for ii, file in enumerate(regular):
if self.noisy:
print('Loading file {}'.format(file))
if ii == 0:
self.regular = RegularReader(str(file), variables=variables)
else:
self.regular += RegularReader(str(file), variables=variables)
Provides
--------
A RegularReader object with the requested variables loaded.
"""
for ii, file in enumerate(regular):
if noisy:
print('Loading file {}'.format(file))
if ii == 0:
regular = RegularReader(str(file), variables=variables)
else:
regular += RegularReader(str(file), variables=variables)
return regular
class WriteForcing:
""" Create an FVCOM netCDF input file. """
......@@ -1654,7 +1667,7 @@ class WriteForcing:
Parameters
----------
time : np.ndarray, list, tuple
Times as date time objects.
Times as datetime objects.
"""
......
......@@ -774,13 +774,15 @@ class FileReader(Domain):
return time_idx
def MFileReader(fvcom, *args, **kwargs):
def MFileReader(fvcom, noisy=False, *args, **kwargs):
""" Wrapper around FileReader for loading multiple files at once.
Parameters
----------
fvcom : list-like, str
List of files to load.
noisy : bool, optional
Set to True to write out the name of each file being loaded.
Additional arguments are passed to `PyFVCOM.read.FileReader'.
......@@ -792,9 +794,13 @@ def MFileReader(fvcom, *args, **kwargs):
"""
if isinstance(fvcom, str):
if noisy:
print('Loading {}'.format(fvcom))
FVCOM = FileReader(fvcom, *args, **kwargs)
else:
for file in fvcom:
if noisy:
print('Loading {}'.format(file))
if file == fvcom[0]:
FVCOM = FileReader(file, *args, **kwargs)
else:
......
This diff is collapsed.
import itertools
import numpy as np
import itertools
def fix_range(a, nmin, nmax):
"""
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment