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.
Files changed (94) hide show
  1. rsseismic/Application.py +196 -0
  2. rsseismic/ApplicationManager.py +111 -0
  3. rsseismic/BedrockLayer.py +29 -0
  4. rsseismic/MeanProfile.py +169 -0
  5. rsseismic/MeanProfileSoilLayer.py +119 -0
  6. rsseismic/Model.py +204 -0
  7. rsseismic/Motions.py +140 -0
  8. rsseismic/ProfileGenerationSettings.py +29 -0
  9. rsseismic/Profiles.py +186 -0
  10. rsseismic/ProjectSettings.py +46 -0
  11. rsseismic/ReferenceCurve.py +73 -0
  12. rsseismic/Results.py +419 -0
  13. rsseismic/SoilLayer.py +34 -0
  14. rsseismic/SoilLayerCurve.py +124 -0
  15. rsseismic/SoilLayerOperations.py +120 -0
  16. rsseismic/__init__.py +79 -0
  17. rsseismic/_application_paths.py +74 -0
  18. rsseismic/_batch_compute.py +420 -0
  19. rsseismic/_client.py +81 -0
  20. rsseismic/_proto_converters.py +345 -0
  21. rsseismic/_proxyObject.py +11 -0
  22. rsseismic/_result_bulk_dataframes.py +202 -0
  23. rsseismic/_result_dataframes.py +77 -0
  24. rsseismic/_rpc_helpers.py +55 -0
  25. rsseismic/enums/__init__.py +23 -0
  26. rsseismic/enums/_generated.py +120 -0
  27. rsseismic/enums/fitting_procedure.py +15 -0
  28. rsseismic/exceptions.py +11 -0
  29. rsseismic/generatedFiles/ApplicationService_pb2.py +46 -0
  30. rsseismic/generatedFiles/ApplicationService_pb2.pyi +67 -0
  31. rsseismic/generatedFiles/ApplicationService_pb2_grpc.py +274 -0
  32. rsseismic/generatedFiles/BedrockLayerDataService_pb2.py +27 -0
  33. rsseismic/generatedFiles/BedrockLayerDataService_pb2.pyi +5 -0
  34. rsseismic/generatedFiles/BedrockLayerDataService_pb2_grpc.py +231 -0
  35. rsseismic/generatedFiles/CommonMessages_pb2.py +50 -0
  36. rsseismic/generatedFiles/CommonMessages_pb2.pyi +113 -0
  37. rsseismic/generatedFiles/CommonMessages_pb2_grpc.py +29 -0
  38. rsseismic/generatedFiles/MeanProfileService_pb2.py +62 -0
  39. rsseismic/generatedFiles/MeanProfileService_pb2.pyi +176 -0
  40. rsseismic/generatedFiles/MeanProfileService_pb2_grpc.py +458 -0
  41. rsseismic/generatedFiles/MeanProfileSoilLayerDataService_pb2.py +45 -0
  42. rsseismic/generatedFiles/MeanProfileSoilLayerDataService_pb2.pyi +87 -0
  43. rsseismic/generatedFiles/MeanProfileSoilLayerDataService_pb2_grpc.py +360 -0
  44. rsseismic/generatedFiles/ModelService_pb2.py +54 -0
  45. rsseismic/generatedFiles/ModelService_pb2.pyi +122 -0
  46. rsseismic/generatedFiles/ModelService_pb2_grpc.py +360 -0
  47. rsseismic/generatedFiles/MotionService_pb2.py +78 -0
  48. rsseismic/generatedFiles/MotionService_pb2.pyi +224 -0
  49. rsseismic/generatedFiles/MotionService_pb2_grpc.py +575 -0
  50. rsseismic/generatedFiles/ProfileGenerationSettingsService_pb2.py +27 -0
  51. rsseismic/generatedFiles/ProfileGenerationSettingsService_pb2.pyi +5 -0
  52. rsseismic/generatedFiles/ProfileGenerationSettingsService_pb2_grpc.py +145 -0
  53. rsseismic/generatedFiles/ProfileService_pb2.py +76 -0
  54. rsseismic/generatedFiles/ProfileService_pb2.pyi +246 -0
  55. rsseismic/generatedFiles/ProfileService_pb2_grpc.py +532 -0
  56. rsseismic/generatedFiles/ProjectSettingsDataService_pb2.py +35 -0
  57. rsseismic/generatedFiles/ProjectSettingsDataService_pb2.pyi +40 -0
  58. rsseismic/generatedFiles/ProjectSettingsDataService_pb2_grpc.py +232 -0
  59. rsseismic/generatedFiles/ReferenceCurveDataService_pb2.py +41 -0
  60. rsseismic/generatedFiles/ReferenceCurveDataService_pb2.pyi +73 -0
  61. rsseismic/generatedFiles/ReferenceCurveDataService_pb2_grpc.py +281 -0
  62. rsseismic/generatedFiles/ResultsService_pb2.py +82 -0
  63. rsseismic/generatedFiles/ResultsService_pb2.pyi +373 -0
  64. rsseismic/generatedFiles/ResultsService_pb2_grpc.py +489 -0
  65. rsseismic/generatedFiles/SoilLayerCurveDataService_pb2.py +52 -0
  66. rsseismic/generatedFiles/SoilLayerCurveDataService_pb2.pyi +150 -0
  67. rsseismic/generatedFiles/SoilLayerCurveDataService_pb2_grpc.py +280 -0
  68. rsseismic/generatedFiles/SoilLayerDataService_pb2.py +27 -0
  69. rsseismic/generatedFiles/SoilLayerDataService_pb2.pyi +5 -0
  70. rsseismic/generatedFiles/SoilLayerDataService_pb2_grpc.py +231 -0
  71. rsseismic/generatedFiles/SoilLayerService_pb2.py +46 -0
  72. rsseismic/generatedFiles/SoilLayerService_pb2.pyi +122 -0
  73. rsseismic/generatedFiles/SoilLayerService_pb2_grpc.py +317 -0
  74. rsseismic/generatedFiles/__init__.py +4 -0
  75. rsseismic/properties/_PropertyAccessor.py +151 -0
  76. rsseismic/properties/__init__.py +6 -0
  77. rsseismic/properties/bedrockLayer/__init__.py +1 -0
  78. rsseismic/properties/bedrockLayer/_generated.py +127 -0
  79. rsseismic/properties/meanProfileSoilLayer/__init__.py +1 -0
  80. rsseismic/properties/meanProfileSoilLayer/_generated.py +87 -0
  81. rsseismic/properties/profileGenerationSettings/__init__.py +1 -0
  82. rsseismic/properties/profileGenerationSettings/_generated.py +195 -0
  83. rsseismic/properties/projectSettings/__init__.py +1 -0
  84. rsseismic/properties/projectSettings/_generated.py +270 -0
  85. rsseismic/properties/referenceCurve/__init__.py +1 -0
  86. rsseismic/properties/referenceCurve/_generated.py +264 -0
  87. rsseismic/properties/soilLayer/__init__.py +1 -0
  88. rsseismic/properties/soilLayer/_generated.py +523 -0
  89. rsseismic/types.py +311 -0
  90. rsseismicscripting-3.0.0.dist-info/METADATA +88 -0
  91. rsseismicscripting-3.0.0.dist-info/RECORD +94 -0
  92. rsseismicscripting-3.0.0.dist-info/WHEEL +5 -0
  93. rsseismicscripting-3.0.0.dist-info/licenses/License.txt +20 -0
  94. 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