Skip to content

Commit fed2fdc

Browse files
authored
Merge pull request #249 from xylar/land_ice_mesh_tools_to_python3
Land ice mesh tools to python 3 Make a few minor formatting changes to the land ice mesh tools so they work in python 3 as well as python 2. I also include mark_horns_for_culling.py because I think this script might be used primarily by the land-ice model.
2 parents ee4b2d8 + f00466a commit fed2fdc

File tree

5 files changed

+164
-149
lines changed

5 files changed

+164
-149
lines changed

landice/mesh_tools_li/create_landice_grid_from_generic_MPAS_grid.py

Lines changed: 34 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
# I've only tested it with a periodic_hex grid, but it should work with any MPAS grid.
44
# Currently variable attributes are not copied (and periodic_hex does not assign any, so this is ok). If variable attributes are added to periodic_hex, this script should be modified to copy them (looping over dir(var), skipping over variable function names "assignValue", "getValue", "typecode").
55

6+
from __future__ import absolute_import, division, print_function, \
7+
unicode_literals
8+
69
import sys, numpy
710
from netCDF4 import Dataset
811
from optparse import OptionParser
@@ -11,7 +14,7 @@
1114

1215
sphere_radius = 6.37122e6 # earth radius, if needed
1316

14-
print "** Gathering information. (Invoke with --help for more details. All arguments are optional)"
17+
print("** Gathering information. (Invoke with --help for more details. All arguments are optional)")
1518
parser = OptionParser()
1619
parser.add_option("-i", "--in", dest="fileinName", help="input filename. Defaults to 'grid.nc'", metavar="FILENAME")
1720
parser.add_option("-o", "--out", dest="fileoutName", help="output filename. Defaults to 'landice_grid.nc'", metavar="FILENAME")
@@ -26,14 +29,14 @@
2629
options, args = parser.parse_args()
2730

2831
if not options.fileinName:
29-
print "No input filename specified, so using 'grid.nc'."
32+
print("No input filename specified, so using 'grid.nc'.")
3033
options.fileinName = 'grid.nc'
3134
else:
32-
print "Input file is:", options.fileinName
35+
print("Input file is: {}".format(options.fileinName))
3336
if not options.fileoutName:
34-
print "No output filename specified, so using 'landice_grid.nc'."
37+
print("No output filename specified, so using 'landice_grid.nc'.")
3538
options.fileoutName = 'landice_grid.nc'
36-
print '' # make a space in stdout before further output
39+
print('') # make a space in stdout before further output
3740

3841
# Get the input file
3942
filein = Dataset(options.fileinName,'r')
@@ -47,27 +50,27 @@
4750
# ============================================
4851
# Do this first as doing it last is slow for big files since adding
4952
# attributes forces the contents to get reorganized.
50-
print "---- Copying global attributes from input file to output file ----"
53+
print("---- Copying global attributes from input file to output file ----")
5154
for name in filein.ncattrs():
5255
# sphere radius needs to be set to that of the earth if on a sphere
5356
if name == 'sphere_radius' and getattr(filein, 'on_a_sphere') == "YES ":
5457
setattr(fileout, 'sphere_radius', sphere_radius)
55-
print 'Set global attribute sphere_radius = ', str(sphere_radius)
58+
print('Set global attribute sphere_radius = {}'.format(sphere_radius))
5659
elif name =='history':
5760
# Update history attribute of netCDF file
5861
newhist = '\n'.join([getattr(filein, 'history'), ' '.join(sys.argv[:]) ] )
5962
setattr(fileout, 'history', newhist )
6063
else:
6164
# Otherwise simply copy the attr
6265
setattr(fileout, name, getattr(filein, name) )
63-
print 'Copied global attribute ', name, '=', getattr(filein, name)
66+
print('Copied global attribute {} = {}'.format(name, getattr(filein, name)))
6467

6568
# Update history attribute of netCDF file if we didn't above
6669
if not hasattr(fileout, 'history'):
6770
setattr(fileout, 'history', sys.argv[:] )
6871

6972
fileout.sync()
70-
print '' # make a space in stdout before further output
73+
print('') # make a space in stdout before further output
7174

7275

7376
# ============================================
@@ -78,7 +81,7 @@
7881
# It may be better to list them explicitly as I do for the grid variables,
7982
# but this way ensures they all get included and is easier.
8083
# Note: The UNLIMITED time dimension will return a dimension value of None with Scientific.IO. This is what is supposed to happen. See below for how to deal with assigning values to a variable with a unlimited dimension. Special handling is needed with the netCDF module.
81-
print "---- Copying dimensions from input file to output file ----"
84+
print("---- Copying dimensions from input file to output file ----")
8285
for dim in filein.dimensions.keys():
8386
if dim == 'nTracers':
8487
pass # Do nothing - we don't want this dimension
@@ -91,12 +94,12 @@
9194
if options.levels is None:
9295
# If nVertLevels is in the input file, and a value for it was not
9396
# specified on the command line, then use the value from the file (do nothing here)
94-
print "Using nVertLevels from the intput file:", len(filein.dimensions[dim])
97+
print("Using nVertLevels from the intput file: {}".format(len(filein.dimensions[dim])))
9598
dimvalue = len(filein.dimensions[dim])
9699
else:
97100
# if nVertLevels is in the input file, but a value WAS specified
98101
# on the command line, then use the command line value
99-
print "Using nVertLevels specified on the command line:", int(options.levels)
102+
print("Using nVertLevels specified on the command line: {}".format(int(options.levels)))
100103
dimvalue = int(options.levels)
101104
else:
102105
dimvalue = len(filein.dimensions[dim])
@@ -105,31 +108,31 @@
105108
# it has not been added to the output file yet. Treat those here.
106109
if 'nVertLevels' not in fileout.dimensions:
107110
if options.levels is None:
108-
print "nVertLevels not in input file and not specified. Using default value of 10."
111+
print("nVertLevels not in input file and not specified. Using default value of 10.")
109112
fileout.createDimension('nVertLevels', 10)
110113
else:
111-
print "Using nVertLevels specified on the command line:", int(options.levels)
114+
print("Using nVertLevels specified on the command line: {}".format(int(options.levels)))
112115
fileout.createDimension('nVertLevels', int(options.levels))
113116
# Also create the nVertInterfaces dimension, even if none of the variables require it.
114117
fileout.createDimension('nVertInterfaces', len(fileout.dimensions['nVertLevels']) + 1) # nVertInterfaces = nVertLevels + 1
115-
print 'Added new dimension nVertInterfaces to output file with value of ' + str(len(fileout.dimensions['nVertInterfaces'])) + '.'
118+
print('Added new dimension nVertInterfaces to output file with value of {}.'.format(len(fileout.dimensions['nVertInterfaces'])))
116119

117120
fileout.sync()
118-
print 'Finished creating dimensions in output file.\n' # include an extra blank line here
121+
print('Finished creating dimensions in output file.\n') # include an extra blank line here
119122

120123
# ============================================
121124
# Copy over all of the required grid variables to the new file
122125
# ============================================
123-
print "Beginning to copy mesh variables to output file."
126+
print("Beginning to copy mesh variables to output file.")
124127
vars2copy = ['latCell', 'lonCell', 'xCell', 'yCell', 'zCell', 'indexToCellID', 'latEdge', 'lonEdge', 'xEdge', 'yEdge', 'zEdge', 'indexToEdgeID', 'latVertex', 'lonVertex', 'xVertex', 'yVertex', 'zVertex', 'indexToVertexID', 'cellsOnEdge', 'nEdgesOnCell', 'nEdgesOnEdge', 'edgesOnCell', 'edgesOnEdge', 'weightsOnEdge', 'dvEdge', 'dcEdge', 'angleEdge', 'areaCell', 'areaTriangle', 'cellsOnCell', 'verticesOnCell', 'verticesOnEdge', 'edgesOnVertex', 'cellsOnVertex', 'kiteAreasOnVertex']
125128
# Add these optional fields if they exist in the input file
126129
for optionalVar in ['meshDensity', 'gridSpacing', 'cellQuality', 'triangleQuality', 'triangleAngleQuality', 'obtuseTriangle']:
127130
if optionalVar in filein.variables:
128131
vars2copy.append(optionalVar)
129132

130133
for varname in vars2copy:
131-
print "-",
132-
print "|"
134+
print("-"),
135+
print("|")
133136
for varname in vars2copy:
134137
thevar = filein.variables[varname]
135138
datatype = thevar.dtype
@@ -146,8 +149,8 @@
146149
del newVar, thevar
147150
sys.stdout.write("* "); sys.stdout.flush()
148151
fileout.sync()
149-
print "|"
150-
print "Finished copying mesh variables to output file.\n"
152+
print("|")
153+
print("Finished copying mesh variables to output file.\n")
151154

152155
# ============================================
153156
# Create the land ice variables (all the shallow water vars in the input file can be ignored)
@@ -170,7 +173,7 @@
170173
layerInterfaces[k] = 4.0/3.0 * (1.0 - ((k+1.0-1.0)/(nInterfaces-1.0) + 1.0)**-2)
171174
for k in range(nVertLevels):
172175
layerThicknessFractionsData[k] = layerInterfaces[k+1] - layerInterfaces[k]
173-
print "Setting layerThicknessFractions to:", layerThicknessFractionsData
176+
print("Setting layerThicknessFractions to: {}".format(layerThicknessFractionsData))
174177
else:
175178
sys.exit('Unknown method for vertical spacing method (--vert): '+options.vertMethod)
176179

@@ -192,17 +195,17 @@
192195
newvar[:] = numpy.zeros(newvar.shape)
193196
newvar = fileout.createVariable('floatingBasalMassBal', datatype, ('Time', 'nCells'))
194197
newvar[:] = numpy.zeros(newvar.shape)
195-
print 'Added default variables: thickness, temperature, bedTopography, sfcMassBal, floatingBasalMassBal'
198+
print('Added default variables: thickness, temperature, bedTopography, sfcMassBal, floatingBasalMassBal')
196199

197200
if options.beta:
198201
newvar = fileout.createVariable('beta', datatype, ('Time', 'nCells'))
199202
newvar[:] = 1.0e8 # Give a default beta that won't have much sliding.
200-
print 'Added optional variable: beta'
203+
print('Added optional variable: beta')
201204

202205
if options.effecpress:
203206
newvar = fileout.createVariable('effectivePressure', datatype, ('Time', 'nCells'))
204207
newvar[:] = 1.0e8 # Give a default effective pressure that won't have much sliding.
205-
print 'Added optional variable: effectivePressure'
208+
print('Added optional variable: effectivePressure')
206209

207210
if options.dirichlet:
208211
newvar = fileout.createVariable('dirichletVelocityMask', datatypeInt, ('Time', 'nCells', 'nVertInterfaces'))
@@ -211,7 +214,7 @@
211214
newvar[:] = 0.0
212215
newvar = fileout.createVariable('uReconstructY', datatype, ('Time', 'nCells', 'nVertInterfaces',))
213216
newvar[:] = 0.0
214-
print 'Added optional dirichlet variables: dirichletVelocityMask, uReconstructX, uReconstructY'
217+
print('Added optional dirichlet variables: dirichletVelocityMask, uReconstructX, uReconstructY')
215218

216219
if options.thermal:
217220
newvar = fileout.createVariable('temperature', datatype, ('Time', 'nCells', 'nVertLevels'))
@@ -220,7 +223,7 @@
220223
newvar[:] = 273.15 # Give default value for temperate ice
221224
newvar = fileout.createVariable('basalHeatFlux', datatype, ('Time', 'nCells'))
222225
newvar[:] = 0.0 # Default to none (W/m2)
223-
print 'Added optional thermal variables: temperature, surfaceAirTemperature, basalHeatFlux'
226+
print('Added optional thermal variables: temperature, surfaceAirTemperature, basalHeatFlux')
224227

225228
if options.hydro:
226229
newvar = fileout.createVariable('waterThickness', datatype, ('Time', 'nCells'))
@@ -237,7 +240,7 @@
237240
newvar[:] = 0.0
238241
newvar = fileout.createVariable('waterFluxMask', 'i', ('Time', 'nEdges'))
239242
newvar[:] = 0.0
240-
print 'Added optional hydro variables: waterThickness, tillWaterThickness, meltInput, frictionAngle, waterPressure, waterFluxMask'
243+
print('Added optional hydro variables: waterThickness, tillWaterThickness, meltInput, frictionAngle, waterPressure, waterFluxMask')
241244

242245
if options.obs:
243246
newvar = fileout.createVariable('observedSurfaceVelocityX', datatype, ('Time', 'nCells'))
@@ -252,7 +255,7 @@
252255
newvar[:] = 0.0
253256
newvar = fileout.createVariable('thicknessUncertainty', datatype, ('Time', 'nCells'))
254257
newvar[:] = 0.0
255-
print 'Added optional velocity optimization variables: observedSurfaceVelocityX, observedSurfaceVelocityY, observedSurfaceVelocityUncertainty, observedThicknessTendency, observedThicknessTendencyUncertainty, thicknessUncertainty'
258+
print('Added optional velocity optimization variables: observedSurfaceVelocityX, observedSurfaceVelocityY, observedSurfaceVelocityUncertainty, observedThicknessTendency, observedThicknessTendencyUncertainty, thicknessUncertainty')
256259

257260
# Update history attribute of netCDF file
258261
thiscommand = datetime.now().strftime("%a %b %d %H:%M:%S %Y") + ": " + " ".join(sys.argv[:])
@@ -262,10 +265,10 @@
262265
newhist = thiscommand
263266
setattr(fileout, 'history', newhist )
264267

265-
print "Completed creating land ice variables in new file. Now syncing to file."
268+
print("Completed creating land ice variables in new file. Now syncing to file.")
266269
fileout.sync()
267270

268271
filein.close()
269272
fileout.close()
270273

271-
print '\n** Successfully created ' + options.fileoutName + '.**'
274+
print('\n** Successfully created {}.**'.format(options.fileoutName))

landice/mesh_tools_li/define_cullMask.py

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@
22
# Script for adding a field named cullMask to an MPAS land ice grid for use with the MpasCellCuller tool that actually culls the unwanted cells.
33
# Matt Hoffman, February 28, 2013
44

5+
from __future__ import absolute_import, division, print_function, \
6+
unicode_literals
7+
58
import sys
69
import numpy as np
710
from optparse import OptionParser
811
from netCDF4 import Dataset as NetCDFFile
912
from datetime import datetime
1013

1114

12-
print "** Gathering information."
15+
print("** Gathering information.")
1316
parser = OptionParser()
1417
parser.add_option("-f", "--file", dest="file", help="grid file to modify; default: landice_grid.nc", metavar="FILE")
1518
parser.add_option("-m", "--method", dest="method", help="method to use for marking cells to cull. Supported methods: 'noIce', 'numCells', 'distance', 'radius', 'edgeFraction'", metavar="METHOD")
@@ -19,7 +22,7 @@
1922
options, args = parser.parse_args()
2023

2124
if not options.file:
22-
print "No grid filename provided. Using landice_grid.nc."
25+
print("No grid filename provided. Using landice_grid.nc.")
2326
options.file = "landice_grid.nc"
2427

2528
if not options.method:
@@ -46,18 +49,18 @@
4649
thicknessMissing = True
4750
try:
4851
thickness = f.variables['thickness'][0,:]
49-
print 'Using thickness field at time 0'
52+
print('Using thickness field at time 0')
5053
thicknessMissing = False
5154
except:
52-
print "The field 'thickness' is not available. Some culling methods will not work."
55+
print("The field 'thickness' is not available. Some culling methods will not work.")
5356

5457

5558
# ===== Various methods for defining the mask ====
5659

5760
# =========
5861
# only keep cells with ice
5962
if maskmethod == 'noIce':
60-
print "Method: remove cells without ice"
63+
print("Method: remove cells without ice")
6164
if thicknessMissing:
6265
sys.exit("Unable to perform 'numCells' method because thickness field was missing.")
6366

@@ -66,13 +69,13 @@
6669
# =========
6770
# add a buffer of X cells around the ice
6871
elif maskmethod == 'numCells':
69-
print "Method: remove cells beyond a certain number of cells from existing ice"
72+
print("Method: remove cells beyond a certain number of cells from existing ice")
7073

7174
if thicknessMissing:
7275
sys.exit("Unable to perform 'numCells' method because thickness field was missing.")
7376

7477
buffersize=int(options.numCells) # number of cells to expand
75-
print "Using a buffer of {} cells".format(buffersize)
78+
print("Using a buffer of {} cells".format(buffersize))
7679

7780
keepCellMask = np.copy(cullCell[:])
7881
keepCellMask[:] = 0
@@ -81,17 +84,17 @@
8184

8285
# mark the cells with ice first
8386
keepCellMask[thickness > 0.0] = 1
84-
print 'Num of cells with ice:', sum(keepCellMask)
87+
print('Num of cells with ice: {}'.format(sum(keepCellMask)))
8588

8689
for i in range(buffersize):
87-
print 'Starting buffer loop ', i+1
90+
print('Starting buffer loop {}'.format(i+1))
8891
keepCellMaskNew = np.copy(keepCellMask) # make a copy to edit that can be edited without changing the original
8992
ind = np.nonzero(keepCellMask == 0)[0]
9093
for i in range(len(ind)):
9194
iCell = ind[i]
9295
keepCellMaskNew[iCell] = keepCellMask[cellsOnCell[iCell,:nEdgesOnCell[iCell]]-1].max() # if any neighbor has a value of 1, then 1 will get assigned to iCell.
9396
keepCellMask = np.copy(keepCellMaskNew) # after we've looped over all cells assign the new mask to the variable we need (either for another loop around the domain or to write out)
94-
print ' Num of cells to keep:', sum(keepCellMask)
97+
print(' Num of cells to keep: {}'.format(sum(keepCellMask)))
9598

9699
# Now convert the keepCellMask to the cullMask
97100
cullCell[:] = np.absolute(keepCellMask[:]-1) # Flip the mask for which ones to cull
@@ -100,13 +103,13 @@
100103
# remove cells beyond a certain distance of ice extent
101104
elif maskmethod == 'distance':
102105

103-
print "Method: remove cells beyond a certain distance from existing ice"
106+
print("Method: remove cells beyond a certain distance from existing ice")
104107

105108
if thicknessMissing:
106109
sys.exit("Unable to perform 'numCells' method because thickness field was missing.")
107110

108111
dist=float(options.distance)
109-
print "Using a buffer distance of {} km".format(dist)
112+
print("Using a buffer distance of {} km".format(dist))
110113
dist = dist * 1000.0 # convert to m
111114

112115
keepCellMask = np.copy(cullCell[:])
@@ -118,7 +121,7 @@
118121

119122
# mark the cells with ice first
120123
keepCellMask[thickness > 0.0] = 1
121-
print 'Num of cells with ice:', sum(keepCellMask)
124+
print('Num of cells with ice: {}'.format(sum(keepCellMask)))
122125

123126
# find list of margin cells
124127
iceCells = np.nonzero(keepCellMask == 1)[0]
@@ -138,7 +141,7 @@
138141
ind = np.nonzero(((xCell-xCell[iCell])**2 + (yCell-yCell[iCell])**2)**0.5 < dist)[0]
139142
keepCellMask[ind] = 1
140143

141-
print ' Num of cells to keep:', sum(keepCellMask)
144+
print(' Num of cells to keep:'.format(sum(keepCellMask)))
142145

143146
# Now convert the keepCellMask to the cullMask
144147
cullCell[:] = np.absolute(keepCellMask[:]-1) # Flip the mask for which ones to cull
@@ -147,14 +150,14 @@
147150
# =========
148151
# cut out beyond some radius (good for the dome)
149152
elif maskmethod == 'radius':
150-
print "Method: remove cells beyond a radius"
153+
print("Method: remove cells beyond a radius")
151154
ind = np.nonzero( (xCell[:]**2 + yCell[:]**2)**0.5 > 26000.0 )
152155
cullCell[ind] = 1
153156

154157
# =========
155158
# cut off some fraction of the height/width on all 4 sides - useful for cleaning up a mesh from periodic_general
156159
elif maskmethod == 'edgeFraction':
157-
print "Method: remove a fraction from all 4 edges"
160+
print("Method: remove a fraction from all 4 edges")
158161
frac=0.025
159162

160163
cullCell[:] = 0
@@ -175,7 +178,7 @@
175178
# =========
176179

177180

178-
print 'Num of cells to cull:', sum(cullCell[:])
181+
print('Num of cells to cull: {}'.format(sum(cullCell[:])))
179182

180183
# =========
181184
# Try to add the new variable
@@ -205,6 +208,6 @@
205208
plt.show()
206209

207210
f.close()
208-
print "cullMask generation complete."
211+
print("cullMask generation complete.")
209212

210213

0 commit comments

Comments
 (0)