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
rsseismic/Model.py
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
|
|
5
|
+
from rsseismic._client import Client
|
|
6
|
+
from rsseismic._proxyObject import _ProxyObject
|
|
7
|
+
from rsseismic._rpc_helpers import require_success
|
|
8
|
+
from rsseismic.exceptions import ScriptingError
|
|
9
|
+
from rsseismic.generatedFiles import ModelService_pb2 as ModelService_pb2
|
|
10
|
+
from rsseismic.generatedFiles import ModelService_pb2_grpc as ModelService_pb2_grpc
|
|
11
|
+
from rsseismic.MeanProfile import MeanProfile
|
|
12
|
+
from rsseismic.Motions import Motions
|
|
13
|
+
from rsseismic.ProfileGenerationSettings import ProfileGenerationSettings
|
|
14
|
+
from rsseismic.Profiles import Profiles
|
|
15
|
+
from rsseismic.ProjectSettings import ProjectSettings
|
|
16
|
+
from rsseismic.Results import Results
|
|
17
|
+
from rsseismic.SoilLayerOperations import SoilLayerOperations
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dataclass(frozen=True)
|
|
21
|
+
class RunComputeResult:
|
|
22
|
+
"""Outcome of ``Model.runCompute()``."""
|
|
23
|
+
|
|
24
|
+
success: bool
|
|
25
|
+
partialSuccess: bool
|
|
26
|
+
errorMessage: str
|
|
27
|
+
|
|
28
|
+
@property
|
|
29
|
+
def ok(self) -> bool:
|
|
30
|
+
"""True when every selected profile and motion pair completed successfully."""
|
|
31
|
+
return self.success and not self.partialSuccess
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@dataclass(frozen=True)
|
|
35
|
+
class GenerateProfilesResult:
|
|
36
|
+
"""Outcome of ``Model.generateProfiles()``."""
|
|
37
|
+
|
|
38
|
+
success: bool
|
|
39
|
+
errorMessage: str
|
|
40
|
+
validationErrors: list[str]
|
|
41
|
+
profileCount: int
|
|
42
|
+
profileNames: list[str]
|
|
43
|
+
hasBeenGenerated: bool
|
|
44
|
+
|
|
45
|
+
@property
|
|
46
|
+
def ok(self) -> bool:
|
|
47
|
+
"""True when profile generation completed successfully."""
|
|
48
|
+
return self.success
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@dataclass(frozen=True)
|
|
52
|
+
class ResetGeneratedProfilesResult:
|
|
53
|
+
"""Outcome of ``Model.resetGeneratedProfiles()``."""
|
|
54
|
+
|
|
55
|
+
success: bool
|
|
56
|
+
errorMessage: str
|
|
57
|
+
hasBeenGenerated: bool
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class Model(_ProxyObject):
|
|
61
|
+
"""
|
|
62
|
+
Handle for an open RSSeismic project.
|
|
63
|
+
|
|
64
|
+
Obtain a ``Model`` from ``RSSeismicApplication.openFile(path)`` or
|
|
65
|
+
``RSSeismicApplication.newProject()``.
|
|
66
|
+
|
|
67
|
+
Use the attributes on this object to work with project data: ``Profiles``,
|
|
68
|
+
``Motions``, ``Results``, ``MeanProfile``, ``ProjectSettings``,
|
|
69
|
+
``ProfileGenerationSettings``, and ``SoilLayers``.
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
def __init__(self, client: Client, modelId: str):
|
|
73
|
+
super().__init__(client, modelId)
|
|
74
|
+
self._model_service = ModelService_pb2_grpc.ModelServiceStub(self._client.channel)
|
|
75
|
+
self.Motions = Motions(client, modelId)
|
|
76
|
+
self.Profiles = Profiles(client, modelId)
|
|
77
|
+
self.ProjectSettings = ProjectSettings(client, modelId)
|
|
78
|
+
self.ProfileGenerationSettings = ProfileGenerationSettings(client, modelId)
|
|
79
|
+
self.MeanProfile = MeanProfile(client, modelId)
|
|
80
|
+
self.SoilLayers = SoilLayerOperations(client, modelId)
|
|
81
|
+
self.Results = Results(client, modelId)
|
|
82
|
+
|
|
83
|
+
@property
|
|
84
|
+
def modelId(self) -> str:
|
|
85
|
+
return self._objectId
|
|
86
|
+
|
|
87
|
+
def save(self) -> None:
|
|
88
|
+
"""Save the project to its current file path."""
|
|
89
|
+
request = ModelService_pb2.SaveRequest(modelID=self._objectId)
|
|
90
|
+
response = self._client.callFunction(self._model_service.Save, request)
|
|
91
|
+
require_success(response, "Save")
|
|
92
|
+
|
|
93
|
+
def saveAs(self, filePath: str) -> None:
|
|
94
|
+
"""Save the project to a new file path."""
|
|
95
|
+
request = ModelService_pb2.SaveAsRequest(modelID=self._objectId, filePath=filePath)
|
|
96
|
+
response = self._client.callFunction(self._model_service.SaveAs, request)
|
|
97
|
+
require_success(response, "SaveAs")
|
|
98
|
+
|
|
99
|
+
def close(self, saveProject: bool = False) -> None:
|
|
100
|
+
"""
|
|
101
|
+
Close the project in RSSeismic.
|
|
102
|
+
|
|
103
|
+
When ``saveProject`` is True, the project is saved before it is closed.
|
|
104
|
+
"""
|
|
105
|
+
request = ModelService_pb2.CloseRequest(
|
|
106
|
+
modelID=self._objectId,
|
|
107
|
+
saveProject=saveProject,
|
|
108
|
+
)
|
|
109
|
+
response = self._client.callFunction(self._model_service.Close, request)
|
|
110
|
+
require_success(response, "Close")
|
|
111
|
+
|
|
112
|
+
def runCompute(self, timeout: float | None = None) -> RunComputeResult:
|
|
113
|
+
"""
|
|
114
|
+
Run analysis for all selected profile and motion combinations.
|
|
115
|
+
|
|
116
|
+
Returns a ``RunComputeResult``. Check ``result.ok`` for full success.
|
|
117
|
+
When ``partialSuccess`` is True, some pairs completed but others failed;
|
|
118
|
+
see ``errorMessage`` for details.
|
|
119
|
+
|
|
120
|
+
Optional ``timeout`` is the maximum wait time in seconds for long runs.
|
|
121
|
+
When omitted, the call waits until compute finishes.
|
|
122
|
+
"""
|
|
123
|
+
request = ModelService_pb2.RunComputeRequest(modelID=self._objectId)
|
|
124
|
+
response = self._client.callFunction(
|
|
125
|
+
self._model_service.RunCompute,
|
|
126
|
+
request,
|
|
127
|
+
timeout=timeout,
|
|
128
|
+
)
|
|
129
|
+
return RunComputeResult(
|
|
130
|
+
success=response.success,
|
|
131
|
+
partialSuccess=response.partialSuccess,
|
|
132
|
+
errorMessage=response.errorMessage or "",
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
def clearResults(self) -> None:
|
|
136
|
+
"""Remove stored analysis results from the project."""
|
|
137
|
+
request = ModelService_pb2.ClearResultsRequest(modelID=self._objectId)
|
|
138
|
+
response = self._client.callFunction(self._model_service.ClearResults, request)
|
|
139
|
+
require_success(response, "ClearResults")
|
|
140
|
+
|
|
141
|
+
def resetGeneratedProfiles(self) -> ResetGeneratedProfilesResult:
|
|
142
|
+
"""
|
|
143
|
+
Clear the generated-profiles state so profiles can be generated again.
|
|
144
|
+
|
|
145
|
+
Does not remove profiles already in the project. Requires automatic profile
|
|
146
|
+
generation to be enabled in project settings.
|
|
147
|
+
"""
|
|
148
|
+
request = ModelService_pb2.ResetGeneratedProfilesRequest(modelID=self._objectId)
|
|
149
|
+
response = self._client.callFunction(
|
|
150
|
+
self._model_service.ResetGeneratedProfiles,
|
|
151
|
+
request,
|
|
152
|
+
)
|
|
153
|
+
require_success(response, "ResetGeneratedProfiles")
|
|
154
|
+
return ResetGeneratedProfilesResult(
|
|
155
|
+
success=response.success,
|
|
156
|
+
errorMessage=response.errorMessage or "",
|
|
157
|
+
hasBeenGenerated=response.hasBeenGenerated,
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
def generateProfiles(
|
|
161
|
+
self,
|
|
162
|
+
seed: int = 0,
|
|
163
|
+
timeout: float | None = None,
|
|
164
|
+
) -> GenerateProfilesResult:
|
|
165
|
+
"""
|
|
166
|
+
Create individual profiles from the mean profile template.
|
|
167
|
+
|
|
168
|
+
Validates ``model.MeanProfile`` first, then replaces the profiles in the
|
|
169
|
+
project with the newly generated set. Configure how many profiles to create
|
|
170
|
+
with ``model.ProfileGenerationSettings`` before calling this method.
|
|
171
|
+
|
|
172
|
+
When ``seed`` is 0, RSSeismic chooses a random seed. Use a fixed seed to
|
|
173
|
+
reproduce the same generated profiles.
|
|
174
|
+
|
|
175
|
+
Optional ``timeout`` is the maximum wait time in seconds. When omitted, the
|
|
176
|
+
call waits until generation finishes.
|
|
177
|
+
|
|
178
|
+
Raises:
|
|
179
|
+
ScriptingError: Validation failed or generation could not complete.
|
|
180
|
+
"""
|
|
181
|
+
request = ModelService_pb2.GenerateProfilesRequest(
|
|
182
|
+
modelID=self._objectId,
|
|
183
|
+
seed=seed,
|
|
184
|
+
)
|
|
185
|
+
response = self._client.callFunction(
|
|
186
|
+
self._model_service.GenerateProfiles,
|
|
187
|
+
request,
|
|
188
|
+
timeout=timeout,
|
|
189
|
+
)
|
|
190
|
+
if not response.success:
|
|
191
|
+
message = response.errorMessage or "GenerateProfiles failed."
|
|
192
|
+
if response.validationErrors:
|
|
193
|
+
details = "\n".join(f"- {error}" for error in response.validationErrors)
|
|
194
|
+
message = f"{message}\n{details}"
|
|
195
|
+
raise ScriptingError(message)
|
|
196
|
+
|
|
197
|
+
return GenerateProfilesResult(
|
|
198
|
+
success=response.success,
|
|
199
|
+
errorMessage=response.errorMessage or "",
|
|
200
|
+
validationErrors=list(response.validationErrors),
|
|
201
|
+
profileCount=response.profileCount,
|
|
202
|
+
profileNames=list(response.profileNames),
|
|
203
|
+
hasBeenGenerated=response.hasBeenGenerated,
|
|
204
|
+
)
|
rsseismic/Motions.py
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from rsseismic._client import Client
|
|
4
|
+
from rsseismic._proto_converters import from_motion_entry, from_motion_pair_entry
|
|
5
|
+
from rsseismic._proxyObject import _ProxyObject
|
|
6
|
+
from rsseismic._rpc_helpers import log_success_advisory, require_success
|
|
7
|
+
from rsseismic.generatedFiles import MotionService_pb2 as MotionService_pb2
|
|
8
|
+
from rsseismic.generatedFiles import MotionService_pb2_grpc as MotionService_pb2_grpc
|
|
9
|
+
from rsseismic.types import MotionInfo, MotionPairInfo
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class Motions(_ProxyObject):
|
|
13
|
+
"""Ground motion directories, scanning, listing, and selection for an open model."""
|
|
14
|
+
|
|
15
|
+
def __init__(self, client: Client, modelId: str):
|
|
16
|
+
super().__init__(client, modelId)
|
|
17
|
+
self._motion_service = MotionService_pb2_grpc.MotionServiceStub(self._client.channel)
|
|
18
|
+
|
|
19
|
+
def listMotionDirectories(self) -> list[str]:
|
|
20
|
+
"""Return motion directories currently associated with this project."""
|
|
21
|
+
request = MotionService_pb2.ListMotionDirectoriesRequest(modelID=self._objectId)
|
|
22
|
+
response = self._client.callFunction(self._motion_service.ListMotionDirectories, request)
|
|
23
|
+
require_success(response, "ListMotionDirectories")
|
|
24
|
+
return list(response.directories)
|
|
25
|
+
|
|
26
|
+
def addMotionDirectory(self, motionDirectory: str) -> list[str]:
|
|
27
|
+
"""
|
|
28
|
+
Add a folder to app motion-directory preferences (global, not project-specific).
|
|
29
|
+
|
|
30
|
+
Returns the updated list of preference directories. If the directory is already
|
|
31
|
+
listed, the server returns success with a warning.
|
|
32
|
+
"""
|
|
33
|
+
request = MotionService_pb2.AddMotionDirectoryRequest(motionDirectory=motionDirectory)
|
|
34
|
+
response = self._client.callFunction(self._motion_service.AddMotionDirectory, request)
|
|
35
|
+
require_success(response, "AddMotionDirectory")
|
|
36
|
+
log_success_advisory(response)
|
|
37
|
+
return list(response.directories)
|
|
38
|
+
|
|
39
|
+
def removeMotionDirectory(self, motionDirectory: str) -> list[str]:
|
|
40
|
+
"""
|
|
41
|
+
Remove a folder from app motion-directory preferences.
|
|
42
|
+
|
|
43
|
+
At least one directory must remain. Returns the updated preference list.
|
|
44
|
+
"""
|
|
45
|
+
request = MotionService_pb2.RemoveMotionDirectoryRequest(motionDirectory=motionDirectory)
|
|
46
|
+
response = self._client.callFunction(self._motion_service.RemoveMotionDirectory, request)
|
|
47
|
+
require_success(response, "RemoveMotionDirectory")
|
|
48
|
+
return list(response.directories)
|
|
49
|
+
|
|
50
|
+
def refreshMotionsList(self) -> int:
|
|
51
|
+
"""
|
|
52
|
+
Copy preference directories onto the project and rescan motion files.
|
|
53
|
+
|
|
54
|
+
Returns the number of motions loaded.
|
|
55
|
+
"""
|
|
56
|
+
request = MotionService_pb2.RefreshMotionsListRequest(modelID=self._objectId)
|
|
57
|
+
response = self._client.callFunction(self._motion_service.RefreshMotionsList, request)
|
|
58
|
+
require_success(response, "RefreshMotionsList")
|
|
59
|
+
return response.motionsLoaded
|
|
60
|
+
|
|
61
|
+
def listMotions(self) -> list[MotionInfo]:
|
|
62
|
+
"""Return all motions with name, file path, and selection state (uni-directional projects only)."""
|
|
63
|
+
request = MotionService_pb2.ListMotionsRequest(modelID=self._objectId)
|
|
64
|
+
response = self._client.callFunction(self._motion_service.ListMotions, request)
|
|
65
|
+
require_success(response, "ListMotions")
|
|
66
|
+
return [from_motion_entry(motion) for motion in response.motions]
|
|
67
|
+
|
|
68
|
+
def setMotionSelection(
|
|
69
|
+
self,
|
|
70
|
+
motionNames: list[str],
|
|
71
|
+
selectOnlyListed: bool = True,
|
|
72
|
+
) -> None:
|
|
73
|
+
"""
|
|
74
|
+
Select motions by name (uni-directional projects only).
|
|
75
|
+
|
|
76
|
+
When selectOnlyListed is True (default), only the listed motions remain selected.
|
|
77
|
+
"""
|
|
78
|
+
request = MotionService_pb2.SetMotionSelectionRequest(
|
|
79
|
+
modelID=self._objectId,
|
|
80
|
+
motionNames=motionNames,
|
|
81
|
+
selectOnlyListed=selectOnlyListed,
|
|
82
|
+
)
|
|
83
|
+
response = self._client.callFunction(self._motion_service.SetMotionSelection, request)
|
|
84
|
+
require_success(response, "SetMotionSelection")
|
|
85
|
+
|
|
86
|
+
def listMotionPairs(self) -> list[MotionPairInfo]:
|
|
87
|
+
"""Return horizontal motion pairs inferred from file names (bi-directional projects only)."""
|
|
88
|
+
request = MotionService_pb2.ListMotionPairsRequest(modelID=self._objectId)
|
|
89
|
+
response = self._client.callFunction(self._motion_service.ListMotionPairs, request)
|
|
90
|
+
require_success(response, "ListMotionPairs")
|
|
91
|
+
return [from_motion_pair_entry(pair) for pair in response.pairs]
|
|
92
|
+
|
|
93
|
+
def setMotionPairSelection(
|
|
94
|
+
self,
|
|
95
|
+
pairIds: list[str],
|
|
96
|
+
selectOnlyListed: bool = True,
|
|
97
|
+
) -> None:
|
|
98
|
+
"""
|
|
99
|
+
Select motion pairs by pair id (bi-directional projects only).
|
|
100
|
+
|
|
101
|
+
When selectOnlyListed is True (default), only the listed pairs remain selected.
|
|
102
|
+
Selecting a pair selects both horizontal components.
|
|
103
|
+
"""
|
|
104
|
+
request = MotionService_pb2.SetMotionPairSelectionRequest(
|
|
105
|
+
modelID=self._objectId,
|
|
106
|
+
pairIds=pairIds,
|
|
107
|
+
selectOnlyListed=selectOnlyListed,
|
|
108
|
+
)
|
|
109
|
+
response = self._client.callFunction(self._motion_service.SetMotionPairSelection, request)
|
|
110
|
+
require_success(response, "SetMotionPairSelection")
|
|
111
|
+
|
|
112
|
+
def selectAllMotions(self) -> None:
|
|
113
|
+
"""Select all motions (uni-directional) or all motion pairs (bi-directional)."""
|
|
114
|
+
request = MotionService_pb2.SelectAllMotionsRequest(modelID=self._objectId)
|
|
115
|
+
response = self._client.callFunction(self._motion_service.SelectAllMotions, request)
|
|
116
|
+
require_success(response, "SelectAllMotions")
|
|
117
|
+
|
|
118
|
+
def deselectAllMotions(self) -> None:
|
|
119
|
+
"""Deselect all motions (uni-directional) or all motion pairs (bi-directional)."""
|
|
120
|
+
request = MotionService_pb2.DeselectAllMotionsRequest(modelID=self._objectId)
|
|
121
|
+
response = self._client.callFunction(self._motion_service.DeselectAllMotions, request)
|
|
122
|
+
require_success(response, "DeselectAllMotions")
|
|
123
|
+
|
|
124
|
+
def selectAllMotionsInDirectory(self, motionDirectory: str) -> None:
|
|
125
|
+
"""Select all motions or pairs (by H1 folder) whose files are in the given directory."""
|
|
126
|
+
request = MotionService_pb2.SelectAllMotionsInDirectoryRequest(
|
|
127
|
+
modelID=self._objectId,
|
|
128
|
+
motionDirectory=motionDirectory,
|
|
129
|
+
)
|
|
130
|
+
response = self._client.callFunction(self._motion_service.SelectAllMotionsInDirectory, request)
|
|
131
|
+
require_success(response, "SelectAllMotionsInDirectory")
|
|
132
|
+
|
|
133
|
+
def deselectAllMotionsInDirectory(self, motionDirectory: str) -> None:
|
|
134
|
+
"""Deselect all motions or pairs (by H1 folder) whose files are in the given directory."""
|
|
135
|
+
request = MotionService_pb2.DeselectAllMotionsInDirectoryRequest(
|
|
136
|
+
modelID=self._objectId,
|
|
137
|
+
motionDirectory=motionDirectory,
|
|
138
|
+
)
|
|
139
|
+
response = self._client.callFunction(self._motion_service.DeselectAllMotionsInDirectory, request)
|
|
140
|
+
require_success(response, "DeselectAllMotionsInDirectory")
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from rsseismic._client import Client
|
|
4
|
+
from rsseismic._proxyObject import _ProxyObject
|
|
5
|
+
from rsseismic.generatedFiles import ProfileGenerationSettingsService_pb2_grpc as ProfileGenerationSettingsService_pb2_grpc
|
|
6
|
+
from rsseismic.properties._PropertyAccessor import PropertyAccessor
|
|
7
|
+
from rsseismic.properties.profileGenerationSettings._generated import ProfileGenerationSettingsPropertiesMixin
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class ProfileGenerationSettings(_ProxyObject, ProfileGenerationSettingsPropertiesMixin):
|
|
11
|
+
"""
|
|
12
|
+
Settings that control automatic profile generation.
|
|
13
|
+
|
|
14
|
+
Access via ``model.ProfileGenerationSettings``. Use the generated ``get*`` /
|
|
15
|
+
``set*`` helpers to configure how many profiles to create, randomization options,
|
|
16
|
+
and related parameters (for example ``setProfilesToGenerate``).
|
|
17
|
+
|
|
18
|
+
After profiles have been generated once, call ``model.resetGeneratedProfiles()``
|
|
19
|
+
before generating again. Use ``model.generateProfiles()`` to create profiles from
|
|
20
|
+
the mean profile template.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
def __init__(self, client: Client, modelId: str):
|
|
24
|
+
super().__init__(client, modelId)
|
|
25
|
+
self.modelId = modelId
|
|
26
|
+
self._settings_service = ProfileGenerationSettingsService_pb2_grpc.ProfileGenerationSettingsServiceStub(
|
|
27
|
+
self._client.channel
|
|
28
|
+
)
|
|
29
|
+
self.Data = PropertyAccessor(client, modelId, self._settings_service)
|
rsseismic/Profiles.py
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
from rsseismic._client import Client
|
|
6
|
+
from rsseismic._proto_converters import (
|
|
7
|
+
from_active_profile_response,
|
|
8
|
+
from_bedrock_layer_entry,
|
|
9
|
+
from_profile_entry,
|
|
10
|
+
from_soil_layer_entry,
|
|
11
|
+
)
|
|
12
|
+
from rsseismic._proxyObject import _ProxyObject
|
|
13
|
+
from rsseismic._rpc_helpers import require_success
|
|
14
|
+
from rsseismic.generatedFiles import ProfileService_pb2 as ProfileService_pb2
|
|
15
|
+
from rsseismic.generatedFiles import ProfileService_pb2_grpc as ProfileService_pb2_grpc
|
|
16
|
+
from rsseismic.types import (
|
|
17
|
+
ActiveProfile,
|
|
18
|
+
BedrockLayerSummary,
|
|
19
|
+
DeleteProfileResult,
|
|
20
|
+
ProfileSummary,
|
|
21
|
+
SoilLayerSummary,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
if TYPE_CHECKING:
|
|
25
|
+
from rsseismic.BedrockLayer import BedrockLayer
|
|
26
|
+
from rsseismic.SoilLayer import SoilLayer
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class Profiles(_ProxyObject):
|
|
30
|
+
"""Profile navigation and CRUD for an open model."""
|
|
31
|
+
|
|
32
|
+
def __init__(self, client: Client, modelId: str):
|
|
33
|
+
super().__init__(client, modelId)
|
|
34
|
+
self._profile_service = ProfileService_pb2_grpc.ProfileServiceStub(self._client.channel)
|
|
35
|
+
|
|
36
|
+
def listProfiles(self) -> list[ProfileSummary]:
|
|
37
|
+
request = ProfileService_pb2.ListProfilesRequest(modelID=self._objectId)
|
|
38
|
+
response = self._client.callFunction(self._profile_service.ListProfiles, request)
|
|
39
|
+
require_success(response, "ListProfiles")
|
|
40
|
+
return [from_profile_entry(profile) for profile in response.profiles]
|
|
41
|
+
|
|
42
|
+
def getActiveProfile(self) -> ActiveProfile:
|
|
43
|
+
request = ProfileService_pb2.GetActiveProfileRequest(modelID=self._objectId)
|
|
44
|
+
response = self._client.callFunction(self._profile_service.GetActiveProfile, request)
|
|
45
|
+
require_success(response, "GetActiveProfile")
|
|
46
|
+
return from_active_profile_response(response)
|
|
47
|
+
|
|
48
|
+
def setActiveProfile(self, profileName: str) -> None:
|
|
49
|
+
request = ProfileService_pb2.SetActiveProfileRequest(
|
|
50
|
+
modelID=self._objectId,
|
|
51
|
+
profileName=profileName,
|
|
52
|
+
)
|
|
53
|
+
response = self._client.callFunction(self._profile_service.SetActiveProfile, request)
|
|
54
|
+
require_success(response, "SetActiveProfile")
|
|
55
|
+
|
|
56
|
+
def listSoilLayers(self, profileName: str = "") -> list[SoilLayerSummary]:
|
|
57
|
+
"""
|
|
58
|
+
List soil layers for a profile.
|
|
59
|
+
|
|
60
|
+
When profileName is empty, the active profile is used.
|
|
61
|
+
"""
|
|
62
|
+
request = ProfileService_pb2.ListSoilLayersRequest(
|
|
63
|
+
modelID=self._objectId,
|
|
64
|
+
profileName=profileName,
|
|
65
|
+
)
|
|
66
|
+
response = self._client.callFunction(self._profile_service.ListSoilLayers, request)
|
|
67
|
+
require_success(response, "ListSoilLayers")
|
|
68
|
+
return [from_soil_layer_entry(layer) for layer in response.layers]
|
|
69
|
+
|
|
70
|
+
def listActiveSoilLayers(self) -> list[SoilLayerSummary]:
|
|
71
|
+
"""List soil layers for the active profile."""
|
|
72
|
+
return self.listSoilLayers("")
|
|
73
|
+
|
|
74
|
+
def getBedrockLayer(self, profileName: str = "") -> BedrockLayerSummary:
|
|
75
|
+
"""
|
|
76
|
+
Return the bedrock layer for a profile.
|
|
77
|
+
|
|
78
|
+
When profileName is empty, the active profile is used.
|
|
79
|
+
"""
|
|
80
|
+
request = ProfileService_pb2.GetBedrockLayerRequest(
|
|
81
|
+
modelID=self._objectId,
|
|
82
|
+
profileName=profileName,
|
|
83
|
+
)
|
|
84
|
+
response = self._client.callFunction(self._profile_service.GetBedrockLayer, request)
|
|
85
|
+
require_success(response, "GetBedrockLayer")
|
|
86
|
+
return from_bedrock_layer_entry(response.bedrock)
|
|
87
|
+
|
|
88
|
+
def getActiveBedrockLayer(self) -> BedrockLayerSummary:
|
|
89
|
+
"""Return the bedrock layer for the active profile."""
|
|
90
|
+
return self.getBedrockLayer("")
|
|
91
|
+
|
|
92
|
+
def getSoilLayer(self, layerId: str) -> SoilLayer:
|
|
93
|
+
"""Return a property proxy for a soil layer GUID."""
|
|
94
|
+
from rsseismic.SoilLayer import SoilLayer
|
|
95
|
+
|
|
96
|
+
return SoilLayer(self._client, self._objectId, layerId)
|
|
97
|
+
|
|
98
|
+
def getBedrockLayerProxy(self, profileName: str = "") -> BedrockLayer:
|
|
99
|
+
"""Return a property proxy for the bedrock layer of a profile."""
|
|
100
|
+
from rsseismic.BedrockLayer import BedrockLayer
|
|
101
|
+
|
|
102
|
+
entry = self.getBedrockLayer(profileName)
|
|
103
|
+
return BedrockLayer(self._client, self._objectId, entry.layerID)
|
|
104
|
+
|
|
105
|
+
def createProfile(self, profileName: str = "") -> str:
|
|
106
|
+
"""
|
|
107
|
+
Create a new profile and make it active.
|
|
108
|
+
|
|
109
|
+
When profileName is empty, the server assigns a unique default name.
|
|
110
|
+
"""
|
|
111
|
+
request = ProfileService_pb2.CreateProfileRequest(
|
|
112
|
+
modelID=self._objectId,
|
|
113
|
+
profileName=profileName,
|
|
114
|
+
)
|
|
115
|
+
response = self._client.callFunction(self._profile_service.CreateProfile, request)
|
|
116
|
+
require_success(response, "CreateProfile")
|
|
117
|
+
return response.profileName
|
|
118
|
+
|
|
119
|
+
def copyProfile(self, profileName: str = "") -> str:
|
|
120
|
+
"""
|
|
121
|
+
Copy the active profile and make the copy active.
|
|
122
|
+
|
|
123
|
+
When profileName is empty, the server assigns a unique default name.
|
|
124
|
+
"""
|
|
125
|
+
request = ProfileService_pb2.CopyProfileRequest(
|
|
126
|
+
modelID=self._objectId,
|
|
127
|
+
profileName=profileName,
|
|
128
|
+
)
|
|
129
|
+
response = self._client.callFunction(self._profile_service.CopyProfile, request)
|
|
130
|
+
require_success(response, "CopyProfile")
|
|
131
|
+
return response.profileName
|
|
132
|
+
|
|
133
|
+
def deleteProfile(self, profileName: str) -> DeleteProfileResult:
|
|
134
|
+
"""Delete a profile by name. At least one profile must remain."""
|
|
135
|
+
request = ProfileService_pb2.DeleteProfileRequest(
|
|
136
|
+
modelID=self._objectId,
|
|
137
|
+
profileName=profileName,
|
|
138
|
+
)
|
|
139
|
+
response = self._client.callFunction(self._profile_service.DeleteProfile, request)
|
|
140
|
+
require_success(response, "DeleteProfile")
|
|
141
|
+
return DeleteProfileResult(
|
|
142
|
+
deletedProfileName=response.deletedProfileName,
|
|
143
|
+
activeProfileName=response.activeProfileName,
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
def renameActiveProfile(self, newProfileName: str) -> str:
|
|
147
|
+
"""Rename the active profile."""
|
|
148
|
+
request = ProfileService_pb2.RenameActiveProfileRequest(
|
|
149
|
+
modelID=self._objectId,
|
|
150
|
+
newProfileName=newProfileName,
|
|
151
|
+
)
|
|
152
|
+
response = self._client.callFunction(self._profile_service.RenameActiveProfile, request)
|
|
153
|
+
require_success(response, "RenameActiveProfile")
|
|
154
|
+
return response.profileName
|
|
155
|
+
|
|
156
|
+
def getOutputDepths(self, profileName: str = "") -> list[float]:
|
|
157
|
+
"""
|
|
158
|
+
Return output depths for a profile in project length units.
|
|
159
|
+
|
|
160
|
+
When profileName is empty, the active profile is used.
|
|
161
|
+
"""
|
|
162
|
+
request = ProfileService_pb2.GetOutputDepthsRequest(
|
|
163
|
+
modelID=self._objectId,
|
|
164
|
+
profileName=profileName,
|
|
165
|
+
)
|
|
166
|
+
response = self._client.callFunction(self._profile_service.GetOutputDepths, request)
|
|
167
|
+
require_success(response, "GetOutputDepths")
|
|
168
|
+
return list(response.depths)
|
|
169
|
+
|
|
170
|
+
def getActiveOutputDepths(self) -> list[float]:
|
|
171
|
+
"""Return output depths for the active profile."""
|
|
172
|
+
return self.getOutputDepths("")
|
|
173
|
+
|
|
174
|
+
def setOutputDepths(self, depths: list[float], profileName: str = "") -> None:
|
|
175
|
+
"""
|
|
176
|
+
Set output depths for a profile in project length units.
|
|
177
|
+
|
|
178
|
+
When profileName is empty, the active profile is used.
|
|
179
|
+
"""
|
|
180
|
+
request = ProfileService_pb2.SetOutputDepthsRequest(
|
|
181
|
+
modelID=self._objectId,
|
|
182
|
+
profileName=profileName,
|
|
183
|
+
depths=depths,
|
|
184
|
+
)
|
|
185
|
+
response = self._client.callFunction(self._profile_service.SetOutputDepths, request)
|
|
186
|
+
require_success(response, "SetOutputDepths")
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from rsseismic._client import Client
|
|
4
|
+
from rsseismic._proxyObject import _ProxyObject
|
|
5
|
+
from rsseismic._rpc_helpers import require_success
|
|
6
|
+
from rsseismic.generatedFiles import ProjectSettingsDataService_pb2 as ProjectSettingsDataService_pb2
|
|
7
|
+
from rsseismic.generatedFiles import ProjectSettingsDataService_pb2_grpc as ProjectSettingsDataService_pb2_grpc
|
|
8
|
+
from rsseismic.properties._PropertyAccessor import PropertyAccessor
|
|
9
|
+
from rsseismic.types import UnitSystem
|
|
10
|
+
from rsseismic.properties.projectSettings._generated import ProjectSettingsPropertiesMixin
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ProjectSettings(_ProxyObject, ProjectSettingsPropertiesMixin):
|
|
14
|
+
"""
|
|
15
|
+
Project-wide settings for analysis, motions, and output.
|
|
16
|
+
|
|
17
|
+
Access via ``model.ProjectSettings``. Use the generated ``get*`` / ``set*`` helpers
|
|
18
|
+
for options such as analysis method, input motion configuration, default soil model,
|
|
19
|
+
and automatic profile generation. Use ``getUnitSystem()`` and ``changeUnitSystem()``
|
|
20
|
+
to read or switch between metric and imperial units.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
def __init__(self, client: Client, modelId: str):
|
|
24
|
+
super().__init__(client, modelId)
|
|
25
|
+
self.modelId = modelId
|
|
26
|
+
self._settings_service = ProjectSettingsDataService_pb2_grpc.ProjectSettingsDataServiceStub(
|
|
27
|
+
self._client.channel
|
|
28
|
+
)
|
|
29
|
+
self.Data = PropertyAccessor(client, modelId, self._settings_service)
|
|
30
|
+
|
|
31
|
+
def getUnitSystem(self) -> UnitSystem:
|
|
32
|
+
"""Return the project unit system (Metric or Imperial)."""
|
|
33
|
+
request = ProjectSettingsDataService_pb2.GetUnitSystemRequest(objectId=self._objectId)
|
|
34
|
+
response = self._client.callFunction(self._settings_service.GetUnitSystem, request)
|
|
35
|
+
require_success(response, "GetUnitSystem")
|
|
36
|
+
return UnitSystem.from_is_metric(response.isMetric)
|
|
37
|
+
|
|
38
|
+
def changeUnitSystem(self, unitSystem: UnitSystem) -> UnitSystem:
|
|
39
|
+
"""Switch between metric and imperial units. Returns the unit system now in effect."""
|
|
40
|
+
request = ProjectSettingsDataService_pb2.ChangeUnitSystemRequest(
|
|
41
|
+
objectId=self._objectId,
|
|
42
|
+
useMetric=unitSystem.to_use_metric(),
|
|
43
|
+
)
|
|
44
|
+
response = self._client.callFunction(self._settings_service.ChangeUnitSystem, request)
|
|
45
|
+
require_success(response, "ChangeUnitSystem")
|
|
46
|
+
return UnitSystem.from_is_metric(response.isMetric)
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from rsseismic._client import Client
|
|
4
|
+
from rsseismic._proto_converters import from_reference_curve_points, to_reference_curve_points
|
|
5
|
+
from rsseismic._proxyObject import _ProxyObject
|
|
6
|
+
from rsseismic._rpc_helpers import log_success_advisory, require_success
|
|
7
|
+
from rsseismic.types import DynamicsPoint
|
|
8
|
+
from rsseismic.generatedFiles import ReferenceCurveDataService_pb2 as ReferenceCurveDataService_pb2
|
|
9
|
+
from rsseismic.generatedFiles import ReferenceCurveDataService_pb2_grpc as ReferenceCurveDataService_pb2_grpc
|
|
10
|
+
from rsseismic.properties._PropertyAccessor import ProjectScopedPropertyAccessor
|
|
11
|
+
from rsseismic.properties.referenceCurve._generated import ReferenceCurvePropertiesMixin
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ReferenceCurve(_ProxyObject, ReferenceCurvePropertiesMixin):
|
|
15
|
+
"""
|
|
16
|
+
Reference curve for a soil layer.
|
|
17
|
+
|
|
18
|
+
Access via ``layer.ReferenceCurve`` on a ``SoilLayer`` or ``MeanProfileSoilLayer``.
|
|
19
|
+
Use the generated ``get*`` / ``set*`` helpers to configure the curve model, soil type,
|
|
20
|
+
and related parameters. Use ``getCurvePoints`` / ``setCurvePoints`` for user-defined
|
|
21
|
+
curves, or call ``generateReferenceCurve()`` to build the curve from those settings.
|
|
22
|
+
|
|
23
|
+
On mean-profile template layers, ``generateReferenceCurve()`` is not available;
|
|
24
|
+
set properties and points directly instead.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(self, client: Client, modelId: str, layerId: str):
|
|
28
|
+
super().__init__(client, layerId)
|
|
29
|
+
self.modelId = modelId
|
|
30
|
+
stub = ReferenceCurveDataService_pb2_grpc.ReferenceCurveDataServiceStub(self._client.channel)
|
|
31
|
+
self.Data = ProjectScopedPropertyAccessor(client, modelId, layerId, stub)
|
|
32
|
+
self._service = stub
|
|
33
|
+
|
|
34
|
+
@property
|
|
35
|
+
def layerId(self) -> str:
|
|
36
|
+
return self._objectId
|
|
37
|
+
|
|
38
|
+
def getCurvePoints(self) -> list[DynamicsPoint]:
|
|
39
|
+
"""Return reference curve points."""
|
|
40
|
+
request = ReferenceCurveDataService_pb2.GetReferenceCurvePointsRequest(
|
|
41
|
+
projectId=self.modelId,
|
|
42
|
+
layerID=self._objectId,
|
|
43
|
+
)
|
|
44
|
+
response = self._client.callFunction(self._service.GetCurvePoints, request)
|
|
45
|
+
require_success(response, "GetCurvePoints")
|
|
46
|
+
return from_reference_curve_points(list(response.points))
|
|
47
|
+
|
|
48
|
+
def setCurvePoints(self, points: list[DynamicsPoint]) -> None:
|
|
49
|
+
"""Set reference curve points when using a user-defined curve model."""
|
|
50
|
+
if not points:
|
|
51
|
+
raise ValueError("At least one curve point is required.")
|
|
52
|
+
request = ReferenceCurveDataService_pb2.SetReferenceCurvePointsRequest(
|
|
53
|
+
projectId=self.modelId,
|
|
54
|
+
layerID=self._objectId,
|
|
55
|
+
points=to_reference_curve_points(points),
|
|
56
|
+
)
|
|
57
|
+
response = self._client.callFunction(self._service.SetCurvePoints, request)
|
|
58
|
+
require_success(response, "SetCurvePoints")
|
|
59
|
+
|
|
60
|
+
def generateReferenceCurve(self) -> int:
|
|
61
|
+
"""
|
|
62
|
+
Build the reference curve from the current curve model, soil type, and parameters.
|
|
63
|
+
|
|
64
|
+
Returns the number of points created. Not available on mean-profile template layers.
|
|
65
|
+
"""
|
|
66
|
+
request = ReferenceCurveDataService_pb2.GenerateReferenceCurveRequest(
|
|
67
|
+
projectId=self.modelId,
|
|
68
|
+
layerID=self._objectId,
|
|
69
|
+
)
|
|
70
|
+
response = self._client.callFunction(self._service.GenerateReferenceCurve, request)
|
|
71
|
+
require_success(response, "GenerateReferenceCurve")
|
|
72
|
+
log_success_advisory(response)
|
|
73
|
+
return response.pointCount
|