wawi 0.0.1__py3-none-any.whl → 0.0.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wawi/__init__.py +8 -4
- wawi/fe.py +134 -0
- wawi/general.py +468 -0
- wawi/identification.py +66 -0
- wawi/io.py +719 -0
- wawi/modal.py +608 -0
- wawi/plot.py +569 -0
- wawi/prob.py +9 -0
- wawi/random.py +38 -0
- wawi/signal.py +45 -0
- wawi/structural.py +278 -0
- wawi/time_domain.py +126 -0
- wawi/tools.py +7 -0
- wawi/wave.py +491 -0
- wawi/wind.py +1109 -0
- wawi/wind_code.py +14 -0
- {wawi-0.0.1.dist-info → wawi-0.0.5.dist-info}/METADATA +7 -6
- wawi-0.0.5.dist-info/RECORD +21 -0
- wawi-0.0.1.dist-info/RECORD +0 -6
- {wawi-0.0.1.dist-info → wawi-0.0.5.dist-info}/LICENSE +0 -0
- {wawi-0.0.1.dist-info → wawi-0.0.5.dist-info}/WHEEL +0 -0
- {wawi-0.0.1.dist-info → wawi-0.0.5.dist-info}/top_level.txt +0 -0
wawi/plot.py
ADDED
@@ -0,0 +1,569 @@
|
|
1
|
+
import numpy as np
|
2
|
+
import matplotlib.pyplot as plt
|
3
|
+
from matplotlib.animation import FuncAnimation
|
4
|
+
from wawi.wave import dispersion_relation_scalar as get_kappa
|
5
|
+
from scipy.ndimage import rotate, shift
|
6
|
+
from matplotlib import transforms
|
7
|
+
from scipy.interpolate import RectBivariateSpline, interp1d
|
8
|
+
|
9
|
+
|
10
|
+
def plot_ads(ad_dict, v, terms='stiffness', num=None, test_v=dict(), test_ad=dict(), zasso_type=False, ranges=None):
|
11
|
+
# v: v or K
|
12
|
+
if terms is 'stiffness':
|
13
|
+
terms = [['P4', 'P6', 'P3'], ['H6', 'H4', 'H3'], ['A6', 'A4', 'A3']]
|
14
|
+
elif terms is 'damping':
|
15
|
+
terms = [['P1', 'P5', 'P2'], ['H5', 'H1', 'H2'], ['A5', 'A1', 'A2']]
|
16
|
+
|
17
|
+
# Create exponent defs for K_normalized plotting
|
18
|
+
K_exp = dict()
|
19
|
+
stiffness_terms = ['P4', 'P6', 'P3', 'H6', 'H4', 'H3', 'A6', 'A4', 'A3']
|
20
|
+
damping_terms = ['P1', 'P5', 'P2', 'H5', 'H1', 'H2', 'A5', 'A1', 'A2']
|
21
|
+
K_exp.update(zip(stiffness_terms, [1]*len(stiffness_terms)))
|
22
|
+
K_exp.update(zip(damping_terms, [2]*len(damping_terms)))
|
23
|
+
|
24
|
+
K_label_add = dict()
|
25
|
+
K_label_add.update(zip(stiffness_terms, ['$K$']*len(stiffness_terms)))
|
26
|
+
K_label_add.update(zip(damping_terms, ['$K^2$']*len(damping_terms)))
|
27
|
+
|
28
|
+
fig, ax = plt.subplots(nrows=len(terms[0]), ncols=len(terms), num=num, sharex=True)
|
29
|
+
|
30
|
+
for row_ix, row in enumerate(terms):
|
31
|
+
for col_ix, term in enumerate(row):
|
32
|
+
axi = ax[row_ix, col_ix]
|
33
|
+
|
34
|
+
if term in ad_dict:
|
35
|
+
if ranges is not None and term in ranges:
|
36
|
+
ad_valid = ad_dict[term](v)*1
|
37
|
+
|
38
|
+
v_min, v_max = ranges[term]
|
39
|
+
|
40
|
+
ad_valid[v<v_min] = ad_dict[term](v_min)
|
41
|
+
ad_valid[v>v_max] = ad_dict[term](v_max)
|
42
|
+
else:
|
43
|
+
ad_valid = ad_dict[term](v)
|
44
|
+
|
45
|
+
axi.plot(v, ad_valid, label='Fit')
|
46
|
+
|
47
|
+
label = zasso_type*K_label_add[term]+('$' + term[0] + '_' + term[1] + '^*' + '$')
|
48
|
+
axi.set_ylabel(label)
|
49
|
+
axi.grid('on')
|
50
|
+
|
51
|
+
if term in test_v:
|
52
|
+
if zasso_type:
|
53
|
+
vK = 1/test_v[term]
|
54
|
+
factor = vK**K_exp[term]
|
55
|
+
else:
|
56
|
+
vK = test_v[term]
|
57
|
+
factor = 1.0
|
58
|
+
|
59
|
+
axi.plot(vK, test_ad[term]*factor, '.k', label='Test')
|
60
|
+
|
61
|
+
for col_ix in range(len(terms)):
|
62
|
+
if zasso_type:
|
63
|
+
ax[-1, col_ix].set_xlabel('$K$')
|
64
|
+
else:
|
65
|
+
ax[-1, col_ix].set_xlabel('$V/(B\cdot \omega)$')
|
66
|
+
|
67
|
+
fig.tight_layout()
|
68
|
+
return fig, ax
|
69
|
+
|
70
|
+
def save_plot(pl, path, w=None, h=None):
|
71
|
+
ws = pl.window_size
|
72
|
+
if w is not None and h is None:
|
73
|
+
w = int(np.round(w))
|
74
|
+
h = int(np.round(ws[1] * w/ws[0]))
|
75
|
+
elif h is not None and w is None:
|
76
|
+
h = int(np.round(h))
|
77
|
+
w = int(np.round(ws[0] * h/ws[1]))
|
78
|
+
elif h is None and w is None:
|
79
|
+
w,h = ws
|
80
|
+
else:
|
81
|
+
w = int(np.round(w))
|
82
|
+
h = int(np.round(h))
|
83
|
+
|
84
|
+
pl.screenshot(path, window_size=[w,h], return_img=False)
|
85
|
+
|
86
|
+
def plot_dir_and_crests(theta0, Tp, arrow_length=100, origin=np.array([0,0]),
|
87
|
+
ax=None, n_repeats=2, crest_length=1000,
|
88
|
+
alpha_crests=0.2, arrow_options={}):
|
89
|
+
arr_opts = {'head_width': 4, 'width':2, 'edgecolor':'none'}
|
90
|
+
arr_opts.update(**arrow_options)
|
91
|
+
|
92
|
+
if ax is None:
|
93
|
+
ax = plt.gca()
|
94
|
+
|
95
|
+
# Plot wave angle and crests
|
96
|
+
v = np.array([np.cos(theta0*np.pi/180), np.sin(theta0*np.pi/180)])
|
97
|
+
v_norm = np.array([-np.sin(theta0*np.pi/180), np.cos(theta0*np.pi/180)])
|
98
|
+
wave_length = 2*np.pi/get_kappa(2*np.pi/Tp, U=0.0)
|
99
|
+
|
100
|
+
plt.arrow(origin[0],origin[1], arrow_length*v[0], arrow_length*v[1], **arr_opts)
|
101
|
+
plt.text(origin[0], origin[1], f'$\\theta_0$ = {theta0}$^o$\n $T_p$={Tp} s\n $\lambda=${wave_length:.0f} m')
|
102
|
+
|
103
|
+
dv = v*wave_length
|
104
|
+
for n in range(n_repeats):
|
105
|
+
p1 = origin-v_norm*crest_length/2
|
106
|
+
p2 = origin+v_norm*crest_length/2
|
107
|
+
pts = np.vstack([p1,p2])
|
108
|
+
|
109
|
+
ax.plot(pts[:,0], pts[:,1], alpha=alpha_crests, color='black', zorder=0)
|
110
|
+
origin = origin + dv
|
111
|
+
|
112
|
+
return ax
|
113
|
+
|
114
|
+
def rotate_image_about_pivot(Z, x, y, angle, x0=0, y0=0):
|
115
|
+
xc = np.mean(x)
|
116
|
+
yc = np.mean(y)
|
117
|
+
|
118
|
+
pixel_x = interp1d(x, np.arange(len(x)), fill_value='extrapolate')
|
119
|
+
pixel_y = interp1d(y, np.arange(len(y)), fill_value='extrapolate')
|
120
|
+
|
121
|
+
ds_x = pixel_x(x0) - pixel_x(xc) # sample shift x
|
122
|
+
ds_y = pixel_y(y0) - pixel_y(yc) # sample shift y
|
123
|
+
ds = np.array([ds_x, ds_y])*0
|
124
|
+
|
125
|
+
T = np.array([[np.cos(angle*np.pi/180), np.sin(angle*np.pi/180)],
|
126
|
+
[-np.sin(angle*np.pi/180), np.cos(angle*np.pi/180)]])
|
127
|
+
|
128
|
+
ds_rot = T @ ds
|
129
|
+
|
130
|
+
return shift(rotate(shift(Z, ds[::-1]), angle), -ds_rot[::-1])
|
131
|
+
|
132
|
+
def combine_eta(eta_fine, eta_course, x_fine, y_fine, x_course, y_course, x=None, y=None):
|
133
|
+
dx_fine = x_fine[1]-x_fine[0]
|
134
|
+
dy_fine = y_fine[1]-y_fine[0]
|
135
|
+
|
136
|
+
if x is None:
|
137
|
+
x = np.arange(np.min(x_course), np.max(x_course), dx_fine)
|
138
|
+
|
139
|
+
if y is None:
|
140
|
+
y = np.arange(np.min(y_course), np.max(y_course), dy_fine)
|
141
|
+
|
142
|
+
eta_course_i = RectBivariateSpline(y_course,x_course,eta_course)
|
143
|
+
eta_fine_i = RectBivariateSpline(y_fine,x_fine,eta_fine)
|
144
|
+
|
145
|
+
eta_combined = eta_course_i(y,x)
|
146
|
+
sel = np.ix_(
|
147
|
+
(y >= np.min(y_fine)) & (y <= np.max(y_fine)),
|
148
|
+
(x >= np.min(x_fine)) & (x <= np.max(x_fine)))
|
149
|
+
|
150
|
+
eta_combined[sel] = eta_fine_i(y[(y >= np.min(y_fine)) & (y <= np.max(y_fine))],
|
151
|
+
x[(x >= np.min(x_fine)) & (x <= np.max(x_fine))])
|
152
|
+
|
153
|
+
return eta_combined, x, y
|
154
|
+
|
155
|
+
|
156
|
+
def animate_surface(eta, x, y, t, filename=None, fps=None,
|
157
|
+
speed_ratio=1.0, figsize=None, writer='ffmpeg',
|
158
|
+
ax=None, surface=None):
|
159
|
+
|
160
|
+
|
161
|
+
if surface is None:
|
162
|
+
if ax is None:
|
163
|
+
fig, ax = plt.subplots(figsize=figsize)
|
164
|
+
else:
|
165
|
+
fig = fig.get_figure()
|
166
|
+
surface, __ = plot_surface(eta[:,:,0], x, y, ax=ax, colorbar=False, labels=False)
|
167
|
+
else:
|
168
|
+
fig = surface.get_figure()
|
169
|
+
ax = fig.axes[0]
|
170
|
+
|
171
|
+
def animate(i):
|
172
|
+
surface.set_data(eta[:,:,i])
|
173
|
+
return surface,
|
174
|
+
|
175
|
+
frames = np.arange(len(t))
|
176
|
+
dt = t[1]-t[0]
|
177
|
+
fs = 1/dt
|
178
|
+
|
179
|
+
if filename is None:
|
180
|
+
repeat = True
|
181
|
+
else:
|
182
|
+
repeat = False
|
183
|
+
|
184
|
+
if fps is None:
|
185
|
+
fps = fs*speed_ratio
|
186
|
+
|
187
|
+
interval = 1/fps*1000
|
188
|
+
|
189
|
+
anim = FuncAnimation(fig, animate,
|
190
|
+
frames=frames, interval=interval, blit=True, repeat=repeat)
|
191
|
+
|
192
|
+
if filename is not None:
|
193
|
+
anim.save(filename, writer=writer, fps=fps)
|
194
|
+
else:
|
195
|
+
plt.show()
|
196
|
+
|
197
|
+
def xy_to_latlon(latlon0, coors, rot=0):
|
198
|
+
import cartopy.crs as ccrs, cartopy.geodesic as cgds
|
199
|
+
dist = np.linalg.norm(coors, axis=1)
|
200
|
+
azi = np.arctan2(coors[:,0], coors[:,1])*180/np.pi - rot # atan2(x,y) to get azimuth (relative to N-vector)
|
201
|
+
geodesic = cgds.Geodesic()
|
202
|
+
|
203
|
+
return np.vstack(geodesic.direct(np.tile(latlon0, [len(dist), 1]), azi, dist))[:,:2]
|
204
|
+
|
205
|
+
|
206
|
+
def plot_surface_in_map(eta, x, y, eta_geo0, extent,
|
207
|
+
eta_scatter=None,
|
208
|
+
wms_url='https://openwms.statkart.no/skwms1/wms.terrengmodell?request=GetCapabilities&service=WMS',
|
209
|
+
wms_layers=['relieff'], ax=None,
|
210
|
+
cm='Blues_r', colorbar=True, figsize=None, eta_rot=0, labels=False):
|
211
|
+
|
212
|
+
import cartopy.crs as ccrs, cartopy.geodesic as cgds
|
213
|
+
|
214
|
+
proj = 'Mercator'
|
215
|
+
proj = getattr(ccrs, proj)()
|
216
|
+
|
217
|
+
|
218
|
+
if ax is None:
|
219
|
+
ax = plt.axes(projection=proj)
|
220
|
+
|
221
|
+
|
222
|
+
# Plot scatter
|
223
|
+
if eta_scatter is None:
|
224
|
+
scatter = None
|
225
|
+
else:
|
226
|
+
eta_scatter = xy_to_latlon(eta_geo0, eta_scatter, rot=eta_rot)
|
227
|
+
scatter = ax.scatter(eta_scatter[:,0], eta_scatter[:,1], c='black', s=6, transform=ccrs.PlateCarree())
|
228
|
+
|
229
|
+
# Plot eta
|
230
|
+
if eta is not None:
|
231
|
+
eta_max = np.max(np.abs(eta))
|
232
|
+
corners = np.array([[np.min(x), np.min(y)],
|
233
|
+
[np.min(x), np.max(y)],
|
234
|
+
[np.max(x), np.max(y)],
|
235
|
+
[np.max(x), np.min(y)]])
|
236
|
+
|
237
|
+
corners_latlon = xy_to_latlon(eta_geo0, corners, rot=eta_rot)
|
238
|
+
|
239
|
+
extent_merc = np.vstack(proj.transform_points(ccrs.PlateCarree(), np.array([extent[0], extent[2]]), np.array([extent[1], extent[3]])))[:,:2]
|
240
|
+
extent_merc = [np.min(extent_merc[:,0]), np.max(extent_merc[:,0]),
|
241
|
+
np.min(extent_merc[:,1]), np.max(extent_merc[:,1])]
|
242
|
+
|
243
|
+
ax.imshow(np.zeros([2,2]), cmap=cm, origin='lower', interpolation='none',
|
244
|
+
vmin=-eta_max, vmax=eta_max, extent=extent_merc)
|
245
|
+
|
246
|
+
corners_latlon_new = np.vstack(proj.transform_points(ccrs.PlateCarree(), *corners_latlon.T))[:,:2]
|
247
|
+
eta_extent_new = [np.min(corners_latlon_new[:,0]), np.max(corners_latlon_new[:,0]),
|
248
|
+
np.min(corners_latlon_new[:,1]), np.max(corners_latlon_new[:,1])]
|
249
|
+
|
250
|
+
eta_rotated = rotate(eta, -eta_rot)
|
251
|
+
|
252
|
+
surface = ax.imshow(eta_rotated, cmap=cm, origin='lower',
|
253
|
+
interpolation='none', extent=eta_extent_new,
|
254
|
+
vmin=-eta_max, vmax=eta_max)
|
255
|
+
|
256
|
+
if colorbar:
|
257
|
+
plt.colorbar(surface)
|
258
|
+
|
259
|
+
else:
|
260
|
+
surface = None
|
261
|
+
if labels:
|
262
|
+
ax.gridlines(color='lightgrey', linestyle='-', draw_labels=True)
|
263
|
+
|
264
|
+
ax.add_wms(wms_url, layers=wms_layers, extent=extent)
|
265
|
+
ax.set_extent(extent)
|
266
|
+
|
267
|
+
return ax, scatter, surface
|
268
|
+
|
269
|
+
|
270
|
+
def plot_surface(eta, x, y, ax=None,
|
271
|
+
cm='Blues_r', colorbar=True,
|
272
|
+
labels=True, figsize=None, interpolation='none'):
|
273
|
+
|
274
|
+
if ax is None:
|
275
|
+
fig, ax = plt.subplots(figsize=figsize)
|
276
|
+
|
277
|
+
dx = (x[1]-x[0])/2.
|
278
|
+
dy = (y[1]-y[0])/2.
|
279
|
+
extent = [x[0]-dx, x[-1]+dx, y[0]-dy, y[-1]+dy]
|
280
|
+
|
281
|
+
eta_max = np.max(np.abs(eta))
|
282
|
+
surface_plot = ax.imshow(eta, cmap=cm, extent=extent, origin='lower', vmin=-eta_max, vmax=eta_max, interpolation=interpolation)
|
283
|
+
|
284
|
+
if labels:
|
285
|
+
ax.set_xlabel('x [m]')
|
286
|
+
ax.set_ylabel('y [m]')
|
287
|
+
else:
|
288
|
+
ax.set_xticks([])
|
289
|
+
ax.set_yticks([])
|
290
|
+
|
291
|
+
if colorbar:
|
292
|
+
cb = plt.colorbar(surface_plot)
|
293
|
+
|
294
|
+
return surface_plot, ax
|
295
|
+
|
296
|
+
|
297
|
+
def set_axes_equal(ax: plt.Axes):
|
298
|
+
import matplotlib.pyplot as plt
|
299
|
+
"""Set 3D plot axes to equal scale.
|
300
|
+
|
301
|
+
Make axes of 3D plot have equal scale so that spheres appear as
|
302
|
+
spheres and cubes as cubes. Required since `ax.axis('equal')`
|
303
|
+
and `ax.set_aspect('equal')` don't work on 3D.
|
304
|
+
"""
|
305
|
+
limits = np.array([
|
306
|
+
ax.get_xlim3d(),
|
307
|
+
ax.get_ylim3d(),
|
308
|
+
ax.get_zlim3d(),
|
309
|
+
])
|
310
|
+
origin = np.mean(limits, axis=1)
|
311
|
+
radius = 0.5 * np.max(np.abs(limits[:, 1] - limits[:, 0]))
|
312
|
+
_set_axes_radius(ax, origin, radius)
|
313
|
+
|
314
|
+
def _set_axes_radius(ax, origin, radius):
|
315
|
+
x, y, z = origin
|
316
|
+
ax.set_xlim3d([x - radius, x + radius])
|
317
|
+
ax.set_ylim3d([y - radius, y + radius])
|
318
|
+
ax.set_zlim3d([z - radius, z + radius])
|
319
|
+
|
320
|
+
def equal_3d(ax=plt.gca()):
|
321
|
+
x_lims = np.array(ax.get_xlim())
|
322
|
+
y_lims = np.array(ax.get_ylim())
|
323
|
+
z_lims = np.array(ax.get_zlim())
|
324
|
+
|
325
|
+
x_range = np.diff(x_lims)
|
326
|
+
y_range = np.diff(y_lims)
|
327
|
+
z_range = np.diff(z_lims)
|
328
|
+
|
329
|
+
max_range = np.max([x_range,y_range,z_range])/2
|
330
|
+
|
331
|
+
ax.set_xlim(np.mean(x_lims) - max_range, np.mean(x_lims) + max_range)
|
332
|
+
ax.set_ylim(np.mean(y_lims) - max_range, np.mean(y_lims) + max_range)
|
333
|
+
ax.set_zlim(np.mean(z_lims) - max_range, np.mean(z_lims) + max_range)
|
334
|
+
# ax.set_aspect(1)
|
335
|
+
|
336
|
+
return ax
|
337
|
+
|
338
|
+
def plot_transformation_mats(x,y,z,T,figno=None, ax=None, scaling='auto'):
|
339
|
+
|
340
|
+
if ax==None:
|
341
|
+
fig = plt.figure(figno)
|
342
|
+
ax = fig.add_subplot(111, projection='3d')
|
343
|
+
|
344
|
+
ax.scatter(x,y,z,'.k')
|
345
|
+
|
346
|
+
if scaling=='auto':
|
347
|
+
xr = max(x)-min(x)
|
348
|
+
yr = max(y)-min(y)
|
349
|
+
zr = max(z)-min(z)
|
350
|
+
r = np.sqrt(xr**2+yr**2+zr**2)
|
351
|
+
scaling = 0.005*r
|
352
|
+
|
353
|
+
compcolors = ['tab:red', 'tab:blue', 'tab:green']
|
354
|
+
h = [None]*3
|
355
|
+
for ix, Ti in enumerate(T):
|
356
|
+
xi = x[ix]
|
357
|
+
yi = y[ix]
|
358
|
+
zi = z[ix]
|
359
|
+
|
360
|
+
for comp in range(0,3):
|
361
|
+
xunit = [xi, xi+Ti[comp,0]*scaling]
|
362
|
+
yunit = [yi, yi+Ti[comp,1]*scaling]
|
363
|
+
zunit = [zi, zi+Ti[comp,2]*scaling]
|
364
|
+
|
365
|
+
h[comp] = plt.plot(xs=xunit,ys=yunit,zs=zunit, color=compcolors[comp])[0]
|
366
|
+
|
367
|
+
plt.legend(h,['x', 'y', 'z'])
|
368
|
+
ax.set_xlabel('x')
|
369
|
+
ax.set_ylabel('y')
|
370
|
+
ax.set_zlabel('z')
|
371
|
+
|
372
|
+
equal_3d(ax)
|
373
|
+
return ax,h
|
374
|
+
|
375
|
+
|
376
|
+
def plot_elements(element_matrix, node_matrix, chosen_nodes_ix=[], disp=None, node_labels=False, element_labels=False, plot_nodes=True, plot_elements=True, ax=None, fig=None, element_settings={}, node_settings={}, node_label_settings={}, chosen_node_settings={}, disp_settings={}, element_label_settings={}, three_d=True):
|
377
|
+
e_dict = {'color': 'LimeGreen', 'alpha': 1}
|
378
|
+
e_dict.update(**element_settings)
|
379
|
+
|
380
|
+
n_dict = {'color':'Black', 'linestyle':'', 'marker':'.', 'markersize':4, 'alpha':0.8}
|
381
|
+
n_dict.update(**node_settings)
|
382
|
+
|
383
|
+
n_chosen_dict = {'color':'GreenYellow', 'linestyle':'', 'marker':'o', 'markersize':8, 'alpha':1, 'markeredgecolor':'dimgray'}
|
384
|
+
n_chosen_dict.update(**chosen_node_settings)
|
385
|
+
|
386
|
+
disp_dict = {'color':'IndianRed', 'alpha':1}
|
387
|
+
disp_dict.update(**disp_settings)
|
388
|
+
|
389
|
+
l_nodes_dict = {'color':'Black', 'fontsize': 8, 'fontweight':'normal'}
|
390
|
+
l_nodes_dict.update(**node_label_settings)
|
391
|
+
|
392
|
+
l_elements_dict = {'color':'LimeGreen', 'fontsize': 8, 'fontweight':'bold', 'style':'italic'}
|
393
|
+
l_elements_dict.update(**element_label_settings)
|
394
|
+
|
395
|
+
if ax is None and fig is None:
|
396
|
+
fig = plt.figure()
|
397
|
+
|
398
|
+
if ax == None and three_d:
|
399
|
+
ax = fig.gca(projection='3d')
|
400
|
+
elif ax == None:
|
401
|
+
ax = fig.gca()
|
402
|
+
elif three_d:
|
403
|
+
1
|
404
|
+
# ax.set(projection='3d') #mangler funksjonalitet her...
|
405
|
+
|
406
|
+
element_handles = [None]*len(element_matrix[:,0])
|
407
|
+
|
408
|
+
if plot_elements:
|
409
|
+
for element_ix, __ in enumerate(element_matrix[:,0]):
|
410
|
+
node1 = element_matrix[element_ix, 1]
|
411
|
+
node2 = element_matrix[element_ix, 2]
|
412
|
+
nodeix1 = np.where(node_matrix[:,0]==node1)[0]
|
413
|
+
nodeix2 = np.where(node_matrix[:,0]==node2)[0]
|
414
|
+
x01 = node_matrix[nodeix1,1:4]
|
415
|
+
x02 = node_matrix[nodeix2,1:4]
|
416
|
+
x0 = np.vstack([x01,x02])
|
417
|
+
|
418
|
+
if three_d:
|
419
|
+
element_handles[element_ix] = ax.plot(xs=x0[:,0], ys=x0[:,1], zs=x0[:,2], **e_dict)
|
420
|
+
else:
|
421
|
+
element_handles[element_ix] = ax.plot(x0[:,0], x0[:,1], **e_dict)
|
422
|
+
|
423
|
+
if element_labels:
|
424
|
+
xmean = np.mean(x0, axis=0)
|
425
|
+
if three_d:
|
426
|
+
ax.text(xmean[0],xmean[1],xmean[2],'%i' % element_matrix[element_ix,0], **l_elements_dict)
|
427
|
+
else:
|
428
|
+
ax.text(xmean[0],xmean[1],s='%i' % element_matrix[element_ix,0], **l_elements_dict)
|
429
|
+
|
430
|
+
if disp is not None:
|
431
|
+
disp_node1 = disp[nodeix1[0]*6:(nodeix1[0]*6+6)]
|
432
|
+
disp_node2 = disp[nodeix2[0]*6:(nodeix2[0]*6+6)]
|
433
|
+
x1 = x01+disp_node1[0:3]
|
434
|
+
x2 = x02+disp_node2[0:3]
|
435
|
+
x = np.vstack([x1,x2])
|
436
|
+
|
437
|
+
if three_d:
|
438
|
+
ax.plot(xs=x[:,0], ys=x[:,1], zs=x[:,2], **disp_dict)
|
439
|
+
else:
|
440
|
+
ax.plot(x[:,0], x[:,1], **disp_dict)
|
441
|
+
|
442
|
+
if plot_nodes:
|
443
|
+
if three_d:
|
444
|
+
ax.plot(xs=node_matrix[:, 1], ys=node_matrix[:, 2], zs=node_matrix[:, 3], **n_dict)
|
445
|
+
else:
|
446
|
+
ax.plot(node_matrix[:, 1], node_matrix[:, 2], **n_dict)
|
447
|
+
|
448
|
+
if chosen_nodes_ix != []:
|
449
|
+
if three_d:
|
450
|
+
ax.plot(xs=node_matrix[chosen_nodes_ix, 1], ys=node_matrix[chosen_nodes_ix, 2], zs=node_matrix[chosen_nodes_ix, 3], **n_chosen_dict)
|
451
|
+
else:
|
452
|
+
ax.plot(node_matrix[chosen_nodes_ix, 1], node_matrix[chosen_nodes_ix, 2], **n_chosen_dict)
|
453
|
+
|
454
|
+
if node_labels:
|
455
|
+
if three_d:
|
456
|
+
for node_ix in range(0, np.shape(node_matrix)[0]):
|
457
|
+
ax.text(node_matrix[node_ix, 1], node_matrix[node_ix, 2], node_matrix[node_ix, 3], '%i' % node_matrix[node_ix, 0], **l_nodes_dict)
|
458
|
+
else:
|
459
|
+
for node_ix in range(0, np.shape(node_matrix)[0]):
|
460
|
+
ax.text(node_matrix[node_ix, 1], node_matrix[node_ix, 2], '%i' % node_matrix[node_ix, 0], **l_nodes_dict)
|
461
|
+
|
462
|
+
if three_d:
|
463
|
+
equal_3d(ax)
|
464
|
+
else:
|
465
|
+
ax.set_aspect('equal', adjustable='box')
|
466
|
+
|
467
|
+
ax.grid('off')
|
468
|
+
return ax, element_handles
|
469
|
+
|
470
|
+
|
471
|
+
def plot_2d(S2d, x1, x2, ax=None, levels=80, discrete=False, **kwargs):
|
472
|
+
if ax is None:
|
473
|
+
ax = plt.gca()
|
474
|
+
|
475
|
+
X, Y = np.meshgrid(x1, x2)
|
476
|
+
if discrete:
|
477
|
+
contour = ax.pcolormesh(x1,x2,S2d, **kwargs)
|
478
|
+
else:
|
479
|
+
contour = ax.contourf(X, Y, S2d.T, levels=levels, **kwargs)
|
480
|
+
return contour
|
481
|
+
|
482
|
+
|
483
|
+
def plot_S2d(S, omega, theta, D=None, omega_range=None, theta_range=None):
|
484
|
+
|
485
|
+
if theta_range is None:
|
486
|
+
theta_range = [np.min(theta), np.max(theta)]
|
487
|
+
|
488
|
+
if omega_range is None:
|
489
|
+
omega_range = [0, np.max(omega)]
|
490
|
+
|
491
|
+
X, Y = np.meshgrid(omega, theta)
|
492
|
+
|
493
|
+
if D is None:
|
494
|
+
SD = S*1
|
495
|
+
else:
|
496
|
+
SD = S[:,np.newaxis] @ D[np.newaxis,:]
|
497
|
+
|
498
|
+
SD[np.isnan(SD)] = 0
|
499
|
+
|
500
|
+
plt.figure(2).clf()
|
501
|
+
fig = plt.figure(num=2, constrained_layout=True)
|
502
|
+
|
503
|
+
if D is not None:
|
504
|
+
widths = [2, 0.7]
|
505
|
+
heights = [0.7, 2.0, 0.7]
|
506
|
+
spec = fig.add_gridspec(ncols=2, nrows=3, width_ratios=widths,
|
507
|
+
height_ratios=heights, wspace=.1, hspace=.1)
|
508
|
+
else:
|
509
|
+
widths = [2]
|
510
|
+
heights = [2.0, 0.7]
|
511
|
+
spec = fig.add_gridspec(ncols=1, nrows=2, width_ratios=widths,
|
512
|
+
height_ratios=heights, wspace=.1, hspace=.1)
|
513
|
+
|
514
|
+
if D is not None:
|
515
|
+
ax = [None]*3
|
516
|
+
ax[0] = fig.add_subplot(spec[1,0]) # SD
|
517
|
+
ax[1] = fig.add_subplot(spec[0,0]) # S
|
518
|
+
ax[2] = fig.add_subplot(spec[1,1]) # D
|
519
|
+
ax[1].set_yticklabels('')
|
520
|
+
ax[2].set_xticklabels('')
|
521
|
+
ax[2].set_yticklabels('')
|
522
|
+
cbar_ax = fig.add_subplot(spec[2,0])
|
523
|
+
else:
|
524
|
+
ax = [fig.add_subplot(spec[0,0])]
|
525
|
+
cbar_ax = fig.add_subplot(spec[1,0])
|
526
|
+
|
527
|
+
cbar_ax.axis('off')
|
528
|
+
|
529
|
+
# Contour plot
|
530
|
+
contour = ax[0].contourf(X, Y, SD.T)
|
531
|
+
ax[0].set_ylim(theta_range)
|
532
|
+
ax[0].set_xlim(omega_range)
|
533
|
+
ax[0].set_ylabel(r'$\theta$ [rad]')
|
534
|
+
ax[0].set_xlabel(r'$\omega$ [rad/s]')
|
535
|
+
|
536
|
+
if D is not None:
|
537
|
+
# S line plot
|
538
|
+
ax[1].plot(omega, S)
|
539
|
+
ax[1].set_ylim(bottom=0)
|
540
|
+
ax[1].set_xlim(omega_range)
|
541
|
+
ax[1].set_xticklabels('')
|
542
|
+
ax[1].set_yticks([])
|
543
|
+
|
544
|
+
# D line plot
|
545
|
+
|
546
|
+
ax[2].plot(D, theta)
|
547
|
+
ax[2].set_ylim(theta_range)
|
548
|
+
ax[2].set_xlim(left=0)
|
549
|
+
ax[2].set_xticks([])
|
550
|
+
|
551
|
+
# cbar_ax.axis('off')
|
552
|
+
fig.colorbar(contour, ax=cbar_ax, orientation="horizontal", aspect=25, shrink=1.0)
|
553
|
+
|
554
|
+
ax[0].spines['top'].set_visible(False)
|
555
|
+
ax[0].spines['right'].set_visible(False)
|
556
|
+
|
557
|
+
if D is not None:
|
558
|
+
ax[1].spines['top'].set_visible(False)
|
559
|
+
ax[1].spines['right'].set_visible(False)
|
560
|
+
ax[1].set_ylabel(r'$S_\eta(\omega)$')
|
561
|
+
|
562
|
+
ax[2].spines['bottom'].set_visible(False)
|
563
|
+
ax[2].spines['right'].set_visible(False)
|
564
|
+
ax[2].set_xlabel(r'$D(\theta)$',rotation=-90)
|
565
|
+
ax[2].xaxis.set_label_position('top')
|
566
|
+
|
567
|
+
fig.subplots_adjust(top=0.97, bottom=0.08, left=0.16, right=0.97)
|
568
|
+
|
569
|
+
return fig
|
wawi/prob.py
ADDED
wawi/random.py
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
import numpy as np
|
2
|
+
|
3
|
+
def zero_crossing_period(S, omega):
|
4
|
+
return 2*np.pi*np.sqrt(np.trapz(S, x=omega)/np.trapz(omega**2*S, x=omega))
|
5
|
+
|
6
|
+
def stoch_mom(S, omega, n=0):
|
7
|
+
return np.trapz(S*omega**n, x=omega)
|
8
|
+
|
9
|
+
def m0(S, omega):
|
10
|
+
return stoch_mom(S, omega, n=0)
|
11
|
+
|
12
|
+
def m2(S, omega):
|
13
|
+
return stoch_mom(S, omega, n=2)
|
14
|
+
|
15
|
+
def v0_from_spectrum(S, omega):
|
16
|
+
return 1/(2*np.pi) * np.sqrt(m2(S, omega)/m0(S, omega))
|
17
|
+
|
18
|
+
def v0(m0,m2):
|
19
|
+
return 1/(2*np.pi) * np.sqrt(m2/m0)
|
20
|
+
|
21
|
+
def peakfactor(T, v0):
|
22
|
+
c = np.sqrt(2*np.log(v0*T))
|
23
|
+
kp = c + np.euler_gamma/c
|
24
|
+
return kp
|
25
|
+
|
26
|
+
def expmax(T, v0, std):
|
27
|
+
return peakfactor(T,v0)*std
|
28
|
+
|
29
|
+
def expmax_from_spectrum(S, omega, T):
|
30
|
+
m0_val = m0(S, omega)
|
31
|
+
std = np.sqrt(m0_val)
|
32
|
+
|
33
|
+
v0_val = v0(m0_val, m2(S, omega))
|
34
|
+
|
35
|
+
return expmax(T, v0_val, std)
|
36
|
+
|
37
|
+
def peakfactor_from_spectrum(S, omega, T):
|
38
|
+
return peakfactor(T, v0(S, omega))
|
wawi/signal.py
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
from .wave import jonswap
|
2
|
+
import numpy as np
|
3
|
+
from scipy.optimize import curve_fit
|
4
|
+
|
5
|
+
def fit_jonswap(S, w, sigma=[0.07, 0.09], initial_values=None):
|
6
|
+
if initial_values is None:
|
7
|
+
initial_values = {}
|
8
|
+
|
9
|
+
Hs0 = np.sqrt(np.trapz(S, w))*4
|
10
|
+
|
11
|
+
p0 = {'Hs': Hs0, 'Tp': 1, 'gamma': 1} #standard values of curve_fit are 1
|
12
|
+
p0.update(**initial_values)
|
13
|
+
|
14
|
+
if w[0]==0:
|
15
|
+
w = w[1:]
|
16
|
+
S = S[1:]
|
17
|
+
|
18
|
+
fun = lambda om, Hs, Tp, gamma: jonswap(Hs, Tp, gamma, sigma=sigma)(om)
|
19
|
+
popt,__ = curve_fit(fun, w, S)
|
20
|
+
out = dict(Hs=popt[0], Tp=popt[1], gamma=popt[2], p0=[p0['Hs'], p0['Tp'], p0['gamma']])
|
21
|
+
|
22
|
+
return out
|
23
|
+
|
24
|
+
def onesided_to_twosided(omega, S, axis=-1):
|
25
|
+
S2 = 0.5*np.concatenate([np.flip(S, axis=axis), S], axis=axis)
|
26
|
+
omega2 = np.hstack([np.flip(-omega), omega])
|
27
|
+
|
28
|
+
return omega2, S2
|
29
|
+
|
30
|
+
|
31
|
+
def twosided_to_onesided(omega, S):
|
32
|
+
n_samples = len(omega)
|
33
|
+
return omega[:n_samples//2], S[:,:,:n_samples//2]
|
34
|
+
|
35
|
+
|
36
|
+
def ramp_up(Nramp, Ntot):
|
37
|
+
t_scale = np.ones(Ntot)
|
38
|
+
t_scale[:Nramp] = np.linspace(0, 1, Nramp)
|
39
|
+
return t_scale
|
40
|
+
|
41
|
+
def ramp_up_t(t, t0):
|
42
|
+
Nramp = np.sum(t<t0)
|
43
|
+
Ntot = len(t)
|
44
|
+
|
45
|
+
return ramp_up(Nramp, Ntot)
|