Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move ocean and visualization conda-package scripts #597

Merged
merged 5 commits into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions conda_package/docs/ocean/moc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,14 @@ In this example, only the ``mesh.nc`` file is required as an input. The
resulting ``xarray.Dataset`` contains both the basin and southern-transect
masks.

A command-line tool ``moc_southern_boundary_extractor.py`` is also available
A command-line tool ``moc_southern_boundary_extractor`` is also available
for this purpose:

.. code-block:: none

$ moc_southern_boundary_extractor.py --help
$ moc_southern_boundary_extractor --help

usage: moc_southern_boundary_extractor.py [-h] -f IN_FILE -m MESH_FILE -o
usage: moc_southern_boundary_extractor [-h] -f IN_FILE -m MESH_FILE -o
OUT_FILE

This script takes a mesh file (-m flag) and a file with MOC regions masks
Expand All @@ -92,9 +92,6 @@ for this purpose:
is applied only to vertices and edges, not cells, because the need for southern
boundary transect data on cells is not foreseen.

Author: Xylar Asay-Davis
last modified: 5/22/2018

optional arguments:
-h, --help show this help message and exit
-f IN_FILE, --in_file IN_FILE
Expand Down
4 changes: 2 additions & 2 deletions conda_package/docs/visualization.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ ParaVeiw, meaning each cell has the correct polygonal geometry and will be
visualized with a single, constant value for a given field. The extractor,
which is available either through the
:py:func:`mpas_tools.viz.paraview_extractor.extract_vtk()` function or the
``paraview_vtk_field_extractor.py`` command-line interface, can also be used to
``paraview_vtk_field_extractor`` command-line interface, can also be used to
visualize data on MPAS vertices (visualized on triangles) and edges (visualized
on quadrilaterals).

Expand Down Expand Up @@ -128,7 +128,7 @@ The same extraction could be accomplished with the command-line tool as follows:

.. code-block:: none

$ paraview_vtk_field_extractor.py \
$ paraview_vtk_field_extractor \
-f "analysis_members/mpaso.hist.am.timeSeriesStatsDaily.*.nc" \
-v timeDaily_avg_activeTracers_temperature -d nVertLevels=0 \
-m init.nc -o vtk_files --xtime=xtime_startDaily
Expand Down
122 changes: 117 additions & 5 deletions conda_package/mpas_tools/ocean/coastline_alteration.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from __future__ import absolute_import, division, print_function, \
unicode_literals
import argparse

import numpy
import xarray
Expand Down Expand Up @@ -35,10 +34,43 @@ def add_critical_land_blockages(dsMask, dsBlockages):
return dsMask


def main_add_critical_land_blockages():
"""
Entry point for add_critical_land_blockages command-line tool
"""
description = """
Add transects that identify critical regions where narrow strips of land block
ocean flow. These are, essentially, the opposite of critical passages, which
must remain open for ocean flow.
"""
parser = \
argparse.ArgumentParser(description=description,
formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument("-f", "--input_mask_file", dest="input_mask_filename",
help="Mask file that includes cell and edge masks.",
metavar="INPUTMASKFILE", required=True)
parser.add_argument("-o", "--output_mask_file",
dest="output_mask_filename",
help="Mask file that includes cell and edge masks.",
metavar="OUTPUTMASKFILE", required=True)
parser.add_argument("-b", "--blockage_file", dest="blockage_file",
help="Masks for each transect identifying critical "
"land blockage.", metavar="BLOCKFILE",
required=True)
args = parser.parse_args()

dsMask = xarray.open_dataset(args.input_mask_filename)

dsBlockages = xarray.open_dataset(args.blockage_file)

dsMask = add_critical_land_blockages(dsMask, dsBlockages)
dsMask.to_netcdf(args.output_mask_filename)


def widen_transect_edge_masks(dsMask, dsMesh, latitude_threshold=43.0):
"""
Alter critical passages at polar latitudes to be at least two cells wide, to
avoid sea ice blockage
Alter critical passages at polar latitudes to be at least two cells wide,
to avoid sea ice blockage

Parameters
----------
Expand Down Expand Up @@ -78,6 +110,44 @@ def widen_transect_edge_masks(dsMask, dsMesh, latitude_threshold=43.0):
return dsMask


def main_widen_transect_edge_masks():
"""
Entry point for widen_transect_edge_masks command-line tool
"""
description = """
Alter transects to be at least two cells wide. This is used for critical
passages, to avoid sea ice blockage. Specifically, mark cells on both sides
of each transect edge mask as a water cell.
"""
parser = \
argparse.ArgumentParser(description=description,
formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument("-f", "--mask_file", dest="mask_filename",
help="Mask file with cell and edge transect masks.",
metavar="MASKFILE",
required=True)
parser.add_argument("-m", "--mesh_file", dest="mesh_filename",
help="MPAS Mesh filename.", metavar="MESHFILE",
required=True)
parser.add_argument("-o", "--out_file", dest="out_filename",
help="Output mask file,different from input filename.",
metavar="MASKFILE",
required=True)
parser.add_argument("-l", "--latitude_threshold",
dest="latitude_threshold",
help="Minimum latitude, degrees, for transect "
"widening.",
required=False, type=float, default=43.0)
args = parser.parse_args()

dsMask = xarray.open_dataset(args.mask_filename)

dsMesh = xarray.open_dataset(args.mesh_filename)

dsMask = widen_transect_edge_masks(dsMask, dsMesh, args.latitude_threshold)
dsMask.to_netcdf(args.out_filename)


def add_land_locked_cells_to_mask(dsMask, dsMesh, latitude_threshold=43.0,
nSweeps=10):
"""
Expand Down Expand Up @@ -143,6 +213,48 @@ def add_land_locked_cells_to_mask(dsMask, dsMesh, latitude_threshold=43.0,
return dsMask


def main_add_land_locked_cells_to_mask():
"""
Entry point for add_land_locked_cells_to_mask command-line tool
"""
description = """
Find ocean cells that are land-locked, and alter the cell
mask so that they are counted as land cells.
"""
parser = \
argparse.ArgumentParser(description=description,
formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument("-f", "--input_mask_file", dest="input_mask_filename",
help="Mask file that includes cell and edge masks.",
metavar="INPUTMASKFILE", required=True)
parser.add_argument("-o", "--output_mask_file",
dest="output_mask_filename",
help="Mask file that includes cell and edge masks.",
metavar="OUTPUTMASKFILE", required=True)
parser.add_argument("-m", "--mesh_file", dest="mesh_filename",
help="MPAS Mesh filename.", metavar="MESHFILE",
required=True)
parser.add_argument("-l", "--latitude_threshold",
dest="latitude_threshold",
help="Minimum latitude, in degrees, for transect "
"widening.",
required=False, type=float, default=43.0)
parser.add_argument("-n", "--number_sweeps", dest="nSweeps",
help="Maximum number of sweeps to search for "
"land-locked cells.",
required=False, type=int, default=10)
args = parser.parse_args()

dsMask = xarray.open_dataset(args.input_mask_filename)

dsMesh = xarray.open_dataset(args.mesh_filename)

dsMask = add_land_locked_cells_to_mask(dsMask, dsMesh,
args.latitude_threshold,
args.nSweeps)
dsMask.to_netcdf(args.output_mask_filename)


def _remove_cells_with_isolated_edges1(dsMask, dsMesh, landMask,
latitude_threshold):
print("Step 1: Searching for land-locked cells. Remove cells that only "
Expand Down Expand Up @@ -307,7 +419,7 @@ def _flood_fill(dsMask, dsMesh, landMask, removable):
filledNeighbors = numpy.logical_and(neighbors >= 0,
floodFill[neighbors] == 1)
fillIndices = cellIndices[filledNeighbors.values]
if(len(fillIndices) > 0):
if len(fillIndices) > 0:
floodFill[fillIndices] = 1
newFloodCellsThisSweep += len(fillIndices)

Expand Down
57 changes: 46 additions & 11 deletions conda_package/mpas_tools/ocean/moc.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
from __future__ import absolute_import, division, print_function, \
unicode_literals
import argparse
import logging
import sys

import xarray
import numpy
import logging
import sys
from geometric_features.aggregation.ocean import moc

import mpas_tools.mesh.conversion
Expand Down Expand Up @@ -88,8 +87,8 @@ def add_moc_southern_boundary_transects(dsMask, dsMesh, logger=None):
Returns
-------
dsMask : ``xarray.Dataset``
Region masks defining MOC basins and the corresponding southern-boundary
transects
Region masks defining MOC basins and the corresponding
southern-boundary transects
"""

useStdout = logger is None
Expand All @@ -113,6 +112,41 @@ def add_moc_southern_boundary_transects(dsMask, dsMesh, logger=None):
return dsMask


def moc_southern_boundary_extractor():
"""
Entry point for moc_southern_boundary_extractor command-line tool
"""
description = """
This script takes a mesh file (-m flag) and a file with MOC regions masks
(-f flag) produce by the MPAS mask creator. The script produces a copy of
the contents of the MOC mask file, adding transects that mark the southern
boundary of each region in a file indicated with the -o flag. The transect
is applied only to vertices and edges, not cells, because the need for southern
boundary transect data on cells is not foreseen.
"""
parser = \
argparse.ArgumentParser(description=description,
formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument('-f', '--in_file', dest='in_file',
help='Input file with MOC masks', metavar='IN_FILE',
required=True)
parser.add_argument('-m', '--mesh_file', dest='mesh_file',
help='Input mesh file', metavar='MESH_FILE',
required=True)
parser.add_argument('-o', '--out_file', dest='out_file',
help='Output file for MOC masks and southern-boundary '
'transects', metavar='OUT_FILE',
required=True)
args = parser.parse_args()

dsMasks = xarray.open_dataset(args.in_file)
dsMesh = xarray.open_dataset(args.mesh_file)

dsMasksAndTransects = add_moc_southern_boundary_transects(dsMasks, dsMesh)

write_netcdf(dsMasksAndTransects, args.out_file)


def _extract_southern_boundary(mesh, mocMask, latBuffer, logger):
"""
Extracts the southern boundary of each region mask in mocMask. Mesh info
Expand All @@ -125,7 +159,7 @@ def _extract_southern_boundary(mesh, mocMask, latBuffer, logger):
nEdges = mesh.sizes['nEdges']

nRegions = mocMask.sizes['nRegions']
assert(mocMask.sizes['nCells'] == nCells)
assert mocMask.sizes['nCells'] == nCells

# convert to python zero-based indices
cellsOnEdge = mesh.variables['cellsOnEdge'].values-1
Expand Down Expand Up @@ -198,7 +232,7 @@ def _extract_southern_boundary(mesh, mocMask, latBuffer, logger):
startIndices = numpy.arange(1, len(edgeSequence))[belowToAbove]
endIndices = numpy.arange(1, len(edgeSequence))[aboveToBelow]

assert(len(startIndices) == len(endIndices))
assert len(startIndices) == len(endIndices)

if len(startIndices) == 0:
# the whole sequence is the southern boundary
Expand Down Expand Up @@ -232,7 +266,8 @@ def _extract_southern_boundary(mesh, mocMask, latBuffer, logger):


def _add_transects_to_moc(mesh, mocMask, southernBoundaryEdges,
southernBoiundaryEdgeSigns, southernBoundaryVertices):
southernBoiundaryEdgeSigns,
southernBoundaryVertices):
"""
Creates transect fields in mocMask from the edges, edge signs and
vertices defining the southern boundaries. Mesh info (nEdges and
Expand Down Expand Up @@ -354,7 +389,7 @@ def _get_edge_sequence_on_boundary(startEdge, edgeSign, edgesOnVertex,
edgeSequence = []
vertexSequence = []
while True:
assert(edgeSign[iEdge] == 1. or edgeSign[iEdge] == -1.)
assert edgeSign[iEdge] == 1. or edgeSign[iEdge] == -1.
if edgeSign[iEdge] == 1.:
v = 0
else:
Expand All @@ -369,7 +404,7 @@ def _get_edge_sequence_on_boundary(startEdge, edgeSign, edgesOnVertex,
if edge != -1 and edge != iEdge and edgeSign[edge] != 0:
nextEdge = edge
break
assert(nextEdge != -1)
assert nextEdge != -1

edgeSequence.append(iEdge)
vertexSequence.append(iVertex)
Expand Down
10 changes: 4 additions & 6 deletions conda_package/recipe/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@
set -x
set -e

cp -r ocean landice visualization mesh_tools conda_package

cd conda_package
${PYTHON} -m pip install . --no-deps --no-build-isolation -vv

# build and install ocean topography smoothing tool
cd ${SRC_DIR}/conda_package/ocean/smooth_topo
cd ${SRC_DIR}/ocean/smooth_topo
Comment on lines -12 to +10
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand the changes in this file and how they relate to the main objective of the PR, but I'm sure that's just because of my relative conda package ignorance.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We were copying the ocean and several other directories into the conda_package directory so the tools found there could be included in the conda package. A major purpose of this PR is to no longer make those copies but rather to require that the conda package takes no python code from outside the conda_package directory. So that change is on purpose.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can still build the C++ and Fortran tools that are outside of conda_package but we need to point to them where they are, not where they used to be copied to.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes total sense, thanks!

mkdir build
cd build
cmake \
Expand All @@ -20,7 +18,7 @@ cmake --build .
cmake --install .

# build and install sea ice partitioning tool
cd ${SRC_DIR}/conda_package/mesh_tools/seaice_grid_tools
cd ${SRC_DIR}/mesh_tools/seaice_grid_tools
mkdir build
cd build
cmake \
Expand All @@ -31,7 +29,7 @@ cmake --build .
cmake --install .

# build and install legacy mask creator
cd ${SRC_DIR}/conda_package/mesh_tools/mesh_conversion_tools
cd ${SRC_DIR}/mesh_tools/mesh_conversion_tools
mkdir build
cd build
cmake \
Expand All @@ -42,7 +40,7 @@ cmake --build .
cp MpasMaskCreator.x ${PREFIX}/bin

# build and install mesh conversion tools
cd ${SRC_DIR}/conda_package/mesh_tools/mesh_conversion_tools_netcdf_c
cd ${SRC_DIR}/mesh_tools/mesh_conversion_tools_netcdf_c
mkdir build
cd build
cmake \
Expand Down
Loading
Loading