Skip to content

Commit dd86f4e

Browse files
committed
Merge PR #586 'xylar/ocean/compass_add_local_passages' into ocean/develop
Add support for custom critical passages and land blockages #586 This is added to support potential addition of "custom" passages or blockages in #555 and #584. The custom transects could come from a local file or it could be pulled in from geometric_features, e.g. with the merge_features command.
2 parents aaaa69e + 2261d50 commit dd86f4e

File tree

1 file changed

+68
-35
lines changed
  • testing_and_setup/compass/ocean/global_ocean/scripts

1 file changed

+68
-35
lines changed

testing_and_setup/compass/ocean/global_ocean/scripts/cull_mesh.py

Lines changed: 68 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,11 @@
2424
from __future__ import absolute_import, division, print_function, \
2525
unicode_literals
2626

27-
import os
2827
from optparse import OptionParser
2928
import xarray
3029

31-
from geometric_features import GeometricFeatures
30+
from geometric_features import GeometricFeatures, FeatureCollection, \
31+
read_feature_collection
3232
from mpas_tools import conversion
3333
from mpas_tools.io import write_netcdf
3434
from mpas_tools.ocean.coastline_alteration import widen_transect_edge_masks, \
@@ -37,16 +37,41 @@
3737

3838

3939
parser = OptionParser()
40-
parser.add_option("--with_cavities", action="store_true", dest="with_cavities")
40+
parser.add_option("--with_cavities", action="store_true", dest="with_cavities",
41+
help="Whether the mesh should include Antarctic ice-shelf"
42+
" cavities")
4143
parser.add_option("--with_critical_passages", action="store_true",
42-
dest="with_critical_passages")
44+
dest="with_critical_passages",
45+
help="Whether the mesh should open the standard critical "
46+
"passages and close land blockages from "
47+
"geometric_features")
48+
parser.add_option(
49+
"--custom_critical_passages",
50+
dest="custom_critical_passages",
51+
help="A geojson file with critical passages to open. This "
52+
"file may be supplied in addition to or instead of "
53+
"the default passages (--with_critical_passages)")
54+
parser.add_option(
55+
"--custom_land_blockages",
56+
dest="custom_land_blockages",
57+
help="A geojson file with critical land blockages to close. "
58+
"This file may be supplied in addition to or instead of "
59+
"the default blockages (--with_critical_passages)")
4360
parser.add_option("--preserve_floodplain", action="store_true",
44-
dest="preserve_floodplain", default=False)
61+
dest="preserve_floodplain", default=False,
62+
help="Whether to use the cellSeedMask field in the base "
63+
"mesh to preserve a floodplain at elevations above z=0")
4564
options, args = parser.parse_args()
4665

4766
# required for compatibility with MPAS
4867
netcdfFormat = 'NETCDF3_64BIT'
4968

69+
critical_passages = options.with_critical_passages or \
70+
(options.custom_critical_passages is not None)
71+
72+
land_blockages = options.with_critical_passages or \
73+
(options.custom_land_blockages is not None)
74+
5075
gf = GeometricFeatures()
5176

5277
# start with the land coverage from Natural Earth
@@ -88,10 +113,37 @@
88113
fcSeed = gf.read(componentName='ocean', objectType='point',
89114
tags=['seed_point'])
90115

91-
if options.with_critical_passages:
92-
# merge transects for critical passages into critical_passages.geojson
93-
fcCritPassages = gf.read(componentName='ocean', objectType='transect',
94-
tags=['Critical_Passage'])
116+
if land_blockages:
117+
if options.with_critical_passages:
118+
# merge transects for critical land blockages into
119+
# critical_land_blockages.geojson
120+
fcCritBlockages = gf.read(componentName='ocean', objectType='transect',
121+
tags=['Critical_Land_Blockage'])
122+
else:
123+
fcCritBlockages = FeatureCollection()
124+
125+
if options.custom_land_blockages is not None:
126+
fcCritBlockages.merge(read_feature_collection(
127+
options.custom_land_blockages))
128+
129+
# create masks from the transects
130+
dsCritBlockMask = conversion.mask(dsBaseMesh, fcMask=fcCritBlockages)
131+
132+
dsLandMask = add_critical_land_blockages(dsLandMask, dsCritBlockMask)
133+
134+
fcCritPassages = FeatureCollection()
135+
dsPreserve = []
136+
137+
if critical_passages:
138+
if options.with_critical_passages:
139+
# merge transects for critical passages into critical_passages.geojson
140+
fcCritPassages.merge(gf.read(componentName='ocean',
141+
objectType='transect',
142+
tags=['Critical_Passage']))
143+
144+
if options.custom_critical_passages is not None:
145+
fcCritPassages.merge(read_feature_collection(
146+
options.custom_critical_passages))
95147

96148
# create masks from the transects
97149
dsCritPassMask = conversion.mask(dsBaseMesh, fcMask=fcCritPassages)
@@ -101,33 +153,15 @@
101153
dsCritPassMask = widen_transect_edge_masks(dsCritPassMask, dsBaseMesh,
102154
latitude_threshold=43.0)
103155

104-
# merge transects for critical land blockages into
105-
# critical_land_blockages.geojson
106-
fcCritBlockages = gf.read(componentName='ocean', objectType='transect',
107-
tags=['Critical_Land_Blockage'])
108-
109-
# create masks from the transects for critical land blockages
110-
dsCritBlockMask = conversion.mask(dsBaseMesh, fcMask=fcCritBlockages)
111-
112-
dsLandMask = add_critical_land_blockages(dsLandMask, dsCritBlockMask)
156+
dsPreserve.append(dsCritPassMask)
113157

114-
# Cull the mesh based on the land mask while keeping critical passages open
115-
if options.preserve_floodplain:
116-
dsCulledMesh = conversion.cull(dsBaseMesh, dsMask=dsLandMask,
117-
dsPreserve=[dsCritPassMask, dsBaseMesh])
118-
else:
119-
dsCulledMesh = conversion.cull(dsBaseMesh, dsMask=dsLandMask,
120-
dsPreserve=dsCritPassMask)
158+
if options.preserve_floodplain:
159+
dsPreserve.append(dsBaseMesh)
121160

122-
else:
123161

124-
# cull the mesh based on the land mask
125-
if options.preserve_floodplain:
126-
dsCulledMesh = conversion.cull(dsBaseMesh, dsMask=dsLandMask,
127-
dsPreserve=dsBaseMesh)
128-
else:
129-
dsCulledMesh = conversion.cull(dsBaseMesh, dsMask=dsLandMask)
130-
fcCritPassages = None
162+
# cull the mesh based on the land mask
163+
dsCulledMesh = conversion.cull(dsBaseMesh, dsMask=dsLandMask,
164+
dsPreserve=dsPreserve)
131165

132166
# create a mask for the flood fill seed points
133167
dsSeedMask = conversion.mask(dsCulledMesh, fcSeed=fcSeed)
@@ -137,7 +171,7 @@
137171
graphInfoFileName='culled_graph.info')
138172
write_netcdf(dsCulledMesh, 'culled_mesh.nc', format=netcdfFormat)
139173

140-
if options.with_critical_passages:
174+
if critical_passages:
141175
# make a new version of the critical passages mask on the culled mesh
142176
dsCritPassMask = conversion.mask(dsCulledMesh, fcMask=fcCritPassages)
143177
write_netcdf(dsCritPassMask, 'critical_passages_mask_final.nc',
@@ -167,4 +201,3 @@
167201
variable_list=['allOnCells'],
168202
filename_pattern='no_ISC_culled_mesh.nc',
169203
out_dir='no_ISC_culled_mesh_vtk')
170-

0 commit comments

Comments
 (0)