xsection 0.0.0__tar.gz
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.
- xsection-0.0.0/PKG-INFO +11 -0
- xsection-0.0.0/README.md +2 -0
- xsection-0.0.0/pyproject.toml +44 -0
- xsection-0.0.0/setup.cfg +4 -0
- xsection-0.0.0/setup.py +20 -0
- xsection-0.0.0/src/xsection/ExtractModes.py +131 -0
- xsection-0.0.0/src/xsection/__init__.py +1 -0
- xsection-0.0.0/src/xsection/__main__.py +190 -0
- xsection-0.0.0/src/xsection/brace2/__main__.py +109 -0
- xsection-0.0.0/src/xsection/integrate.py +207 -0
- xsection-0.0.0/src/xsection/markov.py +54 -0
- xsection-0.0.0/src/xsection/modes.py +59 -0
- xsection-0.0.0/src/xsection/okid.py +580 -0
- xsection-0.0.0/src/xsection/realize.py +450 -0
- xsection-0.0.0/src/xsection/spec.py +14 -0
- xsection-0.0.0/src/xsection/srim.py +520 -0
- xsection-0.0.0/src/xsection/system.py +19 -0
- xsection-0.0.0/src/xsection/validation.py +43 -0
- xsection-0.0.0/src/xsection.egg-info/PKG-INFO +11 -0
- xsection-0.0.0/src/xsection.egg-info/SOURCES.txt +22 -0
- xsection-0.0.0/src/xsection.egg-info/dependency_links.txt +1 -0
- xsection-0.0.0/src/xsection.egg-info/entry_points.txt +2 -0
- xsection-0.0.0/src/xsection.egg-info/top_level.txt +1 -0
- xsection-0.0.0/tests/test1.py +139 -0
xsection-0.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: xsection
|
|
3
|
+
Version: 0.0.0
|
|
4
|
+
Author-email: "Claudio M. Perez" <50180406+claudioperez@users.noreply.github.com>
|
|
5
|
+
Project-URL: repository, http://github.com/BRACE2/xsection
|
|
6
|
+
Project-URL: documentation, https://brace2.github.io/xsection
|
|
7
|
+
Keywords: seismic,earthquake
|
|
8
|
+
Description-Content-Type: text/markdown
|
|
9
|
+
|
|
10
|
+
# `xsection`
|
|
11
|
+
|
xsection-0.0.0/README.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "xsection"
|
|
3
|
+
version = "0.0.0"
|
|
4
|
+
authors = [
|
|
5
|
+
{name="Claudio M. Perez", email="50180406+claudioperez@users.noreply.github.com"}
|
|
6
|
+
]
|
|
7
|
+
|
|
8
|
+
readme = "README.md"
|
|
9
|
+
|
|
10
|
+
keywords = [
|
|
11
|
+
"seismic",
|
|
12
|
+
"earthquake",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
[options]
|
|
16
|
+
#packages = find
|
|
17
|
+
install_requires = [
|
|
18
|
+
"numpy",
|
|
19
|
+
"scipy",
|
|
20
|
+
"tqdm",
|
|
21
|
+
"quakeio",
|
|
22
|
+
"matplotlib",
|
|
23
|
+
"plotly",
|
|
24
|
+
"pandas",
|
|
25
|
+
"control",
|
|
26
|
+
"sdof",
|
|
27
|
+
"opensees",
|
|
28
|
+
"quakeio"
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[project.urls]
|
|
32
|
+
repository = "http://github.com/BRACE2/xsection"
|
|
33
|
+
documentation = "https://brace2.github.io/xsection"
|
|
34
|
+
|
|
35
|
+
[project.scripts]
|
|
36
|
+
xsection = "xsection.__main__:main"
|
|
37
|
+
|
|
38
|
+
[build-system]
|
|
39
|
+
requires = [
|
|
40
|
+
"setuptools >= 52.0.2",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
build-backend = "setuptools.build_meta"
|
|
44
|
+
|
xsection-0.0.0/setup.cfg
ADDED
xsection-0.0.0/setup.py
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
from setuptools import setup
|
|
3
|
+
|
|
4
|
+
if __name__ == "__main__":
|
|
5
|
+
setup(
|
|
6
|
+
# name="opensees",
|
|
7
|
+
# cmake_install_dir="src/opensees",
|
|
8
|
+
# cmake_args = ["-DDependencies=Conda"],
|
|
9
|
+
# package_dir = {"": "src"},
|
|
10
|
+
# packages = ["opensees", "opensees.emit", "opensees.units"],
|
|
11
|
+
# #packages = find_packages("src"),
|
|
12
|
+
# py_modules = [
|
|
13
|
+
# splitext(basename(path))[0] for path in glob("src/*.py")
|
|
14
|
+
# ] + [
|
|
15
|
+
# splitext(basename(path))[0] for path in glob("src/units/*.py")
|
|
16
|
+
# ] + [
|
|
17
|
+
# splitext(basename(path))[0] for path in glob("src/emit/*.py")
|
|
18
|
+
# ]
|
|
19
|
+
)
|
|
20
|
+
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
from cmath import isclose
|
|
2
|
+
from numpy import pi, log, sign
|
|
3
|
+
from numpy.linalg import eig
|
|
4
|
+
import numpy as np
|
|
5
|
+
import scipy.linalg as sl
|
|
6
|
+
|
|
7
|
+
def condeig(a): # TODO: make this match matlab source code for condeig
|
|
8
|
+
"""
|
|
9
|
+
vals, vecs, conds = condeig(A) Computes condition numbers for the
|
|
10
|
+
eigenvalues of a matrix. The condition numbers are the reciprocals
|
|
11
|
+
of the cosines of the angles between the left and right eigenvectors.
|
|
12
|
+
Inspired by Arno Onken's Octave code for condeig.
|
|
13
|
+
|
|
14
|
+
https://github.com/macd/rogues/blob/master/rogues/utils/condeig.py
|
|
15
|
+
"""
|
|
16
|
+
m, n = a.shape
|
|
17
|
+
# eigenvalues, left and right eigenvectors
|
|
18
|
+
lamr, vl, vr = sl.eig(a, left=True, right=True)
|
|
19
|
+
vl = vl.T.conj()
|
|
20
|
+
# Normalize vectors
|
|
21
|
+
for i in range(n):
|
|
22
|
+
vl[i, :] = vl[i, :] / np.sqrt(abs(vl[i, :] ** 2).sum())
|
|
23
|
+
# Condition numbers are reciprocal of the cosines (dot products) of the
|
|
24
|
+
# left eignevectors with the right eigenvectors.
|
|
25
|
+
c = abs(1 / np.diag(np.dot(vl, vr)))
|
|
26
|
+
return vr, lamr, c
|
|
27
|
+
|
|
28
|
+
def ComposeModes(dt, A, B, C, D, debug=False, **kwds)->dict:
|
|
29
|
+
|
|
30
|
+
n = A.shape[0]
|
|
31
|
+
m = C.shape[0]
|
|
32
|
+
|
|
33
|
+
v, d, cnd = condeig(A) # eigenvectors (d) & eiegenvalues (v) of the matrix A
|
|
34
|
+
# kit = np.log(d) # logarithm of the eigenvalues
|
|
35
|
+
|
|
36
|
+
# a) Determination of modal frequencies (Eqs. 3.46 & 3.39)
|
|
37
|
+
sj1 = np.log(d)/dt # dt is the time step
|
|
38
|
+
freq1 = (np.real(sj1*np.conj(sj1))**0.5)/(2*pi)
|
|
39
|
+
|
|
40
|
+
roots = []
|
|
41
|
+
|
|
42
|
+
# selection of proper roots
|
|
43
|
+
if np.isclose(freq1[0], freq1[1]):
|
|
44
|
+
roots.append(0)
|
|
45
|
+
|
|
46
|
+
if np.isclose(freq1[n-1], freq1[n-2]):
|
|
47
|
+
roots.append(n-1)
|
|
48
|
+
|
|
49
|
+
for i in range(2, n-2):
|
|
50
|
+
if np.isclose(freq1[i], freq1[i+1]) or np.isclose(freq1[i], freq1[i-1]):
|
|
51
|
+
roots.append(i)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
# b) Determination of damping ratios (Eqs. 3.46 & 3.39)
|
|
55
|
+
damp1 = -((np.real(sj1))/(2*pi*freq1))
|
|
56
|
+
|
|
57
|
+
# Represent the identified frequency & damping information
|
|
58
|
+
# of the proper roots in a matrix
|
|
59
|
+
|
|
60
|
+
# NOTE: These values are stored in one array like this for legacy reasons,
|
|
61
|
+
# but this should be cleaned and a proper data structure should be used!
|
|
62
|
+
freqdmp = np.array([
|
|
63
|
+
[freq1[i], # first column: identified frequency
|
|
64
|
+
damp1[i], # second column: identified damping ratio
|
|
65
|
+
cnd[i]] # condition number of the eigenvalue
|
|
66
|
+
for i in roots
|
|
67
|
+
])
|
|
68
|
+
|
|
69
|
+
# c) Determination of mode shapes
|
|
70
|
+
modes_raw = C@v # mode shapes (Eq. 3.40)
|
|
71
|
+
|
|
72
|
+
modeshape = np.zeros((m,len(roots)), dtype=complex)
|
|
73
|
+
|
|
74
|
+
# extract mode shapes from mod corresponding to a frequency
|
|
75
|
+
for q,root in enumerate(roots):
|
|
76
|
+
modeshape[:m,q] = modes_raw[:m, root]
|
|
77
|
+
|
|
78
|
+
for q,root in enumerate(roots):
|
|
79
|
+
om = np.argmax(abs(np.real(modeshape[:,q])))
|
|
80
|
+
mx = abs(np.real(modeshape[om,q]))
|
|
81
|
+
modeshape[:,q] = np.real(modeshape[:,q])/mx*sign(np.real(modeshape[om,q]))
|
|
82
|
+
|
|
83
|
+
if debug:
|
|
84
|
+
return locals()
|
|
85
|
+
return freqdmp, modeshape, None, v, d
|
|
86
|
+
|
|
87
|
+
def modes(dt, A, C):
|
|
88
|
+
|
|
89
|
+
# eigendecomp A
|
|
90
|
+
Psi,Gam,cnd = condeig(A) # eigenvectors (Psi) & eigenvalues (Gam) of the matrix A
|
|
91
|
+
|
|
92
|
+
# get damping and frequencies from eigendecomp of A
|
|
93
|
+
Lam = (np.log(Gam))/dt
|
|
94
|
+
Omega = np.real((Lam*np.conj(Lam))**0.5) # radians per second. taking the real part because np keeps a +0j.
|
|
95
|
+
freq = Omega/(2*pi) # cycles per second (Hz)
|
|
96
|
+
damp = -np.real(Lam)/Omega
|
|
97
|
+
|
|
98
|
+
# get modeshapes from C and eigendecomp of A
|
|
99
|
+
modeshape = C @ Psi
|
|
100
|
+
|
|
101
|
+
# nroots = int(len(freq)/2)
|
|
102
|
+
# # print(f"{freq=}")
|
|
103
|
+
# for i in range(nroots):
|
|
104
|
+
# assert np.isclose(freq[2*i],freq[2*i+1]) # make sure we have pairs of roots
|
|
105
|
+
|
|
106
|
+
# modes = {str(i):
|
|
107
|
+
# {'cnd': cnd[2*i], # condition number of the eigenvalue
|
|
108
|
+
# 'freq': freq[2*i], # identified frequency
|
|
109
|
+
# 'damp': damp[2*i], # identified damping ratio
|
|
110
|
+
# 'modeshape': modeshape[:,2*i]
|
|
111
|
+
# }
|
|
112
|
+
# for i in range(nroots)
|
|
113
|
+
# }
|
|
114
|
+
|
|
115
|
+
# return modes
|
|
116
|
+
|
|
117
|
+
# weed out unique roots: get indices of roots that only show up once, and
|
|
118
|
+
# the index of the first of each pair.
|
|
119
|
+
_, notroots = np.unique(freq.round(decimals=5), return_index=True)
|
|
120
|
+
|
|
121
|
+
# print(notroots)
|
|
122
|
+
modes = {str(i):
|
|
123
|
+
{'cnd': cnd[i], # condition number of the eigenvalue
|
|
124
|
+
'freq': freq[i], # identified frequency
|
|
125
|
+
'damp': damp[i], # identified damping ratio
|
|
126
|
+
'modeshape': modeshape[:,i]
|
|
127
|
+
}
|
|
128
|
+
for i in range(len(freq)) if i not in notroots
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return modes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .system import system
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import json
|
|
3
|
+
|
|
4
|
+
import ssid
|
|
5
|
+
import ssid.modes
|
|
6
|
+
import quakeio
|
|
7
|
+
import numpy as np
|
|
8
|
+
from .okid import parse_okid
|
|
9
|
+
|
|
10
|
+
HELP = """
|
|
11
|
+
ssid [-p|w <>...] <method> <event> <inputs> <outputs>
|
|
12
|
+
ssid [-p|w <>...] <method> -i <inputs> -o <outputs>
|
|
13
|
+
|
|
14
|
+
-i/--inputs FILE... Input data
|
|
15
|
+
-o/--outputs FILE... Output data
|
|
16
|
+
|
|
17
|
+
Methods:
|
|
18
|
+
<method> <outputs> <plots>
|
|
19
|
+
srim {dftmcs} {m}
|
|
20
|
+
okid {dftmcs} {m}
|
|
21
|
+
spec {ft} {a}
|
|
22
|
+
four {ft} {a}
|
|
23
|
+
test
|
|
24
|
+
|
|
25
|
+
Outputs options
|
|
26
|
+
-p/--plot
|
|
27
|
+
a/--accel-spect
|
|
28
|
+
-w/--write
|
|
29
|
+
ABCD system matrices
|
|
30
|
+
d damping
|
|
31
|
+
freq frequency
|
|
32
|
+
cycl cyclic frequency
|
|
33
|
+
t period
|
|
34
|
+
m modes
|
|
35
|
+
c condition-number
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
class JSON_Encoder(json.JSONEncoder):
|
|
39
|
+
def default(self, obj):
|
|
40
|
+
if isinstance(obj, np.ndarray):
|
|
41
|
+
return obj.tolist()
|
|
42
|
+
elif isinstance(obj, np.integer):
|
|
43
|
+
return int(obj)
|
|
44
|
+
elif isinstance(obj, np.floating):
|
|
45
|
+
return float(obj)
|
|
46
|
+
return json.JSONEncoder.default(self, obj)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def parse_srim(argi, config):
|
|
50
|
+
help="""
|
|
51
|
+
SRIM -- System Identification with Information Matrix
|
|
52
|
+
|
|
53
|
+
Parameters
|
|
54
|
+
no order of the observer Kalman ARX filter (formerly p).
|
|
55
|
+
r size of the state-space model used for
|
|
56
|
+
representing the system. (formerly orm/n)
|
|
57
|
+
"""
|
|
58
|
+
config.update({"p" : 5, "orm": 4})
|
|
59
|
+
|
|
60
|
+
#argi = iter(args)
|
|
61
|
+
channels = [[], []]
|
|
62
|
+
for arg in argi:
|
|
63
|
+
if arg == "--arx-order":
|
|
64
|
+
config["no"] = int(next(argi))
|
|
65
|
+
|
|
66
|
+
elif arg == "--dt":
|
|
67
|
+
config["dt"] = float(next(argi))
|
|
68
|
+
|
|
69
|
+
elif arg == "--ss-size":
|
|
70
|
+
config["r"] = int(next(argi))
|
|
71
|
+
|
|
72
|
+
elif arg in ["--help", "-h"]:
|
|
73
|
+
print(help)
|
|
74
|
+
sys.exit()
|
|
75
|
+
|
|
76
|
+
elif arg == "--inputs":
|
|
77
|
+
inputs = next(argi)[1:-1].split(",")
|
|
78
|
+
if isinstance(inputs, str):
|
|
79
|
+
channels[0] = [int(inputs)]
|
|
80
|
+
else:
|
|
81
|
+
channels[0] = list(map(int, inputs))
|
|
82
|
+
|
|
83
|
+
elif arg == "--outputs":
|
|
84
|
+
outputs = next(argi)[1:-1].split(",")
|
|
85
|
+
if isinstance(outputs, str):
|
|
86
|
+
channels[1] = [int(outputs)]
|
|
87
|
+
else:
|
|
88
|
+
channels[1] = list(map(int, outputs))
|
|
89
|
+
|
|
90
|
+
elif arg == "--":
|
|
91
|
+
continue
|
|
92
|
+
|
|
93
|
+
else:
|
|
94
|
+
config["event_file"] = arg
|
|
95
|
+
|
|
96
|
+
event = quakeio.read(config["event_file"])
|
|
97
|
+
inputs = np.array([
|
|
98
|
+
event.match("l", station_channel=f"{i}").accel.data for i in channels[0]
|
|
99
|
+
]).T
|
|
100
|
+
outputs = np.array([
|
|
101
|
+
event.match("l", station_channel=f"{i}").accel.data for i in channels[1]
|
|
102
|
+
#event.at(file_name=f"CHAN{i:03d}.V2").accel.data for i in channels[1]
|
|
103
|
+
]).T
|
|
104
|
+
|
|
105
|
+
dt = event.at(station_channel=f"{channels[0][0]}").accel["time_step"]
|
|
106
|
+
config["dt"] = dt
|
|
107
|
+
|
|
108
|
+
A,B,C,D = ssid.system(input=inputs, output=outputs, full=True, **config)
|
|
109
|
+
|
|
110
|
+
ss_modes = ssid.modes.modes((A,B,C,D),dt)
|
|
111
|
+
|
|
112
|
+
output = [
|
|
113
|
+
{
|
|
114
|
+
"period": 1/mode["freq"],
|
|
115
|
+
"frequency": mode["freq"],
|
|
116
|
+
"damping": mode["damp"]
|
|
117
|
+
}
|
|
118
|
+
for mode in sorted(ss_modes.values(), key=lambda item: item["freq"])
|
|
119
|
+
]
|
|
120
|
+
|
|
121
|
+
print(json.dumps(output, cls=JSON_Encoder, indent=4))
|
|
122
|
+
return config
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def parse_args(args):
|
|
126
|
+
outputs = []
|
|
127
|
+
sub_parsers = {
|
|
128
|
+
"srim": parse_srim,
|
|
129
|
+
"test": parse_srim,
|
|
130
|
+
"okid": parse_okid,
|
|
131
|
+
"okid": parse_okid
|
|
132
|
+
}
|
|
133
|
+
config = {
|
|
134
|
+
"method": None,
|
|
135
|
+
"operation": None,
|
|
136
|
+
"protocol": None
|
|
137
|
+
}
|
|
138
|
+
config["channels"] = channels = [[], []]
|
|
139
|
+
|
|
140
|
+
argi = iter(args[1:])
|
|
141
|
+
for arg in argi:
|
|
142
|
+
if arg == "-p":
|
|
143
|
+
outputs.append(next(arg))
|
|
144
|
+
|
|
145
|
+
elif arg in ["--help", "-h"]:
|
|
146
|
+
print(HELP)
|
|
147
|
+
sys.exit()
|
|
148
|
+
|
|
149
|
+
elif arg == "--protocol":
|
|
150
|
+
config["protocol"] = next(arg)
|
|
151
|
+
|
|
152
|
+
elif arg == "--inputs":
|
|
153
|
+
inputs = next(argi)[1:-1].split(",")
|
|
154
|
+
if isinstance(inputs, str):
|
|
155
|
+
channels[0] = [int(inputs)]
|
|
156
|
+
else:
|
|
157
|
+
channels[0] = list(map(int, inputs))
|
|
158
|
+
|
|
159
|
+
elif arg == "--outputs":
|
|
160
|
+
outputs = next(argi)[1:-1].split(",")
|
|
161
|
+
if isinstance(outputs, str):
|
|
162
|
+
channels[1] = [int(outputs)]
|
|
163
|
+
else:
|
|
164
|
+
channels[1] = list(map(int, outputs))
|
|
165
|
+
|
|
166
|
+
# Positional args
|
|
167
|
+
elif config["method"] is None:
|
|
168
|
+
config["method"] = arg
|
|
169
|
+
break
|
|
170
|
+
|
|
171
|
+
# elif config["protocol"] and config["operation"] is None:
|
|
172
|
+
# config["operation"] = arg
|
|
173
|
+
|
|
174
|
+
elif arg == "--":
|
|
175
|
+
continue
|
|
176
|
+
|
|
177
|
+
else:
|
|
178
|
+
print(HELP)
|
|
179
|
+
sys.exit()
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
return sub_parsers[config.pop("method")](argi, config), outputs
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def main():
|
|
186
|
+
parse_args(sys.argv)
|
|
187
|
+
|
|
188
|
+
if __name__ == "__main__":
|
|
189
|
+
main()
|
|
190
|
+
sys.exit()
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
from .srim import parse_srim
|
|
2
|
+
from .okid import parse_okid
|
|
3
|
+
|
|
4
|
+
HELP = """
|
|
5
|
+
ssid [-p|w <>...] <method> <event> <inputs> <outputs>
|
|
6
|
+
ssid [-p|w <>...] <method> -i <inputs> -o <outputs>
|
|
7
|
+
|
|
8
|
+
-i/--inputs FILE... Input data
|
|
9
|
+
-o/--outputs FILE... Output data
|
|
10
|
+
|
|
11
|
+
Methods:
|
|
12
|
+
<method> <outputs> <plots>
|
|
13
|
+
srim {dftmcs} {m}
|
|
14
|
+
okid {dftmcs} {m}
|
|
15
|
+
spec {ft} {a}
|
|
16
|
+
four {ft} {a}
|
|
17
|
+
test
|
|
18
|
+
|
|
19
|
+
Outputs options
|
|
20
|
+
-p/--plot
|
|
21
|
+
a/--accel-spect
|
|
22
|
+
-w/--write
|
|
23
|
+
ABCD system matrices
|
|
24
|
+
d damping
|
|
25
|
+
freq frequency
|
|
26
|
+
cycl cyclic frequency
|
|
27
|
+
t period
|
|
28
|
+
m modes
|
|
29
|
+
c condition-number
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def parse_args(args):
|
|
34
|
+
outputs = []
|
|
35
|
+
parsers = {
|
|
36
|
+
"srim": parse_srim,
|
|
37
|
+
"test": parse_srim,
|
|
38
|
+
"okid": parse_okid
|
|
39
|
+
}
|
|
40
|
+
config = {}
|
|
41
|
+
argi = iter(args[1:])
|
|
42
|
+
for arg in argi:
|
|
43
|
+
if arg == "-p":
|
|
44
|
+
outputs.append(next(arg))
|
|
45
|
+
if arg == "--setup":
|
|
46
|
+
install_me()
|
|
47
|
+
sys.exit()
|
|
48
|
+
elif arg in ["--help", "-h"]:
|
|
49
|
+
print(HELP)
|
|
50
|
+
sys.exit()
|
|
51
|
+
else:
|
|
52
|
+
config["method"] = arg
|
|
53
|
+
return parsers[arg](argi, config), outputs
|
|
54
|
+
|
|
55
|
+
if __name__ == "__main__":
|
|
56
|
+
import sys
|
|
57
|
+
import quakeio
|
|
58
|
+
import numpy as np
|
|
59
|
+
from pathlib import Path
|
|
60
|
+
channels = [[17, 3, 20], [9, 7, 4]]
|
|
61
|
+
method = None
|
|
62
|
+
|
|
63
|
+
config, out_ops = parse_args(sys.argv)
|
|
64
|
+
|
|
65
|
+
if config["method"] == "test":
|
|
66
|
+
data_dir = Path("RioDell_Petrolia_Processed_Data")
|
|
67
|
+
|
|
68
|
+
first_input = quakeio.read(data_dir/f"CHAN{channels[0][0]:03d}.V2")
|
|
69
|
+
npoints = len(first_input.accel.data)
|
|
70
|
+
inputs, outputs = np.zeros((2,npoints,len(channels[0])))
|
|
71
|
+
|
|
72
|
+
# Inputs
|
|
73
|
+
inputs[:,0] = first_input.accel.data
|
|
74
|
+
for i,inp in enumerate(channels[0][1:]):
|
|
75
|
+
inputs[:,i+1] = quakeio.read(data_dir/f"CHAN{inp:03d}.V2").accel.data
|
|
76
|
+
|
|
77
|
+
# Outputs
|
|
78
|
+
for i,inp in enumerate(channels[1]):
|
|
79
|
+
outputs[:,i] = quakeio.read(data_dir/f"CHAN{inp:03d}.V2").accel.data
|
|
80
|
+
|
|
81
|
+
dt = first_input.accel["time_step"]
|
|
82
|
+
config["dt"] = dt
|
|
83
|
+
|
|
84
|
+
elif "event_file" in config:
|
|
85
|
+
event = quakeio.read(config["event_file"])
|
|
86
|
+
inputs = np.array([
|
|
87
|
+
event.at(file_name=f"CHAN{i:03d}.V2").accel.data for i in channels[0]
|
|
88
|
+
]).T
|
|
89
|
+
outputs = np.array([
|
|
90
|
+
event.at(file_name=f"CHAN{i:03d}.V2").accel.data for i in channels[1]
|
|
91
|
+
]).T
|
|
92
|
+
npoints = len(inputs[:,0])
|
|
93
|
+
dt = event.at(file_name=f"CHAN{channels[0][0]:03d}.V2").accel["time_step"]
|
|
94
|
+
config["dt"] = dt
|
|
95
|
+
|
|
96
|
+
#print(config)
|
|
97
|
+
|
|
98
|
+
A,B,C,D = srim(inputs, outputs, **config)
|
|
99
|
+
|
|
100
|
+
freqdmpSRIM, modeshapeSRIM, *_ = ComposeModes(dt, A, B, C, D)
|
|
101
|
+
|
|
102
|
+
if not out_ops:
|
|
103
|
+
print(f"period: {np.real(1/freqdmpSRIM[:,0])}")
|
|
104
|
+
elif "freq" in out_ops:
|
|
105
|
+
print(f"frequency: {freqdmpSRIM[:,0]}")
|
|
106
|
+
elif "cycl" in out_ops:
|
|
107
|
+
print(f"cyclic_frequency: {2*np.pi*freqdmpSRIM[:,0]}")
|
|
108
|
+
|
|
109
|
+
|