Skip to content

Commit eba1d4b

Browse files
committed
detect_plates return index of limit, is cached
This simplifies the API of detect_plates, and caching allows simplifying the API of functions that need the position of ridges and trenches.
1 parent 4baf577 commit eba1d4b

File tree

1 file changed

+47
-51
lines changed

1 file changed

+47
-51
lines changed

stagpy/plates.py

Lines changed: 47 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
"""Plate analysis."""
22

33
from contextlib import suppress
4+
from functools import lru_cache
45

56
import matplotlib.pyplot as plt
67
from matplotlib import colors
78
import numpy as np
8-
from scipy.signal import argrelextrema
9+
from scipy.signal import argrelmin, argrelmax
910

1011
from . import conf, error, field, phyvars
1112
from ._helpers import saveplot, list_of_vars
@@ -68,56 +69,49 @@ def detect_plates_vzcheck(step, vz_thres_ratio=0):
6869
return limits, dvphi, vphi_surf
6970

7071

71-
def detect_plates(step):
72+
@lru_cache()
73+
def detect_plates(snap):
7274
"""Detect plates using derivative of horizontal velocity."""
73-
vphi = step.fields['v2'].values[0, :, :, 0]
74-
ph_coord = step.geom.p_centers
75-
76-
indsurf = _isurf(step)
77-
78-
# dvphi/dphi at cell-center
79-
dvph2 = np.diff(vphi[:, indsurf]) / (ph_coord[1] - ph_coord[0])
75+
dvphi = _surf_diag(snap, 'dv2').values
8076

8177
# finding trenches
82-
pom2 = np.copy(dvph2)
83-
maskbigdvel = np.amin(dvph2) * 0.2
84-
pom2[pom2 > maskbigdvel] = maskbigdvel
85-
trench_span = 15 if step.sdat.par['boundaries']['air_layer'] else 10
86-
argless_dv = argrelextrema(
87-
pom2, np.less, order=trench_span, mode='wrap')[0]
88-
trench = ph_coord[argless_dv]
78+
dvphi_saturated = np.copy(dvphi)
79+
max_dvphi = np.amin(dvphi) * 0.2
80+
dvphi_saturated[dvphi > max_dvphi] = max_dvphi
81+
trench_span = 15 if snap.sdat.par['boundaries']['air_layer'] else 10
82+
itrenches = argrelmin(dvphi_saturated, order=trench_span, mode='wrap')[0]
8983

9084
# finding ridges
91-
pom2 = np.copy(dvph2)
92-
masksmalldvel = np.amax(dvph2) * 0.2
93-
pom2[pom2 < masksmalldvel] = masksmalldvel
85+
dvphi_saturated = np.copy(dvphi)
86+
min_dvphi = np.amax(dvphi) * 0.2
87+
dvphi_saturated[dvphi < min_dvphi] = min_dvphi
9488
ridge_span = 20
95-
arggreat_dv = argrelextrema(
96-
pom2, np.greater, order=ridge_span, mode='wrap')[0]
97-
ridge = ph_coord[arggreat_dv]
89+
iridges = argrelmax(dvphi_saturated, order=ridge_span, mode='wrap')[0]
9890

99-
# elimination of ridges that are too close to trench
91+
# elimination of ridges that are too close to a trench
92+
phi = snap.geom.p_centers
93+
phi_trenches = phi[itrenches]
10094
argdel = []
101-
if trench.any() and ridge.any():
102-
for i, ridge_i in enumerate(ridge):
103-
mdistance = np.amin(abs(trench - ridge_i))
95+
if itrenches.size and iridges.size:
96+
for i, iridge in enumerate(iridges):
97+
mdistance = np.amin(np.abs(phi_trenches - phi[iridge]))
10498
if mdistance < 0.016:
10599
argdel.append(i)
106100
if argdel:
107-
ridge = np.delete(ridge, np.array(argdel))
101+
iridges = np.delete(iridges, argdel)
108102

109-
return trench, ridge, argless_dv
103+
return itrenches, iridges
110104

111105

112-
def plot_plate_limits(axis, ridges, trenches):
106+
def _plot_plate_limits(axis, trenches, ridges):
113107
"""Plot lines designating ridges and trenches."""
114108
for trench in trenches:
115109
axis.axvline(x=trench, color='red', ls='dashed', alpha=0.4)
116110
for ridge in ridges:
117111
axis.axvline(x=ridge, color='green', ls='dashed', alpha=0.4)
118112

119113

120-
def plot_plate_limits_field(axis, rcmb, ridges, trenches):
114+
def _plot_plate_limits_field(axis, rcmb, trenches, ridges):
121115
"""Plot arrows designating ridges and trenches in 2D field plots."""
122116
for trench in trenches:
123117
xxd = (rcmb + 1.02) * np.cos(trench) # arrow begin
@@ -196,7 +190,7 @@ def _continents_location(snap, at_surface=True):
196190
return csurf >= 2
197191

198192

199-
def plot_at_surface(snap, names, trenches, ridges):
193+
def plot_at_surface(snap, names):
200194
"""Plot surface diagnostics."""
201195
for vfig in list_of_vars(names):
202196
fig, axes = plt.subplots(nrows=len(vfig), sharex=True,
@@ -220,9 +214,9 @@ def plot_at_surface(snap, names, trenches, ridges):
220214
where=continents, alpha=0.2,
221215
facecolor='#8B6914')
222216
axis.set_ylim([ymin, ymax])
223-
# need to have trenches and ridges detection without side-
224-
# effects, call it here. Memoized.
225-
plot_plate_limits(axis, ridges, trenches)
217+
phi = snap.geom.p_centers
218+
itrenches, iridges = detect_plates(snap)
219+
_plot_plate_limits(axis, phi[itrenches], phi[iridges])
226220
if len(vplt) == 1:
227221
axis.set_ylabel(label)
228222
else:
@@ -232,8 +226,9 @@ def plot_at_surface(snap, names, trenches, ridges):
232226
saveplot(fig, fname, snap.isnap)
233227

234228

235-
def _write_trench_diagnostics(step, vrms_surf, itrenches, fid):
229+
def _write_trench_diagnostics(step, vrms_surf, fid):
236230
"""Print out some trench diagnostics."""
231+
itrenches, _ = detect_plates(step)
237232
time = step.time * vrms_surf *\
238233
conf.scaling.ttransit / conf.scaling.yearins / 1.e6
239234
isurf = _isurf(step)
@@ -284,28 +279,31 @@ def _write_trench_diagnostics(step, vrms_surf, itrenches, fid):
284279
agetrenches[isubd]))
285280

286281

287-
def plot_scalar_field(step, fieldname, ridges, trenches):
282+
def plot_scalar_field(snap, fieldname):
288283
"""Plot scalar field with plate information."""
289-
fig, axis, _, _ = field.plot_scalar(step, fieldname)
284+
fig, axis, _, _ = field.plot_scalar(snap, fieldname)
290285

291286
if conf.plates.continents:
292287
c_field = np.ma.masked_where(
293-
~_continents_location(step, at_surface=False),
294-
step.fields['c'].values[0, :, :, 0])
288+
~_continents_location(snap, at_surface=False),
289+
snap.fields['c'].values[0, :, :, 0])
295290
cbar = conf.field.colorbar
296291
conf.field.colorbar = False
297292
cmap = colors.ListedColormap(["k", "g", "m"])
298-
field.plot_scalar(step, 'c', c_field, axis, cmap=cmap,
293+
field.plot_scalar(snap, 'c', c_field, axis, cmap=cmap,
299294
norm=colors.BoundaryNorm([2, 3, 4, 5], cmap.N))
300295
conf.field.colorbar = cbar
301296

302297
# plotting velocity vectors
303-
field.plot_vec(axis, step, 'sx' if conf.plates.stress else 'v')
298+
field.plot_vec(axis, snap, 'sx' if conf.plates.stress else 'v')
304299

305300
# Put arrow where ridges and trenches are
306-
plot_plate_limits_field(axis, step.geom.rcmb, ridges, trenches)
301+
phi = snap.geom.p_centers
302+
itrenches, iridges = detect_plates(snap)
303+
_plot_plate_limits_field(axis, snap.geom.rcmb,
304+
phi[itrenches], phi[iridges])
307305

308-
saveplot(fig, f'plates_{fieldname}', step.isnap,
306+
saveplot(fig, f'plates_{fieldname}', snap.isnap,
309307
close=conf.plates.zoom is None)
310308

311309
# Zoom
@@ -320,11 +318,11 @@ def plot_scalar_field(step, fieldname, ridges, trenches):
320318
ladd, radd, uadd, dadd = 0.8, 0.8, 0.1, 0.05
321319
else: # >315 or <=45
322320
ladd, radd, uadd, dadd = 0.1, 0.05, 0.8, 0.8
323-
xzoom = (step.geom.rcmb + 1) * np.cos(np.radians(conf.plates.zoom))
324-
yzoom = (step.geom.rcmb + 1) * np.sin(np.radians(conf.plates.zoom))
321+
xzoom = (snap.geom.rcmb + 1) * np.cos(np.radians(conf.plates.zoom))
322+
yzoom = (snap.geom.rcmb + 1) * np.sin(np.radians(conf.plates.zoom))
325323
axis.set_xlim(xzoom - ladd, xzoom + radd)
326324
axis.set_ylim(yzoom - dadd, yzoom + uadd)
327-
saveplot(fig, f'plates_zoom_{fieldname}', step.isnap)
325+
saveplot(fig, f'plates_zoom_{fieldname}', snap.isnap)
328326

329327

330328
def cmd():
@@ -348,11 +346,9 @@ def cmd():
348346

349347
for step in sdat.walk.filter(fields=['T']):
350348
# could check other fields too
351-
trenches, ridges, itrenches = detect_plates(step)
352-
353-
_write_trench_diagnostics(step, vrms_surf, itrenches, fid)
354-
plot_at_surface(step, conf.plates.plot, trenches, ridges)
355-
plot_scalar_field(step, conf.plates.field, ridges, trenches)
349+
_write_trench_diagnostics(step, vrms_surf, fid)
350+
plot_at_surface(step, conf.plates.plot)
351+
plot_scalar_field(step, conf.plates.field)
356352
else:
357353
nb_plates = []
358354
time = []

0 commit comments

Comments
 (0)