Single-profile workflow#
Open a project, configure layers and motions, run compute, and read basic results using the rsseismic package.
1"""
2Single-profile RSSeismic scripting workflow using the installed rsseismic package.
3
4 python examples/example_single_profile_workflow.py "E:\\path\\to\\project.rsseismicfile"
5 python examples/example_single_profile_workflow.py --port 60058 --motion EQ1 project.rsseismicfile
6 python examples/example_single_profile_workflow.py --no-compute project.rsseismicfile
7"""
8
9from __future__ import annotations
10
11import argparse
12import os
13import sys
14
15from rsseismic import RSSeismicApplication, logger
16from rsseismic._client import DEFAULT_SCRIPTING_PORT
17
18
19def _select_motion_names(model, requested_names: list[str]) -> list[str]:
20 model.Motions.refreshMotionsList()
21 motions = model.Motions.listMotions()
22 if not motions:
23 raise RuntimeError(
24 "No motions available. Configure motion directories in RSSeismic Preferences "
25 "or ensure the project has motions."
26 )
27
28 if requested_names:
29 return requested_names
30
31 selected = [motion.name for motion in motions if motion.isSelected]
32 if selected:
33 return selected
34
35 return [motions[0].name]
36
37
38def run_single_profile_workflow(
39 project_path: str,
40 port: int = DEFAULT_SCRIPTING_PORT,
41 motion_names: list[str] | None = None,
42 run_compute: bool = True,
43) -> str | None:
44 """
45 Open a project, configure motion selection, save, optionally compute, return db3 path.
46
47 Returns resultDatabasePath when compute runs successfully, otherwise None.
48 """
49 project_path = os.path.abspath(project_path.strip())
50 if not os.path.isfile(project_path):
51 raise FileNotFoundError(f"Project file not found: {project_path}")
52
53 app = RSSeismicApplication(port=port)
54 model = None
55 db3_path: str | None = None
56
57 try:
58 app.ping()
59 model = app.openFile(project_path)
60
61 profile_name = model.Profiles.getActiveProfile().profileName
62 names_to_select = _select_motion_names(model, motion_names or [])
63 model.Motions.setMotionSelection(names_to_select, selectOnlyListed=True)
64 model.save()
65
66 if not run_compute:
67 return None
68
69 result = model.runCompute()
70 if not result.success:
71 raise RuntimeError(result.errorMessage or "RunCompute failed.")
72 if result.partialSuccess:
73 logger.warning("Some profile/motion pairs failed:\n%s", result.errorMessage)
74
75 motion_name = names_to_select[0]
76 entry = model.Results.getResultDatabasePath(profile_name, motion_name)
77 db3_path = entry.resultDatabasePath
78 deconv = model.Profiles.getBedrockLayerProxy(profile_name).Data.getBoolValue("Deconvolution")
79 if not db3_path and not deconv:
80 raise RuntimeError("Compute succeeded but resultDatabasePath is empty.")
81 return db3_path
82 finally:
83 if model is not None:
84 model.close(saveProject=False)
85 app.close()
86
87
88def parse_args() -> argparse.Namespace:
89 parser = argparse.ArgumentParser(
90 description="Run a single-profile open → motion → save → compute → db3 workflow."
91 )
92 parser.add_argument(
93 "project",
94 help="Absolute path to a .rsseismicfile",
95 )
96 parser.add_argument(
97 "--port",
98 "-p",
99 type=int,
100 default=int(os.environ.get("RSSEISMIC_SCRIPTING_PORT", DEFAULT_SCRIPTING_PORT)),
101 help=f"gRPC port (default: {DEFAULT_SCRIPTING_PORT}, or RSSEISMIC_SCRIPTING_PORT env)",
102 )
103 parser.add_argument(
104 "--motion",
105 "-m",
106 action="append",
107 default=[],
108 metavar="NAME",
109 help="Motion name to select for compute (repeatable). Default: already-selected, else first motion.",
110 )
111 parser.add_argument(
112 "--no-compute",
113 action="store_true",
114 help="Skip RunCompute (open, motion selection, save, close only)",
115 )
116 return parser.parse_args()
117
118
119def main() -> int:
120 args = parse_args()
121 try:
122 db3_path = run_single_profile_workflow(
123 args.project,
124 port=args.port,
125 motion_names=args.motion,
126 run_compute=not args.no_compute,
127 )
128 except Exception as ex:
129 print(f"Workflow failed: {ex}", file=sys.stderr)
130 return 1
131
132 if db3_path:
133 print(f"Compute finished. Result database: {db3_path}")
134 else:
135 print("Workflow finished (compute skipped).")
136 return 0
137
138
139if __name__ == "__main__":
140 raise SystemExit(main())