RSSeismicScripting 3.0.0__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.
- rsseismic/Application.py +196 -0
- rsseismic/ApplicationManager.py +111 -0
- rsseismic/BedrockLayer.py +29 -0
- rsseismic/MeanProfile.py +169 -0
- rsseismic/MeanProfileSoilLayer.py +119 -0
- rsseismic/Model.py +204 -0
- rsseismic/Motions.py +140 -0
- rsseismic/ProfileGenerationSettings.py +29 -0
- rsseismic/Profiles.py +186 -0
- rsseismic/ProjectSettings.py +46 -0
- rsseismic/ReferenceCurve.py +73 -0
- rsseismic/Results.py +419 -0
- rsseismic/SoilLayer.py +34 -0
- rsseismic/SoilLayerCurve.py +124 -0
- rsseismic/SoilLayerOperations.py +120 -0
- rsseismic/__init__.py +79 -0
- rsseismic/_application_paths.py +74 -0
- rsseismic/_batch_compute.py +420 -0
- rsseismic/_client.py +81 -0
- rsseismic/_proto_converters.py +345 -0
- rsseismic/_proxyObject.py +11 -0
- rsseismic/_result_bulk_dataframes.py +202 -0
- rsseismic/_result_dataframes.py +77 -0
- rsseismic/_rpc_helpers.py +55 -0
- rsseismic/enums/__init__.py +23 -0
- rsseismic/enums/_generated.py +120 -0
- rsseismic/enums/fitting_procedure.py +15 -0
- rsseismic/exceptions.py +11 -0
- rsseismic/generatedFiles/ApplicationService_pb2.py +46 -0
- rsseismic/generatedFiles/ApplicationService_pb2.pyi +67 -0
- rsseismic/generatedFiles/ApplicationService_pb2_grpc.py +274 -0
- rsseismic/generatedFiles/BedrockLayerDataService_pb2.py +27 -0
- rsseismic/generatedFiles/BedrockLayerDataService_pb2.pyi +5 -0
- rsseismic/generatedFiles/BedrockLayerDataService_pb2_grpc.py +231 -0
- rsseismic/generatedFiles/CommonMessages_pb2.py +50 -0
- rsseismic/generatedFiles/CommonMessages_pb2.pyi +113 -0
- rsseismic/generatedFiles/CommonMessages_pb2_grpc.py +29 -0
- rsseismic/generatedFiles/MeanProfileService_pb2.py +62 -0
- rsseismic/generatedFiles/MeanProfileService_pb2.pyi +176 -0
- rsseismic/generatedFiles/MeanProfileService_pb2_grpc.py +458 -0
- rsseismic/generatedFiles/MeanProfileSoilLayerDataService_pb2.py +45 -0
- rsseismic/generatedFiles/MeanProfileSoilLayerDataService_pb2.pyi +87 -0
- rsseismic/generatedFiles/MeanProfileSoilLayerDataService_pb2_grpc.py +360 -0
- rsseismic/generatedFiles/ModelService_pb2.py +54 -0
- rsseismic/generatedFiles/ModelService_pb2.pyi +122 -0
- rsseismic/generatedFiles/ModelService_pb2_grpc.py +360 -0
- rsseismic/generatedFiles/MotionService_pb2.py +78 -0
- rsseismic/generatedFiles/MotionService_pb2.pyi +224 -0
- rsseismic/generatedFiles/MotionService_pb2_grpc.py +575 -0
- rsseismic/generatedFiles/ProfileGenerationSettingsService_pb2.py +27 -0
- rsseismic/generatedFiles/ProfileGenerationSettingsService_pb2.pyi +5 -0
- rsseismic/generatedFiles/ProfileGenerationSettingsService_pb2_grpc.py +145 -0
- rsseismic/generatedFiles/ProfileService_pb2.py +76 -0
- rsseismic/generatedFiles/ProfileService_pb2.pyi +246 -0
- rsseismic/generatedFiles/ProfileService_pb2_grpc.py +532 -0
- rsseismic/generatedFiles/ProjectSettingsDataService_pb2.py +35 -0
- rsseismic/generatedFiles/ProjectSettingsDataService_pb2.pyi +40 -0
- rsseismic/generatedFiles/ProjectSettingsDataService_pb2_grpc.py +232 -0
- rsseismic/generatedFiles/ReferenceCurveDataService_pb2.py +41 -0
- rsseismic/generatedFiles/ReferenceCurveDataService_pb2.pyi +73 -0
- rsseismic/generatedFiles/ReferenceCurveDataService_pb2_grpc.py +281 -0
- rsseismic/generatedFiles/ResultsService_pb2.py +82 -0
- rsseismic/generatedFiles/ResultsService_pb2.pyi +373 -0
- rsseismic/generatedFiles/ResultsService_pb2_grpc.py +489 -0
- rsseismic/generatedFiles/SoilLayerCurveDataService_pb2.py +52 -0
- rsseismic/generatedFiles/SoilLayerCurveDataService_pb2.pyi +150 -0
- rsseismic/generatedFiles/SoilLayerCurveDataService_pb2_grpc.py +280 -0
- rsseismic/generatedFiles/SoilLayerDataService_pb2.py +27 -0
- rsseismic/generatedFiles/SoilLayerDataService_pb2.pyi +5 -0
- rsseismic/generatedFiles/SoilLayerDataService_pb2_grpc.py +231 -0
- rsseismic/generatedFiles/SoilLayerService_pb2.py +46 -0
- rsseismic/generatedFiles/SoilLayerService_pb2.pyi +122 -0
- rsseismic/generatedFiles/SoilLayerService_pb2_grpc.py +317 -0
- rsseismic/generatedFiles/__init__.py +4 -0
- rsseismic/properties/_PropertyAccessor.py +151 -0
- rsseismic/properties/__init__.py +6 -0
- rsseismic/properties/bedrockLayer/__init__.py +1 -0
- rsseismic/properties/bedrockLayer/_generated.py +127 -0
- rsseismic/properties/meanProfileSoilLayer/__init__.py +1 -0
- rsseismic/properties/meanProfileSoilLayer/_generated.py +87 -0
- rsseismic/properties/profileGenerationSettings/__init__.py +1 -0
- rsseismic/properties/profileGenerationSettings/_generated.py +195 -0
- rsseismic/properties/projectSettings/__init__.py +1 -0
- rsseismic/properties/projectSettings/_generated.py +270 -0
- rsseismic/properties/referenceCurve/__init__.py +1 -0
- rsseismic/properties/referenceCurve/_generated.py +264 -0
- rsseismic/properties/soilLayer/__init__.py +1 -0
- rsseismic/properties/soilLayer/_generated.py +523 -0
- rsseismic/types.py +311 -0
- rsseismicscripting-3.0.0.dist-info/METADATA +88 -0
- rsseismicscripting-3.0.0.dist-info/RECORD +94 -0
- rsseismicscripting-3.0.0.dist-info/WHEEL +5 -0
- rsseismicscripting-3.0.0.dist-info/licenses/License.txt +20 -0
- rsseismicscripting-3.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
"""Convert protobuf messages to public types (internal)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from rsseismic.generatedFiles import MeanProfileService_pb2 as MeanProfileService_pb2
|
|
6
|
+
from rsseismic.generatedFiles import MotionService_pb2 as MotionService_pb2
|
|
7
|
+
from rsseismic.generatedFiles import ProfileService_pb2 as ProfileService_pb2
|
|
8
|
+
from rsseismic.generatedFiles import ReferenceCurveDataService_pb2 as ReferenceCurveDataService_pb2
|
|
9
|
+
from rsseismic.generatedFiles import ResultsService_pb2 as ResultsService_pb2
|
|
10
|
+
from rsseismic.generatedFiles import SoilLayerCurveDataService_pb2 as SoilLayerCurveDataService_pb2
|
|
11
|
+
from rsseismic.generatedFiles import SoilLayerService_pb2 as SoilLayerService_pb2
|
|
12
|
+
from rsseismic.types import (
|
|
13
|
+
ActiveProfile,
|
|
14
|
+
AppendLayersResult,
|
|
15
|
+
BedrockLayerSummary,
|
|
16
|
+
DeconvolutionLayerResultFiles,
|
|
17
|
+
DeleteLayerResult,
|
|
18
|
+
DiscretePoint,
|
|
19
|
+
DynamicsPoint,
|
|
20
|
+
GqHFittingLimits,
|
|
21
|
+
InsertLayerResult,
|
|
22
|
+
MeanProfileAppendLayersResult,
|
|
23
|
+
MeanProfileDeleteLayerResult,
|
|
24
|
+
MeanProfileInsertLayerResult,
|
|
25
|
+
MeanProfileMoveLayerResult,
|
|
26
|
+
MeanProfileSummary,
|
|
27
|
+
MotionInfo,
|
|
28
|
+
MotionPairInfo,
|
|
29
|
+
MoveLayerResult,
|
|
30
|
+
ProfileSummary,
|
|
31
|
+
ResultDatabaseInfo,
|
|
32
|
+
ResultLayerSummary,
|
|
33
|
+
ResultMotionSummary,
|
|
34
|
+
SoilLayerSummary,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def from_mean_profile_response(
|
|
39
|
+
response: MeanProfileService_pb2.GetMeanProfileResponse,
|
|
40
|
+
) -> MeanProfileSummary:
|
|
41
|
+
return MeanProfileSummary(
|
|
42
|
+
profileName=response.profileName,
|
|
43
|
+
layerCount=response.layerCount,
|
|
44
|
+
totalThickness=response.totalThickness,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def from_mean_profile_soil_layer_entry(
|
|
49
|
+
entry: MeanProfileService_pb2.SoilLayerEntry,
|
|
50
|
+
) -> SoilLayerSummary:
|
|
51
|
+
return SoilLayerSummary(
|
|
52
|
+
layerID=entry.layerID,
|
|
53
|
+
index1Based=entry.index1Based,
|
|
54
|
+
name=entry.name,
|
|
55
|
+
thickness=entry.thickness,
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def from_mean_profile_bedrock_layer_entry(
|
|
60
|
+
entry: MeanProfileService_pb2.BedrockLayerEntry,
|
|
61
|
+
) -> BedrockLayerSummary:
|
|
62
|
+
return BedrockLayerSummary(
|
|
63
|
+
layerID=entry.layerID,
|
|
64
|
+
name=entry.name,
|
|
65
|
+
thickness=entry.thickness,
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def from_mean_profile_insert_layer_response(
|
|
70
|
+
response: MeanProfileService_pb2.InsertLayerResponse,
|
|
71
|
+
) -> MeanProfileInsertLayerResult:
|
|
72
|
+
return MeanProfileInsertLayerResult(
|
|
73
|
+
layerID=response.layerID,
|
|
74
|
+
index1Based=response.index1Based,
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def from_mean_profile_append_layers_response(
|
|
79
|
+
response: MeanProfileService_pb2.AppendLayersResponse,
|
|
80
|
+
) -> MeanProfileAppendLayersResult:
|
|
81
|
+
return MeanProfileAppendLayersResult(layerIDs=tuple(response.layerIDs))
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def from_mean_profile_delete_layer_response(
|
|
85
|
+
response: MeanProfileService_pb2.DeleteLayerResponse,
|
|
86
|
+
) -> MeanProfileDeleteLayerResult:
|
|
87
|
+
return MeanProfileDeleteLayerResult(deletedLayerID=response.deletedLayerID)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def from_mean_profile_move_layer_response(
|
|
91
|
+
response: MeanProfileService_pb2.MoveLayerResponse,
|
|
92
|
+
) -> MeanProfileMoveLayerResult:
|
|
93
|
+
return MeanProfileMoveLayerResult(
|
|
94
|
+
layerID=response.layerID,
|
|
95
|
+
index1Based=response.index1Based,
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def from_profile_entry(entry: ProfileService_pb2.ProfileEntry) -> ProfileSummary:
|
|
100
|
+
return ProfileSummary(
|
|
101
|
+
name=entry.name,
|
|
102
|
+
isActive=entry.isActive,
|
|
103
|
+
layerCount=entry.layerCount,
|
|
104
|
+
totalThickness=entry.totalThickness,
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def from_active_profile_response(
|
|
109
|
+
response: ProfileService_pb2.GetActiveProfileResponse,
|
|
110
|
+
) -> ActiveProfile:
|
|
111
|
+
return ActiveProfile(
|
|
112
|
+
profileName=response.profileName,
|
|
113
|
+
layerCount=response.layerCount,
|
|
114
|
+
totalThickness=response.totalThickness,
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def from_soil_layer_entry(entry: ProfileService_pb2.SoilLayerEntry) -> SoilLayerSummary:
|
|
119
|
+
return SoilLayerSummary(
|
|
120
|
+
layerID=entry.layerID,
|
|
121
|
+
index1Based=entry.index1Based,
|
|
122
|
+
name=entry.name,
|
|
123
|
+
thickness=entry.thickness,
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def from_bedrock_layer_entry(entry: ProfileService_pb2.BedrockLayerEntry) -> BedrockLayerSummary:
|
|
128
|
+
return BedrockLayerSummary(
|
|
129
|
+
layerID=entry.layerID,
|
|
130
|
+
name=entry.name,
|
|
131
|
+
thickness=entry.thickness,
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def from_motion_entry(entry: MotionService_pb2.MotionEntry) -> MotionInfo:
|
|
136
|
+
return MotionInfo(
|
|
137
|
+
name=entry.name,
|
|
138
|
+
filePath=entry.filePath,
|
|
139
|
+
isSelected=entry.isSelected,
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def from_motion_pair_entry(entry: MotionService_pb2.MotionPairEntry) -> MotionPairInfo:
|
|
144
|
+
return MotionPairInfo(
|
|
145
|
+
pairId=entry.pairId,
|
|
146
|
+
motionH1Name=entry.motionH1Name,
|
|
147
|
+
motionH2Name=entry.motionH2Name,
|
|
148
|
+
motionH1FilePath=entry.motionH1FilePath,
|
|
149
|
+
motionH2FilePath=entry.motionH2FilePath,
|
|
150
|
+
isSelected=entry.isSelected,
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def _motion_type_name(motion_type: int) -> str:
|
|
155
|
+
return ResultsService_pb2.MotionType.Name(motion_type)
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def from_deconvolution_layer_files(
|
|
159
|
+
entry: ResultsService_pb2.DeconvolutionLayerResultFiles,
|
|
160
|
+
) -> DeconvolutionLayerResultFiles:
|
|
161
|
+
return DeconvolutionLayerResultFiles(
|
|
162
|
+
layerIndex=entry.layerIndex,
|
|
163
|
+
layerMotionPath=entry.layerMotionPath,
|
|
164
|
+
layerMotionExists=entry.layerMotionExists,
|
|
165
|
+
layerFasTransferFunctionPath=entry.layerFasTransferFunctionPath,
|
|
166
|
+
layerFasTransferFunctionExists=entry.layerFasTransferFunctionExists,
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def from_result_layer_entry(entry: ResultsService_pb2.ResultLayerEntry) -> ResultLayerSummary:
|
|
171
|
+
return ResultLayerSummary(
|
|
172
|
+
layerID=entry.layerID,
|
|
173
|
+
index1Based=entry.index1Based,
|
|
174
|
+
name=entry.name,
|
|
175
|
+
isTopOfRock=entry.isTopOfRock,
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def from_result_motion_entry(entry: ResultsService_pb2.ResultMotionEntry) -> ResultMotionSummary:
|
|
180
|
+
return ResultMotionSummary(
|
|
181
|
+
motionName=entry.motionName,
|
|
182
|
+
motionType=_motion_type_name(entry.motionType),
|
|
183
|
+
sourceMotionName=entry.sourceMotionName,
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def from_result_database_entry(entry: ResultsService_pb2.ResultDatabaseEntry) -> ResultDatabaseInfo:
|
|
188
|
+
return ResultDatabaseInfo(
|
|
189
|
+
profileName=entry.profileName,
|
|
190
|
+
motionName=entry.motionName,
|
|
191
|
+
motionType=_motion_type_name(entry.motionType),
|
|
192
|
+
resultsFolderPath=entry.resultsFolderPath,
|
|
193
|
+
resultDatabasePath=entry.resultDatabasePath,
|
|
194
|
+
resultDatabaseExists=entry.resultDatabaseExists,
|
|
195
|
+
complementaryResultDatabasePath=entry.complementaryResultDatabasePath,
|
|
196
|
+
complementaryResultDatabaseExists=entry.complementaryResultDatabaseExists,
|
|
197
|
+
inputFilePath=entry.inputFilePath,
|
|
198
|
+
inputFileExists=entry.inputFileExists,
|
|
199
|
+
strainConvergencePath=entry.strainConvergencePath,
|
|
200
|
+
strainConvergenceExists=entry.strainConvergenceExists,
|
|
201
|
+
strainNonConvergenceIdPath=entry.strainNonConvergenceIdPath,
|
|
202
|
+
strainNonConvergenceExists=entry.strainNonConvergenceExists,
|
|
203
|
+
deconvolutionBedrockMotionPath=entry.deconvolutionBedrockMotionPath,
|
|
204
|
+
deconvolutionBedrockMotionExists=entry.deconvolutionBedrockMotionExists,
|
|
205
|
+
deconvolutionBedrockFasTransferFunctionPath=entry.deconvolutionBedrockFasTransferFunctionPath,
|
|
206
|
+
deconvolutionBedrockFasTransferFunctionExists=entry.deconvolutionBedrockFasTransferFunctionExists,
|
|
207
|
+
deconvolutionLayerFiles=tuple(
|
|
208
|
+
from_deconvolution_layer_files(layer_file)
|
|
209
|
+
for layer_file in entry.deconvolutionLayerFiles
|
|
210
|
+
),
|
|
211
|
+
topOfRockOutputEnabled=entry.topOfRockOutputEnabled,
|
|
212
|
+
topOfRockLayerID=entry.topOfRockLayerID,
|
|
213
|
+
topOfRockLayerIndex1Based=entry.topOfRockLayerIndex1Based,
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def from_insert_layer_response(response: SoilLayerService_pb2.InsertLayerResponse) -> InsertLayerResult:
|
|
218
|
+
return InsertLayerResult(
|
|
219
|
+
profileName=response.profileName,
|
|
220
|
+
layerID=response.layerID,
|
|
221
|
+
index1Based=response.index1Based,
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
def from_append_layers_response(response: SoilLayerService_pb2.AppendLayersResponse) -> AppendLayersResult:
|
|
226
|
+
return AppendLayersResult(
|
|
227
|
+
profileName=response.profileName,
|
|
228
|
+
layerIDs=tuple(response.layerIDs),
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def from_delete_layer_response(response: SoilLayerService_pb2.DeleteLayerResponse) -> DeleteLayerResult:
|
|
233
|
+
return DeleteLayerResult(
|
|
234
|
+
profileName=response.profileName,
|
|
235
|
+
deletedLayerID=response.deletedLayerID,
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
def from_move_layer_response(response: SoilLayerService_pb2.MoveLayerResponse) -> MoveLayerResult:
|
|
240
|
+
return MoveLayerResult(
|
|
241
|
+
profileName=response.profileName,
|
|
242
|
+
layerID=response.layerID,
|
|
243
|
+
index1Based=response.index1Based,
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def to_gq_h_fitting_limits_proto(
|
|
248
|
+
limits: GqHFittingLimits,
|
|
249
|
+
) -> SoilLayerCurveDataService_pb2.GqHFittingLimits:
|
|
250
|
+
return SoilLayerCurveDataService_pb2.GqHFittingLimits(
|
|
251
|
+
enable_modulus_min=limits.enableModulusMin,
|
|
252
|
+
modulus_min=limits.modulusMin,
|
|
253
|
+
enable_modulus_max=limits.enableModulusMax,
|
|
254
|
+
modulus_max=limits.modulusMax,
|
|
255
|
+
enable_strength_min=limits.enableStrengthMin,
|
|
256
|
+
strength_min=limits.strengthMin,
|
|
257
|
+
enable_damp_min=limits.enableDampMin,
|
|
258
|
+
damp_min=limits.dampMin,
|
|
259
|
+
enable_damp_max=limits.enableDampMax,
|
|
260
|
+
damp_max=limits.dampMax,
|
|
261
|
+
enable_fix_theta3=limits.enableFixTheta3,
|
|
262
|
+
fix_theta3=limits.fixTheta3,
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def to_reference_curve_points(
|
|
267
|
+
points: list[DynamicsPoint],
|
|
268
|
+
) -> list[ReferenceCurveDataService_pb2.ReferenceCurvePoint]:
|
|
269
|
+
return [
|
|
270
|
+
ReferenceCurveDataService_pb2.ReferenceCurvePoint(
|
|
271
|
+
strain=point.strain,
|
|
272
|
+
ggmax=point.ggmax,
|
|
273
|
+
damping=point.damping,
|
|
274
|
+
strength=point.strength,
|
|
275
|
+
)
|
|
276
|
+
for point in points
|
|
277
|
+
]
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
def from_reference_curve_points(
|
|
281
|
+
points: list[ReferenceCurveDataService_pb2.ReferenceCurvePoint],
|
|
282
|
+
) -> list[DynamicsPoint]:
|
|
283
|
+
return [
|
|
284
|
+
DynamicsPoint(
|
|
285
|
+
strain=point.strain,
|
|
286
|
+
ggmax=point.ggmax,
|
|
287
|
+
damping=point.damping,
|
|
288
|
+
strength=point.strength,
|
|
289
|
+
)
|
|
290
|
+
for point in points
|
|
291
|
+
]
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
def to_dynamics_points(
|
|
295
|
+
points: list[DynamicsPoint],
|
|
296
|
+
) -> list[SoilLayerCurveDataService_pb2.SoilLayerDynamicsPoint]:
|
|
297
|
+
return [
|
|
298
|
+
SoilLayerCurveDataService_pb2.SoilLayerDynamicsPoint(
|
|
299
|
+
strain=point.strain,
|
|
300
|
+
ggmax=point.ggmax,
|
|
301
|
+
damping=point.damping,
|
|
302
|
+
strength=point.strength,
|
|
303
|
+
)
|
|
304
|
+
for point in points
|
|
305
|
+
]
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
def from_dynamics_points(
|
|
309
|
+
points: list[SoilLayerCurveDataService_pb2.SoilLayerDynamicsPoint],
|
|
310
|
+
) -> list[DynamicsPoint]:
|
|
311
|
+
return [
|
|
312
|
+
DynamicsPoint(
|
|
313
|
+
strain=point.strain,
|
|
314
|
+
ggmax=point.ggmax,
|
|
315
|
+
damping=point.damping,
|
|
316
|
+
strength=point.strength,
|
|
317
|
+
)
|
|
318
|
+
for point in points
|
|
319
|
+
]
|
|
320
|
+
|
|
321
|
+
|
|
322
|
+
def to_discrete_points(
|
|
323
|
+
points: list[DiscretePoint],
|
|
324
|
+
) -> list[SoilLayerCurveDataService_pb2.DiscreteCurvePoint]:
|
|
325
|
+
return [
|
|
326
|
+
SoilLayerCurveDataService_pb2.DiscreteCurvePoint(
|
|
327
|
+
strain=point.strain,
|
|
328
|
+
ggmax=point.ggmax,
|
|
329
|
+
damping=point.damping,
|
|
330
|
+
)
|
|
331
|
+
for point in points
|
|
332
|
+
]
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
def from_discrete_points(
|
|
336
|
+
points: list[SoilLayerCurveDataService_pb2.DiscreteCurvePoint],
|
|
337
|
+
) -> list[DiscretePoint]:
|
|
338
|
+
return [
|
|
339
|
+
DiscretePoint(
|
|
340
|
+
strain=point.strain,
|
|
341
|
+
ggmax=point.ggmax,
|
|
342
|
+
damping=point.damping,
|
|
343
|
+
)
|
|
344
|
+
for point in points
|
|
345
|
+
]
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from rsseismic._client import Client
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class _ProxyObject:
|
|
7
|
+
"""Base type for handles to objects owned by RSSeismic."""
|
|
8
|
+
|
|
9
|
+
def __init__(self, client: Client, objectId: str):
|
|
10
|
+
self._client = client
|
|
11
|
+
self._objectId = objectId
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"""Helpers for bulk result DataFrame queries (compose single-motion RPCs)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections.abc import Callable, Iterable, Sequence
|
|
6
|
+
|
|
7
|
+
import pandas as pd
|
|
8
|
+
|
|
9
|
+
from rsseismic.exceptions import ScriptingError
|
|
10
|
+
from rsseismic.generatedFiles import ResultsService_pb2 as ResultsService_pb2
|
|
11
|
+
from rsseismic.types import ResultDatabaseInfo, ResultMotionSummary, ResultMotionType
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def infer_el_convergence_motion_type_filter(
|
|
15
|
+
solution_type: str,
|
|
16
|
+
analysis_mode: str,
|
|
17
|
+
equivalent_linear: bool,
|
|
18
|
+
) -> frozenset[ResultMotionType] | None:
|
|
19
|
+
"""Mirror ResultsViewVM.GetELMotions motion-type rules for the convergence tab."""
|
|
20
|
+
if solution_type == "FrequencyDomain" and analysis_mode == "EquivalentLinear":
|
|
21
|
+
return None
|
|
22
|
+
|
|
23
|
+
if solution_type == "TimeDomain" and analysis_mode == "Nonlinear" and equivalent_linear:
|
|
24
|
+
return frozenset({ResultMotionType.COMPLEMENTARY_EQUIVALENT_LINEAR})
|
|
25
|
+
|
|
26
|
+
return frozenset()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def select_motion_names_from_result_motions(
|
|
30
|
+
motions: Iterable[ResultMotionSummary],
|
|
31
|
+
motion_type_filters: frozenset[ResultMotionType] | None,
|
|
32
|
+
) -> list[str]:
|
|
33
|
+
"""Distinct motion names from listResultMotions(), optionally filtered by type."""
|
|
34
|
+
if motion_type_filters is not None and len(motion_type_filters) == 0:
|
|
35
|
+
return []
|
|
36
|
+
|
|
37
|
+
motion_names: list[str] = []
|
|
38
|
+
seen: set[str] = set()
|
|
39
|
+
|
|
40
|
+
for motion in motions:
|
|
41
|
+
if not motion_type_matches_filters(motion.motionType, motion_type_filters):
|
|
42
|
+
continue
|
|
43
|
+
if motion.motionName in seen:
|
|
44
|
+
continue
|
|
45
|
+
seen.add(motion.motionName)
|
|
46
|
+
motion_names.append(motion.motionName)
|
|
47
|
+
|
|
48
|
+
return motion_names
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def select_convergence_tab_motion_names(
|
|
52
|
+
motions: Iterable[ResultMotionSummary],
|
|
53
|
+
motion_type_filters: frozenset[ResultMotionType] | None,
|
|
54
|
+
) -> list[str]:
|
|
55
|
+
"""Motions shown on the Check convergence tab (GetELMotions)."""
|
|
56
|
+
return select_motion_names_from_result_motions(motions, motion_type_filters)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def select_displacement_animation_motion_names(
|
|
60
|
+
motions: Iterable[ResultMotionSummary],
|
|
61
|
+
) -> list[str]:
|
|
62
|
+
"""All compute-aligned result motions (displacement animation tab motion list)."""
|
|
63
|
+
return select_motion_names_from_result_motions(motions, motion_type_filters=None)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def normalize_result_motion_type_filters(
|
|
67
|
+
motion_type_filters: Sequence[ResultMotionType] | None,
|
|
68
|
+
) -> frozenset[ResultMotionType] | None:
|
|
69
|
+
"""Return None when filters are empty (meaning all motion types)."""
|
|
70
|
+
if motion_type_filters is None:
|
|
71
|
+
return None
|
|
72
|
+
|
|
73
|
+
filters = tuple(motion_type_filters)
|
|
74
|
+
if len(filters) == 0:
|
|
75
|
+
return None
|
|
76
|
+
|
|
77
|
+
for item in filters:
|
|
78
|
+
if not isinstance(item, ResultMotionType):
|
|
79
|
+
raise TypeError(
|
|
80
|
+
f"motionTypeFilters must contain ResultMotionType values; got {type(item)!r}."
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
return frozenset(filters)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def result_motion_type_to_proto_name(motion_type: ResultMotionType) -> str:
|
|
87
|
+
if motion_type is ResultMotionType.COMPLEMENTARY_NONLINEAR_TOTAL_STRESS_LUMPED_MASS:
|
|
88
|
+
return ResultsService_pb2.MotionType.Name(
|
|
89
|
+
ResultsService_pb2.MOTION_TYPE_COMPLEMENTARY_NONLINEAR_TOTAL_STRESS
|
|
90
|
+
)
|
|
91
|
+
return ResultsService_pb2.MotionType.Name(int(motion_type))
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _result_motion_type_from_proto_name(proto_name: str) -> ResultMotionType:
|
|
95
|
+
if proto_name == "MOTION_TYPE_COMPLEMENTARY_NONLINEAR_TOTAL_STRESS":
|
|
96
|
+
return ResultMotionType.COMPLEMENTARY_NONLINEAR_TOTAL_STRESS_LUMPED_MASS
|
|
97
|
+
|
|
98
|
+
try:
|
|
99
|
+
proto_value = ResultsService_pb2.MotionType.Value(proto_name)
|
|
100
|
+
except ValueError as exc:
|
|
101
|
+
raise ValueError(f"Unknown result motion type: {proto_name!r}") from exc
|
|
102
|
+
|
|
103
|
+
return ResultMotionType(proto_value)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def motion_type_matches_filters(
|
|
107
|
+
motion_type_name: str,
|
|
108
|
+
motion_type_filters: frozenset[ResultMotionType] | None,
|
|
109
|
+
) -> bool:
|
|
110
|
+
if motion_type_filters is None:
|
|
111
|
+
return True
|
|
112
|
+
|
|
113
|
+
motion_type = _result_motion_type_from_proto_name(motion_type_name)
|
|
114
|
+
return motion_type in motion_type_filters
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
def select_profile_motion_names(
|
|
118
|
+
databases: Iterable[ResultDatabaseInfo],
|
|
119
|
+
profile_name: str,
|
|
120
|
+
motion_type_filters: frozenset[ResultMotionType] | None,
|
|
121
|
+
*,
|
|
122
|
+
require_strain_convergence: bool = False,
|
|
123
|
+
require_result_database: bool = False,
|
|
124
|
+
) -> list[str]:
|
|
125
|
+
"""Return distinct motion names for a profile from listResultDatabases entries."""
|
|
126
|
+
motion_names: list[str] = []
|
|
127
|
+
seen: set[str] = set()
|
|
128
|
+
|
|
129
|
+
for entry in databases:
|
|
130
|
+
if entry.profileName != profile_name:
|
|
131
|
+
continue
|
|
132
|
+
if require_strain_convergence and not entry.strainConvergenceExists:
|
|
133
|
+
continue
|
|
134
|
+
if require_result_database and not entry.resultDatabaseExists:
|
|
135
|
+
continue
|
|
136
|
+
if not motion_type_matches_filters(entry.motionType, motion_type_filters):
|
|
137
|
+
continue
|
|
138
|
+
if entry.motionName in seen:
|
|
139
|
+
continue
|
|
140
|
+
|
|
141
|
+
seen.add(entry.motionName)
|
|
142
|
+
motion_names.append(entry.motionName)
|
|
143
|
+
|
|
144
|
+
return motion_names
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def resolve_layer_ids(
|
|
148
|
+
layer_ids: Sequence[str] | None,
|
|
149
|
+
list_layers: Callable[[], Sequence[object]],
|
|
150
|
+
) -> list[str]:
|
|
151
|
+
if layer_ids is None or len(layer_ids) == 0:
|
|
152
|
+
return [layer.layerID for layer in list_layers()]
|
|
153
|
+
|
|
154
|
+
return list(layer_ids)
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def fetch_bulk_dataframes(
|
|
158
|
+
motion_names: Sequence[str],
|
|
159
|
+
fetch_one: Callable[[str], pd.DataFrame],
|
|
160
|
+
*,
|
|
161
|
+
skip_errors: bool,
|
|
162
|
+
) -> dict[str, pd.DataFrame]:
|
|
163
|
+
results: dict[str, pd.DataFrame] = {}
|
|
164
|
+
|
|
165
|
+
for motion_name in motion_names:
|
|
166
|
+
try:
|
|
167
|
+
results[motion_name] = fetch_one(motion_name)
|
|
168
|
+
except ScriptingError:
|
|
169
|
+
if not skip_errors:
|
|
170
|
+
raise
|
|
171
|
+
|
|
172
|
+
return results
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def fetch_bulk_layer_series_dataframes(
|
|
176
|
+
motion_names: Sequence[str],
|
|
177
|
+
layer_ids: Sequence[str],
|
|
178
|
+
fetch_one: Callable[[str, str], pd.DataFrame],
|
|
179
|
+
*,
|
|
180
|
+
skip_errors: bool,
|
|
181
|
+
) -> dict[tuple[str, str], pd.DataFrame]:
|
|
182
|
+
results: dict[tuple[str, str], pd.DataFrame] = {}
|
|
183
|
+
|
|
184
|
+
for motion_name in motion_names:
|
|
185
|
+
for layer_id in layer_ids:
|
|
186
|
+
key = (motion_name, layer_id)
|
|
187
|
+
try:
|
|
188
|
+
results[key] = fetch_one(motion_name, layer_id)
|
|
189
|
+
except ScriptingError:
|
|
190
|
+
if not skip_errors:
|
|
191
|
+
raise
|
|
192
|
+
|
|
193
|
+
return results
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
def fetch_bulk_profile_series_dataframes(
|
|
197
|
+
motion_names: Sequence[str],
|
|
198
|
+
fetch_one: Callable[[str], pd.DataFrame],
|
|
199
|
+
*,
|
|
200
|
+
skip_errors: bool,
|
|
201
|
+
) -> dict[str, pd.DataFrame]:
|
|
202
|
+
return fetch_bulk_dataframes(motion_names, fetch_one, skip_errors=skip_errors)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"""Convert ResultsService DataTable messages to pandas DataFrames (internal)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import pandas as pd
|
|
6
|
+
|
|
7
|
+
from rsseismic.generatedFiles import ResultsService_pb2 as ResultsService_pb2
|
|
8
|
+
from rsseismic.types import ResultSeriesKind
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def data_table_to_dataframe(table: ResultsService_pb2.DataTable) -> pd.DataFrame:
|
|
12
|
+
"""Build a DataFrame from a ResultsService DataTable proto message."""
|
|
13
|
+
column_count = len(table.columns)
|
|
14
|
+
data_count = len(table.data)
|
|
15
|
+
if column_count != data_count:
|
|
16
|
+
raise ValueError(
|
|
17
|
+
f"DataTable column count ({column_count}) does not match "
|
|
18
|
+
f"data column count ({data_count})."
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
frame_data = {
|
|
22
|
+
column_name: list(column.values)
|
|
23
|
+
for column_name, column in zip(table.columns, table.data)
|
|
24
|
+
}
|
|
25
|
+
dataframe = pd.DataFrame(frame_data)
|
|
26
|
+
|
|
27
|
+
if table.rowCount and len(dataframe) != table.rowCount:
|
|
28
|
+
raise ValueError(
|
|
29
|
+
f"DataTable rowCount ({table.rowCount}) does not match "
|
|
30
|
+
f"built DataFrame length ({len(dataframe)})."
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
if table.columnUnits:
|
|
34
|
+
dataframe.attrs["column_units"] = dict(zip(table.columns, table.columnUnits))
|
|
35
|
+
|
|
36
|
+
return dataframe
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def resolve_result_series_kind(kind: ResultSeriesKind | int | str) -> int:
|
|
40
|
+
"""Resolve a public ResultSeriesKind (or legacy int/str) to a proto enum value."""
|
|
41
|
+
if isinstance(kind, ResultSeriesKind):
|
|
42
|
+
return int(kind)
|
|
43
|
+
|
|
44
|
+
if isinstance(kind, int):
|
|
45
|
+
try:
|
|
46
|
+
return int(ResultSeriesKind(kind))
|
|
47
|
+
except ValueError as exc:
|
|
48
|
+
raise ValueError(f"Unknown result series kind value: {kind}") from exc
|
|
49
|
+
|
|
50
|
+
if isinstance(kind, str):
|
|
51
|
+
name = kind.strip()
|
|
52
|
+
if not name:
|
|
53
|
+
raise ValueError("Result series kind is required.")
|
|
54
|
+
|
|
55
|
+
if name.startswith("RESULT_SERIES_"):
|
|
56
|
+
member_name = name.removeprefix("RESULT_SERIES_")
|
|
57
|
+
try:
|
|
58
|
+
return int(ResultSeriesKind[member_name])
|
|
59
|
+
except KeyError:
|
|
60
|
+
pass
|
|
61
|
+
|
|
62
|
+
normalized = name.upper().replace("-", "_")
|
|
63
|
+
try:
|
|
64
|
+
return int(ResultSeriesKind[normalized])
|
|
65
|
+
except KeyError:
|
|
66
|
+
pass
|
|
67
|
+
|
|
68
|
+
upper_name = normalized
|
|
69
|
+
if not upper_name.startswith("RESULT_SERIES_"):
|
|
70
|
+
upper_name = f"RESULT_SERIES_{upper_name}"
|
|
71
|
+
|
|
72
|
+
if upper_name in ResultsService_pb2.ResultSeriesKind.keys():
|
|
73
|
+
return ResultsService_pb2.ResultSeriesKind.Value(upper_name)
|
|
74
|
+
|
|
75
|
+
raise ValueError(f"Unknown result series kind: {kind!r}")
|
|
76
|
+
|
|
77
|
+
raise TypeError(f"Unsupported result series kind type: {type(kind)!r}")
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"""Shared helpers for RSSeismic gRPC wrappers."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from enum import Enum
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from rsseismic.exceptions import ScriptingError
|
|
9
|
+
from rsseismic.generatedFiles import CommonMessages_pb2 as CommonMessages_pb2
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def require_success(response: Any, operation: str) -> None:
|
|
13
|
+
"""Raise ScriptingError when a response message has success=false."""
|
|
14
|
+
if getattr(response, "success", False):
|
|
15
|
+
return
|
|
16
|
+
message = getattr(response, "errorMessage", "") or f"{operation} failed."
|
|
17
|
+
raise ScriptingError(message)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def log_success_advisory(response: Any) -> None:
|
|
21
|
+
"""When success is true, log a non-empty errorMessage as a warning (server advisory)."""
|
|
22
|
+
if not getattr(response, "success", False):
|
|
23
|
+
return
|
|
24
|
+
advisory_message = getattr(response, "errorMessage", "") or ""
|
|
25
|
+
if advisory_message:
|
|
26
|
+
from rsseismic import logger
|
|
27
|
+
|
|
28
|
+
logger.warning(advisory_message)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def property_value_from_python(value: Any) -> CommonMessages_pb2.PropertyValue:
|
|
32
|
+
"""Build a CommonMessages PropertyValue from a Python scalar."""
|
|
33
|
+
if isinstance(value, CommonMessages_pb2.PropertyValue):
|
|
34
|
+
return value
|
|
35
|
+
if isinstance(value, bool):
|
|
36
|
+
return CommonMessages_pb2.PropertyValue(boolValue=value)
|
|
37
|
+
if isinstance(value, int):
|
|
38
|
+
return CommonMessages_pb2.PropertyValue(longValue=value)
|
|
39
|
+
if isinstance(value, float):
|
|
40
|
+
return CommonMessages_pb2.PropertyValue(doubleValue=value)
|
|
41
|
+
if isinstance(value, bytes):
|
|
42
|
+
return CommonMessages_pb2.PropertyValue(bytesValue=value)
|
|
43
|
+
if isinstance(value, Enum):
|
|
44
|
+
return CommonMessages_pb2.PropertyValue(enumValue=value.value)
|
|
45
|
+
if isinstance(value, str):
|
|
46
|
+
return CommonMessages_pb2.PropertyValue(stringValue=value)
|
|
47
|
+
raise TypeError(f"Unsupported property value type: {type(value)!r}")
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def property_value_to_python(value: CommonMessages_pb2.PropertyValue) -> Any:
|
|
51
|
+
"""Extract the Python scalar stored in a PropertyValue oneof."""
|
|
52
|
+
field = value.WhichOneof("value")
|
|
53
|
+
if field is None:
|
|
54
|
+
return None
|
|
55
|
+
return getattr(value, field)
|