luminarycloud 0.16.1__py3-none-any.whl → 0.17.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 (59) hide show
  1. luminarycloud/_auth/auth.py +23 -34
  2. luminarycloud/_client/client.py +21 -5
  3. luminarycloud/_client/retry_interceptor.py +7 -0
  4. luminarycloud/_helpers/_create_geometry.py +0 -2
  5. luminarycloud/_helpers/_wait_for_mesh.py +14 -4
  6. luminarycloud/_helpers/warnings/__init__.py +0 -1
  7. luminarycloud/_proto/api/v0/luminarycloud/geometry/geometry_pb2.py +120 -120
  8. luminarycloud/_proto/api/v0/luminarycloud/geometry/geometry_pb2.pyi +2 -8
  9. luminarycloud/_proto/api/v0/luminarycloud/mesh/mesh_pb2.py +25 -3
  10. luminarycloud/_proto/api/v0/luminarycloud/mesh/mesh_pb2.pyi +30 -0
  11. luminarycloud/_proto/api/v0/luminarycloud/mesh/mesh_pb2_grpc.py +34 -0
  12. luminarycloud/_proto/api/v0/luminarycloud/mesh/mesh_pb2_grpc.pyi +12 -0
  13. luminarycloud/_proto/api/v0/luminarycloud/project_ui_state/project_ui_state_pb2.py +97 -0
  14. luminarycloud/_proto/api/v0/luminarycloud/project_ui_state/project_ui_state_pb2.pyi +93 -0
  15. luminarycloud/_proto/api/v0/luminarycloud/project_ui_state/project_ui_state_pb2_grpc.py +132 -0
  16. luminarycloud/_proto/api/v0/luminarycloud/project_ui_state/project_ui_state_pb2_grpc.pyi +44 -0
  17. luminarycloud/_proto/api/v0/luminarycloud/thirdpartyintegration/onshape/onshape_pb2.py +88 -34
  18. luminarycloud/_proto/api/v0/luminarycloud/thirdpartyintegration/onshape/onshape_pb2.pyi +96 -6
  19. luminarycloud/_proto/api/v0/luminarycloud/thirdpartyintegration/onshape/onshape_pb2_grpc.py +68 -0
  20. luminarycloud/_proto/api/v0/luminarycloud/thirdpartyintegration/onshape/onshape_pb2_grpc.pyi +24 -0
  21. luminarycloud/_proto/api/v0/luminarycloud/vis/vis_pb2.py +153 -133
  22. luminarycloud/_proto/api/v0/luminarycloud/vis/vis_pb2.pyi +51 -3
  23. luminarycloud/_proto/cad/shape_pb2.py +78 -19
  24. luminarycloud/_proto/cad/transformation_pb2.py +34 -15
  25. luminarycloud/_proto/geometry/geometry_pb2.py +62 -62
  26. luminarycloud/_proto/geometry/geometry_pb2.pyi +3 -5
  27. luminarycloud/_proto/hexmesh/hexmesh_pb2.py +17 -4
  28. luminarycloud/_proto/hexmesh/hexmesh_pb2.pyi +22 -1
  29. luminarycloud/_proto/quantity/quantity_pb2.py +19 -19
  30. luminarycloud/_proto/upload/upload_pb2.py +25 -15
  31. luminarycloud/_proto/upload/upload_pb2.pyi +31 -2
  32. luminarycloud/feature_modification.py +0 -5
  33. luminarycloud/geometry.py +15 -2
  34. luminarycloud/mesh.py +16 -0
  35. luminarycloud/named_variable_set.py +3 -4
  36. luminarycloud/outputs/stopping_conditions.py +0 -3
  37. luminarycloud/physics_ai/architectures.py +0 -4
  38. luminarycloud/physics_ai/inference.py +0 -4
  39. luminarycloud/physics_ai/models.py +0 -4
  40. luminarycloud/physics_ai/solution.py +2 -2
  41. luminarycloud/pipelines/__init__.py +6 -0
  42. luminarycloud/pipelines/arguments.py +105 -0
  43. luminarycloud/pipelines/core.py +204 -20
  44. luminarycloud/pipelines/operators.py +11 -9
  45. luminarycloud/pipelines/parameters.py +25 -4
  46. luminarycloud/project.py +37 -11
  47. luminarycloud/simulation_param.py +0 -2
  48. luminarycloud/simulation_template.py +1 -3
  49. luminarycloud/solution.py +1 -3
  50. luminarycloud/vis/__init__.py +2 -0
  51. luminarycloud/vis/data_extraction.py +201 -31
  52. luminarycloud/vis/filters.py +94 -35
  53. luminarycloud/vis/primitives.py +78 -1
  54. luminarycloud/vis/visualization.py +44 -6
  55. luminarycloud/volume_selection.py +0 -4
  56. {luminarycloud-0.16.1.dist-info → luminarycloud-0.17.0.dist-info}/METADATA +1 -1
  57. {luminarycloud-0.16.1.dist-info → luminarycloud-0.17.0.dist-info}/RECORD +58 -54
  58. luminarycloud/_helpers/warnings/experimental.py +0 -48
  59. {luminarycloud-0.16.1.dist-info → luminarycloud-0.17.0.dist-info}/WHEEL +0 -0
@@ -150,7 +150,6 @@ def modify_import(
150
150
  feature: gpb.Feature,
151
151
  geometry_url: Optional[str] = None,
152
152
  scaling: Optional[float] = None,
153
- force_discrete: Optional[bool] = None,
154
153
  ) -> gpb.Modification:
155
154
  """
156
155
  Modify an import feature with optional new values.
@@ -160,7 +159,6 @@ def modify_import(
160
159
  feature: A gpb.Feature object
161
160
  geometry_url: The new geometry URL
162
161
  scaling: New scaling factor
163
- force_discrete: Whether to force discrete geometry
164
162
 
165
163
  Returns:
166
164
  A gpb.Modification object
@@ -177,9 +175,6 @@ def modify_import(
177
175
  if scaling is not None:
178
176
  feature_copy.import_geometry.scaling = scaling
179
177
 
180
- if force_discrete is not None:
181
- feature_copy.import_geometry.force_discrete = force_discrete
182
-
183
178
  return gpb.Modification(
184
179
  mod_type=gpb.Modification.ModificationType.MODIFICATION_TYPE_UPDATE_FEATURE,
185
180
  feature=feature_copy,
luminarycloud/geometry.py CHANGED
@@ -10,7 +10,6 @@ from typing import Union, Sequence
10
10
  from typing_extensions import TYPE_CHECKING
11
11
 
12
12
  import luminarycloud as lc
13
- from luminarycloud._helpers.warnings import experimental
14
13
 
15
14
  from ._client import get_default_client
16
15
  from ._helpers._timestamp_to_datetime import timestamp_to_datetime
@@ -112,13 +111,14 @@ class Geometry(ProtoWrapperBase):
112
111
  raise TypeError("volumes must be a list")
113
112
  return VolumeSelection(self, volumes)
114
113
 
115
- @experimental
116
114
  def use_named_variable_set(self, named_variable_set: Union[NamedVariableSet, str]) -> None:
117
115
  """
118
116
  Set the current state of the named variable set for the geometry. The current state of the
119
117
  geometry will be recreated using this named variable set and all future modifications
120
118
  applied will use this named variable set as it was at the time of the call.
121
119
 
120
+ .. warning:: This feature is experimental and may change or be removed without notice.
121
+
122
122
  Parameters
123
123
  ----------
124
124
  named_variable_set : NamedVariableSet | str
@@ -276,6 +276,19 @@ class Geometry(ProtoWrapperBase):
276
276
  )
277
277
  )
278
278
 
279
+ def convert_colors_to_tags(self) -> None:
280
+ """
281
+ Convert colors to tags in the geometry.
282
+ If the imported geometry has surface or volume colors, this will create a tag per color
283
+ (formatted as "[RRR,GGG,BBB]") and assign the corresponding surfaces and volumes to that
284
+ tag.
285
+ """
286
+ self._modify(
287
+ modification=gpb.Modification(
288
+ mod_type=gpb.Modification.MODIFICATION_TYPE_CONVERT_COLORS_TO_TAGS,
289
+ )
290
+ )
291
+
279
292
  def check(self) -> tuple[bool, list[str]]:
280
293
  """
281
294
  Check the geometry for any issues that may prevent meshing.
luminarycloud/mesh.py CHANGED
@@ -136,6 +136,22 @@ class Mesh(ProtoWrapperBase):
136
136
  """
137
137
  return get_mesh_metadata(self.id)
138
138
 
139
+ def to_code(self) -> str:
140
+ """
141
+ Returns the Python code that recreates this mesh.
142
+
143
+ Examples:
144
+ --------
145
+ >>> mesh = lc.get_mesh("mesh-123")
146
+ >>> python_code = mesh.to_code()
147
+ >>> print(python_code)
148
+ """
149
+ req = meshpb.GetMeshGenerationSdkCodeRequest(id=self.id)
150
+ res: meshpb.GetMeshGenerationSdkCodeResponse = (
151
+ get_default_client().GetMeshGenerationSdkCode(req)
152
+ )
153
+ return res.sdk_code
154
+
139
155
 
140
156
  def get_mesh(id: MeshID) -> Mesh:
141
157
  """
@@ -4,7 +4,6 @@ from datetime import datetime
4
4
  from ._client import get_default_client
5
5
  from ._helpers._timestamp_to_datetime import timestamp_to_datetime
6
6
  from ._helpers.named_variables import _named_variables_from_proto, _named_variables_to_proto
7
- from ._helpers.warnings import experimental
8
7
  from ._proto.api.v0.luminarycloud.named_variable_set import (
9
8
  named_variable_set_pb2 as namedvariablepb,
10
9
  )
@@ -12,13 +11,12 @@ from ._wrapper import ProtoWrapper, ProtoWrapperBase
12
11
  from .types import ProjectID, NamedVariableSetID, LcFloat
13
12
 
14
13
 
15
- @experimental
16
14
  @ProtoWrapper(namedvariablepb.NamedVariableSet)
17
15
  class NamedVariableSet(ProtoWrapperBase):
18
16
  """
19
17
  Represents a named variable set object.
20
18
 
21
- Note: This class is experimental and may change in the future.
19
+ .. warning:: This feature is experimental and may change or be removed without notice.
22
20
 
23
21
  Attributes
24
22
  ----------
@@ -119,11 +117,12 @@ class NamedVariableSet(ProtoWrapperBase):
119
117
  return self._named_variables
120
118
 
121
119
 
122
- @experimental
123
120
  def get_named_variable_set(id: NamedVariableSetID) -> NamedVariableSet:
124
121
  """
125
122
  Retrieve a specific named variable set by ID.
126
123
 
124
+ .. warning:: This feature is experimental and may change or be removed without notice.
125
+
127
126
  Parameters
128
127
  ----------
129
128
  id : str
@@ -4,7 +4,6 @@ from .._client import get_default_client
4
4
  from .._proto.api.v0.luminarycloud.stopping_condition import stopping_condition_pb2 as stopcondpb
5
5
  from .._proto.output import output_pb2 as outputpb
6
6
  from dataclasses import dataclass
7
- from .._helpers.warnings import experimental
8
7
 
9
8
 
10
9
  @dataclass
@@ -155,7 +154,6 @@ def delete_stopping_condition(simulation_template_id: str, id: str) -> None:
155
154
  get_default_client().DeleteStoppingCondition(req)
156
155
 
157
156
 
158
- @experimental
159
157
  def get_general_stopping_conditions(simulation_template_id: str) -> GeneralStoppingConditions:
160
158
  """
161
159
  Get the general stopping conditions for a simulation template.
@@ -174,7 +172,6 @@ def get_general_stopping_conditions(simulation_template_id: str) -> GeneralStopp
174
172
  return GeneralStoppingConditions._from_proto(res.basic_stopping_conditions)
175
173
 
176
174
 
177
- @experimental
178
175
  def update_general_stopping_conditions(
179
176
  simulation_template_id: str,
180
177
  max_iterations: int | None = None,
@@ -4,12 +4,10 @@ from typing import List, Optional
4
4
  from .._client import get_default_client
5
5
  from .._proto.api.v0.luminarycloud.physics_ai import physics_ai_pb2 as physaipb
6
6
  from .._wrapper import ProtoWrapper, ProtoWrapperBase
7
- from .._helpers.warnings import experimental
8
7
  from ..types.ids import PhysicsAiArchitectureID, PhysicsAiArchitectureVersionID
9
8
  from ..enum.physics_ai_lifecycle_state import PhysicsAiLifecycleState
10
9
 
11
10
 
12
- @experimental
13
11
  @ProtoWrapper(physaipb.PhysicsAiArchitectureVersion)
14
12
  class PhysicsAiArchitectureVersion(ProtoWrapperBase):
15
13
  """
@@ -25,7 +23,6 @@ class PhysicsAiArchitectureVersion(ProtoWrapperBase):
25
23
  _proto: physaipb.PhysicsAiArchitectureVersion
26
24
 
27
25
 
28
- @experimental
29
26
  @ProtoWrapper(physaipb.PhysicsAiArchitecture)
30
27
  class PhysicsAiArchitecture(ProtoWrapperBase):
31
28
  """
@@ -55,7 +52,6 @@ class PhysicsAiArchitecture(ProtoWrapperBase):
55
52
  return self.versions[0] if self.versions else None
56
53
 
57
54
 
58
- @experimental
59
55
  def list_architectures() -> List[PhysicsAiArchitecture]:
60
56
  """
61
57
  List available Physics AI architectures for model training.
@@ -14,7 +14,6 @@ from .._proto.api.v0.luminarycloud.inference import inference_pb2 as inferencepb
14
14
  from .._proto.inferenceservice import inferenceservice_pb2 as inferenceservicepb
15
15
  from .._wrapper import ProtoWrapper, ProtoWrapperBase
16
16
  from ..project import Project
17
- from .._helpers.warnings import experimental
18
17
  from ..project import Project
19
18
  from .._helpers import upload_file
20
19
  from .._proto.upload import upload_pb2 as uploadpb
@@ -48,7 +47,6 @@ class ExtAeroInferenceResult:
48
47
  self.pressure_surface = inference_result.get("pressure_surface", None)
49
48
 
50
49
 
51
- @experimental
52
50
  def external_aero_inference(
53
51
  project: Project, stl_file: str, checkpoint_file: str, config_name: str, stencil_size: int
54
52
  ) -> ExtAeroInferenceResult:
@@ -77,7 +75,6 @@ def external_aero_inference(
77
75
  return ExtAeroInferenceResult(result)
78
76
 
79
77
 
80
- @experimental
81
78
  def perform_inference(
82
79
  project: Project, stl_file: str, checkpoint_file: str, config_name: str, stencil_size: int
83
80
  ) -> dict[str, Any]:
@@ -144,7 +141,6 @@ def perform_inference(
144
141
  return currated
145
142
 
146
143
 
147
- @experimental
148
144
  def start_inference_job(
149
145
  project: Project,
150
146
  stl_url: str,
@@ -4,12 +4,10 @@ from typing import List, Optional
4
4
  from .._client import get_default_client
5
5
  from .._proto.api.v0.luminarycloud.physics_ai import physics_ai_pb2 as physaipb
6
6
  from .._wrapper import ProtoWrapper, ProtoWrapperBase
7
- from .._helpers.warnings import experimental
8
7
  from ..types.ids import PhysicsAiModelID, PhysicsAiModelVersionID
9
8
  from ..enum.physics_ai_lifecycle_state import PhysicsAiLifecycleState
10
9
 
11
10
 
12
- @experimental
13
11
  @ProtoWrapper(physaipb.PhysicsAiModelVersion)
14
12
  class PhysicsAiModelVersion(ProtoWrapperBase):
15
13
  """
@@ -24,7 +22,6 @@ class PhysicsAiModelVersion(ProtoWrapperBase):
24
22
  _proto: physaipb.PhysicsAiModelVersion
25
23
 
26
24
 
27
- @experimental
28
25
  @ProtoWrapper(physaipb.PhysicsAiModel)
29
26
  class PhysicsAiModel(ProtoWrapperBase):
30
27
  """
@@ -54,7 +51,6 @@ class PhysicsAiModel(ProtoWrapperBase):
54
51
  return self.versions[0] if self.versions else None
55
52
 
56
53
 
57
- @experimental
58
54
  def list_pretrained_models() -> List[PhysicsAiModel]:
59
55
  """
60
56
  List available pretrained Physics AI models.
@@ -4,12 +4,10 @@ import tarfile
4
4
  from typing import List, Optional, BinaryIO, cast
5
5
 
6
6
  from .._client import get_default_client
7
- from .._helpers.warnings import experimental
8
7
  from .._helpers.download import download_solution_physics_ai as _download_solution_physics_ai
9
8
  from ..enum.quantity_type import QuantityType
10
9
 
11
10
 
12
- @experimental
13
11
  def _download_processed_solution_physics_ai( # noqa: F841
14
12
  solution_id: str,
15
13
  exclude_surfaces: Optional[List[str]] = None,
@@ -25,6 +23,8 @@ def _download_processed_solution_physics_ai( # noqa: F841
25
23
  Returns a compressed archive containing processed solution files including
26
24
  merged surfaces (VTP/STL) and optionally volume data (VTU).
27
25
 
26
+ .. warning:: This feature is experimental and may change or be removed without notice.
27
+
28
28
  Args:
29
29
  solution_id: ID of the solution to download
30
30
  exclude_surfaces: List of surface names to exclude from processing
@@ -1,6 +1,7 @@
1
1
  # Copyright 2025 Luminary Cloud, Inc. All Rights Reserved.
2
2
  from .core import (
3
3
  Pipeline as Pipeline,
4
+ PipelineParameter as PipelineParameter,
4
5
  )
5
6
 
6
7
  from .parameters import (
@@ -27,3 +28,8 @@ from .operators import (
27
28
  Simulate as Simulate,
28
29
  SimulateOutputs as SimulateOutputs,
29
30
  )
31
+
32
+ from .arguments import (
33
+ PipelineArgs as PipelineArgs,
34
+ ArgNamedVariableSet as ArgNamedVariableSet,
35
+ )
@@ -0,0 +1,105 @@
1
+ # Copyright 2025 Luminary Cloud, Inc. All Rights Reserved.
2
+ from typing import Any, Type
3
+
4
+ from .core import PipelineParameter
5
+
6
+
7
+ class _NVS(PipelineParameter):
8
+ @classmethod
9
+ def _represented_type(cls) -> Type:
10
+ return str
11
+
12
+ @classmethod
13
+ def _type_name(cls) -> str:
14
+ return "Named Variable Set"
15
+
16
+ def _validate(self) -> None:
17
+ if self.name != "$named-variable-set":
18
+ raise ValueError(
19
+ "The Named Variable Set PipelineParameter must be named '$named-variable-set'"
20
+ )
21
+
22
+ def _add_to_params(self, params: dict) -> None:
23
+ raise ValueError(
24
+ "The NamedVariableSet parameter cannot be used explicitly in a Pipeline. It can only be used in PipelineArgs."
25
+ )
26
+
27
+ def _is_valid_value(self, value: Any) -> bool:
28
+ return isinstance(value, str) and value.startswith("namedvarset-")
29
+
30
+
31
+ ArgNamedVariableSet = _NVS("$named-variable-set")
32
+ """
33
+ This can be used in a PipelineArgs params list to add a Named Variable Set column to the args table.
34
+ There must be zero or one of these in a PipelineArgs params list.
35
+ """
36
+
37
+ # The types that are allowed as PipelineArgs values. This is a union of all concrete
38
+ # PipelineParameters' "represented types".
39
+ PipelineArgValueType = str | int | float | bool
40
+
41
+
42
+ class PipelineArgsRow:
43
+ def __init__(self, args: "PipelineArgs", row_values: list[PipelineArgValueType]):
44
+ self.args = args
45
+ self.row_values = row_values
46
+ self._validate()
47
+
48
+ def _validate(self) -> None:
49
+ if len(self.row_values) != len(self.args.params):
50
+ raise ValueError(
51
+ f"PipelineArgs row wrong size. Expected {len(self.args.params)}, got {len(self.row_values)}"
52
+ )
53
+ for i, v in enumerate(self.row_values):
54
+ param = self.args.params[i]
55
+ if not param._is_valid_value(v):
56
+ raise ValueError(f"PipelineArgs value {v} is invalid for parameter {param}")
57
+
58
+ def value_for(self, param_name: str) -> PipelineArgValueType:
59
+ return self.row_values[self.args.column_for(param_name)]
60
+
61
+ def has_column_for(self, param_name: str) -> bool:
62
+ return self.args.has_column_for(param_name)
63
+
64
+ def __str__(self) -> str:
65
+ s = "PipelineArgsRow("
66
+ for i, v in enumerate(self.row_values):
67
+ s += f"{self.args.params[i].name}={repr(v)}, "
68
+ s += ")"
69
+ return s
70
+
71
+
72
+ class PipelineArgs:
73
+ def __init__(self, params: list[PipelineParameter], args: list[list[PipelineArgValueType]]):
74
+ self.params = params
75
+ self._param_index_by_name = {p.name: i for i, p in enumerate(params)}
76
+ self._validate_params()
77
+ self.rows = [PipelineArgsRow(self, arg) for arg in args]
78
+
79
+ def has_column_for(self, param_name: str) -> bool:
80
+ return param_name in self._param_index_by_name
81
+
82
+ def column_for(self, param_name: str) -> int:
83
+ if not self.has_column_for(param_name):
84
+ raise ValueError(f'Parameter "{param_name}" not found')
85
+ return self._param_index_by_name[param_name]
86
+
87
+ def _validate_params(self) -> None:
88
+ has_nvs = False
89
+ seen_param_names = set()
90
+ for p in self.params:
91
+ if isinstance(p, _NVS):
92
+ if has_nvs:
93
+ raise ValueError(
94
+ "There can be at most one Named Variable Set column in a PipelineArgs"
95
+ )
96
+ has_nvs = True
97
+ else:
98
+ if p.name in seen_param_names:
99
+ raise ValueError(f'There is more than one parameter named "{p.name}"')
100
+ seen_param_names.add(p.name)
101
+
102
+ def __str__(self) -> str:
103
+ return (
104
+ f"PipelineArgs(param_names={[p.name for p in self.params]}, row_count={len(self.rows)})"
105
+ )