Skip to content

Commit ba4696b

Browse files
committed
Add feature creation script
1 parent 98556d1 commit ba4696b

File tree

1 file changed

+138
-0
lines changed

1 file changed

+138
-0
lines changed
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
#!/usr/bin/env python
2+
"""
3+
Download the BedMachine topography
4+
----------------------------------
5+
1. Go tohttps://nsidc.org/data/nsidc-0756/versions/3
6+
2. Click on "HTTPS File System"
7+
3. Log in or create and account.
8+
5. Under "1970.01.01" choose "BedMachineAntarctica-v3.nc"
9+
10+
On Anvil or Chrysalis, BedMachine Antarctica v3 is available so create a
11+
symlink with:
12+
ln -s /lcrc/group/e3sm/public_html/mpas_standalonedata/mpas-ocean/bathymetry_database/BedMachineAntarctica-v3.nc
13+
"""
14+
15+
import shutil
16+
17+
import matplotlib.pyplot as plt
18+
import numpy as np
19+
import shapely
20+
import xarray as xr
21+
from pyproj import Transformer
22+
23+
from geometric_features import GeometricFeatures, FeatureCollection
24+
from geometric_features.feature_collection import _round_coords
25+
from geometric_features.utils import write_feature_names_and_tags
26+
27+
28+
def get_longest_contour(contour_value, author):
29+
30+
def stereo_to_lon_lat(x, y):
31+
lat, lon = transformer.transform(x, y)
32+
return lon, lat
33+
34+
with xr.open_dataset('BedMachineAntarctica-v3.nc') as ds:
35+
# the bed but only in the open ocean or under floating ice
36+
bed = xr.where(np.logical_or(ds.mask == 0, ds.mask == 3),
37+
ds.bed, 0.).values
38+
x = ds.x.values
39+
y = ds.y.values
40+
41+
# plot contours
42+
plt.figure()
43+
cs = plt.contour(x, y, bed, (contour_value,))
44+
paths = cs.allsegs[0]
45+
46+
path_lengths = [len(paths[i]) for i in range(len(paths))]
47+
ilongest = np.argmax(path_lengths)
48+
49+
v = paths[ilongest]
50+
x = v[:, 0]
51+
y = v[:, 1]
52+
53+
# the starting index should be the point closest to the positive x axis
54+
mask = x > 0.
55+
indices = np.arange(y.shape[0])[mask]
56+
index = np.argmin(np.abs(y[mask]))
57+
first = indices[index]
58+
x = np.append(x[first:], x[:first])
59+
y = np.append(y[first:], y[:first])
60+
61+
# Antarctic stereographic to lat/lon
62+
transformer = Transformer.from_crs('epsg:3031', 'epsg:4326')
63+
64+
transect = shapely.geometry.LineString([(i[0], i[1]) for i in zip(x, y)])
65+
66+
# cut a square out at around the first point at 90 degrees longitude to
67+
# prevent the shape from being a closed loop
68+
width = 30e3
69+
x0 = x[0]
70+
y0 = y[0]
71+
square = shapely.geometry.Polygon([(x0 - width, y0 - width),
72+
(x0 + width, y0 - width),
73+
(x0 + width, y0 + width),
74+
(x0 - width, y0 + width),
75+
(x0 - width, y0 - width)])
76+
77+
difference = transect.difference(square)
78+
79+
# cut a tiny weged out to break the shape into 2 at the antimeridian
80+
epsilon = 1e-14
81+
minY = np.amin(y)
82+
wedge = shapely.geometry.Polygon([(epsilon, minY),
83+
(epsilon**2, -epsilon),
84+
(0, epsilon),
85+
(-epsilon**2, -epsilon),
86+
(-epsilon, minY),
87+
(epsilon, minY)])
88+
89+
difference = difference.difference(wedge)
90+
91+
transect_latlon = shapely.ops.transform(stereo_to_lon_lat, difference)
92+
93+
plt.figure()
94+
for geom in transect_latlon.geoms:
95+
x, y = geom.xy
96+
plt.plot(x, y)
97+
98+
fc = FeatureCollection()
99+
100+
geometry = shapely.geometry.mapping(transect_latlon)
101+
# get rid of the wedge again by rounding the coordinates
102+
geometry['coordinates'] = _round_coords(geometry['coordinates'])
103+
104+
fc.add_feature(
105+
{'type': 'Feature',
106+
'properties': {'name': f'Antarctic isobath at {contour_value} m',
107+
'author': author,
108+
'object': 'transect',
109+
'component': 'ocean',
110+
'tags': 'Antarctic'},
111+
'geometry': geometry})
112+
113+
return fc
114+
115+
116+
def main():
117+
xylar = 'Xylar Asay-Davis'
118+
119+
# make a geometric fieatures object that knows about the geometric data
120+
# cache up a couple of directories
121+
gf = GeometricFeatures('../../geometric_data')
122+
123+
fc = get_longest_contour(contour_value=-1000., author=xylar)
124+
125+
# "split" these features into individual files in the geometric data cache
126+
gf.split(fc)
127+
128+
# update the database of feature names and tags
129+
write_feature_names_and_tags(gf.cacheLocation)
130+
# move the resulting file into place
131+
shutil.copyfile('features_and_tags.json',
132+
'../../geometric_features/features_and_tags.json')
133+
134+
plt.show()
135+
136+
137+
if __name__ == '__main__':
138+
main()

0 commit comments

Comments
 (0)