wawi 0.0.1__py3-none-any.whl → 0.0.3__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- wawi/__init__.py +8 -4
- wawi/abq.py +1128 -0
- wawi/fe.py +134 -0
- wawi/general.py +473 -0
- wawi/identification.py +66 -0
- wawi/io.py +696 -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 +1108 -0
- wawi/wind_code.py +14 -0
- {wawi-0.0.1.dist-info → wawi-0.0.3.dist-info}/METADATA +7 -6
- wawi-0.0.3.dist-info/RECORD +22 -0
- wawi-0.0.1.dist-info/RECORD +0 -6
- {wawi-0.0.1.dist-info → wawi-0.0.3.dist-info}/LICENSE +0 -0
- {wawi-0.0.1.dist-info → wawi-0.0.3.dist-info}/WHEEL +0 -0
- {wawi-0.0.1.dist-info → wawi-0.0.3.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)
|