luminarycloud 0.17.0__py3-none-any.whl → 0.18.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.
- luminarycloud/_client/client.py +3 -0
- luminarycloud/_helpers/_create_geometry.py +134 -32
- luminarycloud/_helpers/cond.py +0 -1
- luminarycloud/_proto/api/v0/luminarycloud/geometry/geometry_pb2.py +146 -123
- luminarycloud/_proto/api/v0/luminarycloud/geometry/geometry_pb2.pyi +81 -8
- luminarycloud/_proto/api/v0/luminarycloud/geometry/geometry_pb2_grpc.py +34 -0
- luminarycloud/_proto/api/v0/luminarycloud/geometry/geometry_pb2_grpc.pyi +12 -0
- luminarycloud/_proto/api/v0/luminarycloud/inference/inference_pb2.py +8 -8
- luminarycloud/_proto/api/v0/luminarycloud/inference/inference_pb2.pyi +12 -7
- luminarycloud/_proto/api/v0/luminarycloud/pipelines/pipelines_pb2.py +246 -0
- luminarycloud/_proto/api/v0/luminarycloud/pipelines/pipelines_pb2.pyi +420 -0
- luminarycloud/_proto/api/v0/luminarycloud/pipelines/pipelines_pb2_grpc.py +240 -0
- luminarycloud/_proto/api/v0/luminarycloud/pipelines/pipelines_pb2_grpc.pyi +90 -0
- luminarycloud/_proto/api/v0/luminarycloud/project/project_pb2.py +54 -3
- luminarycloud/_proto/api/v0/luminarycloud/project/project_pb2.pyi +92 -1
- luminarycloud/_proto/api/v0/luminarycloud/project/project_pb2_grpc.py +132 -0
- luminarycloud/_proto/api/v0/luminarycloud/project/project_pb2_grpc.pyi +40 -0
- luminarycloud/_proto/api/v0/luminarycloud/simulation_template/simulation_template_pb2.py +48 -26
- luminarycloud/_proto/api/v0/luminarycloud/simulation_template/simulation_template_pb2.pyi +30 -2
- luminarycloud/_proto/api/v0/luminarycloud/simulation_template/simulation_template_pb2_grpc.py +36 -0
- luminarycloud/_proto/api/v0/luminarycloud/simulation_template/simulation_template_pb2_grpc.pyi +18 -0
- luminarycloud/_proto/client/simulation_pb2.py +261 -251
- luminarycloud/_proto/client/simulation_pb2.pyi +35 -2
- luminarycloud/_proto/frontend/output/output_pb2.py +24 -24
- luminarycloud/_proto/frontend/output/output_pb2.pyi +6 -3
- luminarycloud/_proto/geometry/geometry_pb2.py +63 -63
- luminarycloud/_proto/geometry/geometry_pb2.pyi +14 -4
- luminarycloud/_proto/inferenceservice/inferenceservice_pb2.py +10 -10
- luminarycloud/_proto/inferenceservice/inferenceservice_pb2.pyi +12 -7
- luminarycloud/enum/geometry_status.py +15 -8
- luminarycloud/enum/pipeline_job_status.py +23 -0
- luminarycloud/feature_modification.py +3 -1
- luminarycloud/geometry.py +12 -0
- luminarycloud/geometry_version.py +23 -0
- luminarycloud/params/enum/_enum_wrappers.py +29 -0
- luminarycloud/params/simulation/physics/fluid/boundary_conditions/inlet/fan_curve_inlet_.py +1 -1
- luminarycloud/params/simulation/physics/fluid/boundary_conditions/inlet/mach_inlet_.py +5 -1
- luminarycloud/params/simulation/physics/fluid/boundary_conditions/inlet/mass_flow_inlet_.py +5 -1
- luminarycloud/params/simulation/physics/fluid/boundary_conditions/inlet/total_pressure_inlet_.py +5 -1
- luminarycloud/params/simulation/physics/fluid/boundary_conditions/inlet/velocity_magnitude_inlet_.py +5 -1
- luminarycloud/physics_ai/inference.py +46 -30
- luminarycloud/pipelines/__init__.py +7 -0
- luminarycloud/pipelines/api.py +213 -0
- luminarycloud/project.py +65 -5
- luminarycloud/simulation_template.py +15 -6
- luminarycloud/vis/__init__.py +4 -0
- luminarycloud/vis/interactive_inference.py +153 -0
- luminarycloud/vis/interactive_scene.py +35 -16
- luminarycloud/vis/primitives.py +9 -0
- luminarycloud/vis/visualization.py +6 -0
- luminarycloud/volume_selection.py +3 -2
- {luminarycloud-0.17.0.dist-info → luminarycloud-0.18.0.dist-info}/METADATA +18 -18
- {luminarycloud-0.17.0.dist-info → luminarycloud-0.18.0.dist-info}/RECORD +54 -47
- {luminarycloud-0.17.0.dist-info → luminarycloud-0.18.0.dist-info}/WHEEL +0 -0
luminarycloud/geometry.py
CHANGED
|
@@ -29,6 +29,7 @@ from .named_variable_set import NamedVariableSet, get_named_variable_set
|
|
|
29
29
|
|
|
30
30
|
if TYPE_CHECKING:
|
|
31
31
|
from .project import Project
|
|
32
|
+
from .geometry_version import GeometryVersion
|
|
32
33
|
|
|
33
34
|
|
|
34
35
|
@ProtoWrapper(geometrypb.Geometry)
|
|
@@ -289,6 +290,17 @@ class Geometry(ProtoWrapperBase):
|
|
|
289
290
|
)
|
|
290
291
|
)
|
|
291
292
|
|
|
293
|
+
def latest_version(self) -> GeometryVersion:
|
|
294
|
+
"""
|
|
295
|
+
Get the latest version of the geometry.
|
|
296
|
+
"""
|
|
297
|
+
from .geometry_version import get_geometry_version
|
|
298
|
+
|
|
299
|
+
req = geometrypb.GetGeometryRequest(geometry_id=self.id)
|
|
300
|
+
res_geo: geometrypb.GetGeometryResponse = get_default_client().GetGeometry(req)
|
|
301
|
+
geometry_version_id = res_geo.geometry.last_version_id
|
|
302
|
+
return get_geometry_version(geometry_version_id)
|
|
303
|
+
|
|
292
304
|
def check(self) -> tuple[bool, list[str]]:
|
|
293
305
|
"""
|
|
294
306
|
Check the geometry for any issues that may prevent meshing.
|
|
@@ -87,6 +87,29 @@ class GeometryVersion(ProtoWrapperBase):
|
|
|
87
87
|
]
|
|
88
88
|
return surfaces, volumes
|
|
89
89
|
|
|
90
|
+
def copy_to_new_geometry(self, name: str = "") -> Geometry:
|
|
91
|
+
"""
|
|
92
|
+
Copy this GeometryVersion and create a new Geometry containing only that newly copied version.
|
|
93
|
+
|
|
94
|
+
Parameters
|
|
95
|
+
----------
|
|
96
|
+
name : str, optional
|
|
97
|
+
The name of the new Geometry. If not provided, a default name will be used.
|
|
98
|
+
|
|
99
|
+
Returns
|
|
100
|
+
-------
|
|
101
|
+
Geometry
|
|
102
|
+
The new Geometry containing only the newly copied GeometryVersion.
|
|
103
|
+
"""
|
|
104
|
+
req = geometrypb.CopyGeometryFromVersionRequest(
|
|
105
|
+
geometry_version_id=self.id,
|
|
106
|
+
name=name,
|
|
107
|
+
)
|
|
108
|
+
res: geometrypb.CopyGeometryFromVersionResponse = (
|
|
109
|
+
get_default_client().CopyGeometryFromVersion(req)
|
|
110
|
+
)
|
|
111
|
+
return Geometry(res.geometry)
|
|
112
|
+
|
|
90
113
|
def _list_features(
|
|
91
114
|
self,
|
|
92
115
|
) -> list[gpb.Feature]:
|
|
@@ -1776,6 +1776,9 @@ class DirectionSpecification(_IntEnum):
|
|
|
1776
1776
|
Impose a flow direction normal to the inlet boundary toward the interior of the domain.
|
|
1777
1777
|
DIRECTION_VECTOR
|
|
1778
1778
|
Specify a vector for the inlet flow direction.
|
|
1779
|
+
CYLINDRICAL_DIRECTIONS
|
|
1780
|
+
Specify the inlet flow direction in a cylindrical coordinate system whose main axis
|
|
1781
|
+
is defined by the z axis of the inlet frame.
|
|
1779
1782
|
|
|
1780
1783
|
|
|
1781
1784
|
Examples
|
|
@@ -1783,11 +1786,37 @@ class DirectionSpecification(_IntEnum):
|
|
|
1783
1786
|
>>> from luminarycloud.params.enum import DirectionSpecification
|
|
1784
1787
|
>>> DirectionSpecification.NORMAL_TO_BOUNDARY
|
|
1785
1788
|
>>> DirectionSpecification.DIRECTION_VECTOR
|
|
1789
|
+
>>> DirectionSpecification.CYLINDRICAL_DIRECTIONS
|
|
1786
1790
|
"""
|
|
1787
1791
|
|
|
1788
1792
|
INVALID = _clientpb.INVALID_DIRECTION_SPECIFICATION
|
|
1789
1793
|
NORMAL_TO_BOUNDARY = _clientpb.NORMAL_TO_BOUNDARY
|
|
1790
1794
|
DIRECTION_VECTOR = _clientpb.DIRECTION_VECTOR
|
|
1795
|
+
CYLINDRICAL_DIRECTIONS = _clientpb.CYLINDRICAL_DIRECTIONS
|
|
1796
|
+
|
|
1797
|
+
|
|
1798
|
+
class DirectionFrame(_IntEnum):
|
|
1799
|
+
"""
|
|
1800
|
+
Frame used to define the flow direction.
|
|
1801
|
+
|
|
1802
|
+
Attributes
|
|
1803
|
+
----------
|
|
1804
|
+
DIRECTION_FRAME_GLOBAL
|
|
1805
|
+
The direction vectors are defined by the global frame.
|
|
1806
|
+
DIRECTION_FRAME_BOUNDARY
|
|
1807
|
+
The direction vectors are defined by the frame to which the boundary surfaces are attached.
|
|
1808
|
+
|
|
1809
|
+
|
|
1810
|
+
Examples
|
|
1811
|
+
--------
|
|
1812
|
+
>>> from luminarycloud.params.enum import DirectionFrame
|
|
1813
|
+
>>> DirectionFrame.DIRECTION_FRAME_GLOBAL
|
|
1814
|
+
>>> DirectionFrame.DIRECTION_FRAME_BOUNDARY
|
|
1815
|
+
"""
|
|
1816
|
+
|
|
1817
|
+
INVALID = _clientpb.INVALID_DIRECTION_FRAME
|
|
1818
|
+
DIRECTION_FRAME_GLOBAL = _clientpb.DIRECTION_FRAME_GLOBAL
|
|
1819
|
+
DIRECTION_FRAME_BOUNDARY = _clientpb.DIRECTION_FRAME_BOUNDARY
|
|
1791
1820
|
|
|
1792
1821
|
|
|
1793
1822
|
class OutletPressureConstraint(_IntEnum):
|
|
@@ -32,7 +32,7 @@ class FanCurveInlet(Inlet):
|
|
|
32
32
|
)
|
|
33
33
|
"Method of defining the flow direction at the inlet."
|
|
34
34
|
direction: Vector3 = field(default_factory=lambda: Vector3(1.0, 0.0, 0.0))
|
|
35
|
-
"Vector (x,y,z) defining the flow direction. Automatically scaled to a unit vector internally."
|
|
35
|
+
"Vector (x,y,z) or (ρ,φ,z) defining the flow direction. Automatically scaled to a unit vector internally."
|
|
36
36
|
fan_curve_table: RectilinearTable | None = None
|
|
37
37
|
"Correlation between fan pressure rise and volume flow rate."
|
|
38
38
|
head_loss_coefficient: LcFloat = 0.0
|
|
@@ -33,8 +33,10 @@ class MachInlet(Inlet):
|
|
|
33
33
|
enum.DirectionSpecification.NORMAL_TO_BOUNDARY
|
|
34
34
|
)
|
|
35
35
|
"Method of defining the flow direction at the inlet."
|
|
36
|
+
direction_frame: enum.DirectionFrame = enum.DirectionFrame.DIRECTION_FRAME_GLOBAL
|
|
37
|
+
"Frame used to define the flow direction."
|
|
36
38
|
direction: Vector3 = field(default_factory=lambda: Vector3(1.0, 0.0, 0.0))
|
|
37
|
-
"Vector (x,y,z) defining the flow direction. Automatically scaled to a unit vector internally."
|
|
39
|
+
"Vector (x,y,z) or (ρ,φ,z) defining the flow direction. Automatically scaled to a unit vector internally."
|
|
38
40
|
|
|
39
41
|
def _to_proto(self) -> clientpb.BoundaryConditionsFluid:
|
|
40
42
|
_proto = super()._to_proto()
|
|
@@ -42,6 +44,7 @@ class MachInlet(Inlet):
|
|
|
42
44
|
_proto.farfield_mach_number.CopyFrom(_to_ad_proto(self.mach_number))
|
|
43
45
|
_proto.farfield_pressure.CopyFrom(_to_ad_proto(self.pressure))
|
|
44
46
|
_proto.direction_specification = self.direction_specification.value
|
|
47
|
+
_proto.direction_frame = self.direction_frame.value
|
|
45
48
|
_proto.flow_direction.CopyFrom(self.direction._to_ad_proto())
|
|
46
49
|
return _proto
|
|
47
50
|
|
|
@@ -51,5 +54,6 @@ class MachInlet(Inlet):
|
|
|
51
54
|
self.mach_number = _from_ad_proto(proto.farfield_mach_number)
|
|
52
55
|
self.pressure = _from_ad_proto(proto.farfield_pressure)
|
|
53
56
|
self.direction_specification = enum.DirectionSpecification(proto.direction_specification)
|
|
57
|
+
self.direction_frame = enum.DirectionFrame(proto.direction_frame)
|
|
54
58
|
self.direction._from_ad_proto(proto.flow_direction)
|
|
55
59
|
return None
|
|
@@ -31,14 +31,17 @@ class MassFlowInlet(Inlet):
|
|
|
31
31
|
enum.DirectionSpecification.NORMAL_TO_BOUNDARY
|
|
32
32
|
)
|
|
33
33
|
"Method of defining the flow direction at the inlet."
|
|
34
|
+
direction_frame: enum.DirectionFrame = enum.DirectionFrame.DIRECTION_FRAME_GLOBAL
|
|
35
|
+
"Frame used to define the flow direction."
|
|
34
36
|
direction: Vector3 = field(default_factory=lambda: Vector3(1.0, 0.0, 0.0))
|
|
35
|
-
"Vector (x,y,z) defining the flow direction. Automatically scaled to a unit vector internally."
|
|
37
|
+
"Vector (x,y,z) or (ρ,φ,z) defining the flow direction. Automatically scaled to a unit vector internally."
|
|
36
38
|
|
|
37
39
|
def _to_proto(self) -> clientpb.BoundaryConditionsFluid:
|
|
38
40
|
_proto = super()._to_proto()
|
|
39
41
|
_proto.inlet_momentum = clientpb.InletMomentum.MASS_FLOW_INLET
|
|
40
42
|
_proto.mass_flow_rate.CopyFrom(_to_ad_proto(self.mass_flow_rate))
|
|
41
43
|
_proto.direction_specification = self.direction_specification.value
|
|
44
|
+
_proto.direction_frame = self.direction_frame.value
|
|
42
45
|
_proto.flow_direction.CopyFrom(self.direction._to_ad_proto())
|
|
43
46
|
return _proto
|
|
44
47
|
|
|
@@ -47,5 +50,6 @@ class MassFlowInlet(Inlet):
|
|
|
47
50
|
assert proto.inlet_momentum == clientpb.InletMomentum.MASS_FLOW_INLET
|
|
48
51
|
self.mass_flow_rate = _from_ad_proto(proto.mass_flow_rate)
|
|
49
52
|
self.direction_specification = enum.DirectionSpecification(proto.direction_specification)
|
|
53
|
+
self.direction_frame = enum.DirectionFrame(proto.direction_frame)
|
|
50
54
|
self.direction._from_ad_proto(proto.flow_direction)
|
|
51
55
|
return None
|
luminarycloud/params/simulation/physics/fluid/boundary_conditions/inlet/total_pressure_inlet_.py
CHANGED
|
@@ -33,8 +33,10 @@ class TotalPressureInlet(Inlet):
|
|
|
33
33
|
enum.DirectionSpecification.NORMAL_TO_BOUNDARY
|
|
34
34
|
)
|
|
35
35
|
"Method of defining the flow direction at the inlet."
|
|
36
|
+
direction_frame: enum.DirectionFrame = enum.DirectionFrame.DIRECTION_FRAME_GLOBAL
|
|
37
|
+
"Frame used to define the flow direction."
|
|
36
38
|
direction: Vector3 = field(default_factory=lambda: Vector3(1.0, 0.0, 0.0))
|
|
37
|
-
"Vector (x,y,z) defining the flow direction. Automatically scaled to a unit vector internally."
|
|
39
|
+
"Vector (x,y,z) or (ρ,φ,z) defining the flow direction. Automatically scaled to a unit vector internally."
|
|
38
40
|
|
|
39
41
|
def _to_proto(self) -> clientpb.BoundaryConditionsFluid:
|
|
40
42
|
_proto = super()._to_proto()
|
|
@@ -42,6 +44,7 @@ class TotalPressureInlet(Inlet):
|
|
|
42
44
|
_proto.total_pressure.CopyFrom(_to_ad_proto(self.total_pressure))
|
|
43
45
|
_proto.total_pressure_col.value = self.total_pressure_column_index
|
|
44
46
|
_proto.direction_specification = self.direction_specification.value
|
|
47
|
+
_proto.direction_frame = self.direction_frame.value
|
|
45
48
|
_proto.flow_direction.CopyFrom(self.direction._to_ad_proto())
|
|
46
49
|
return _proto
|
|
47
50
|
|
|
@@ -51,5 +54,6 @@ class TotalPressureInlet(Inlet):
|
|
|
51
54
|
self.total_pressure = _from_ad_proto(proto.total_pressure)
|
|
52
55
|
self.total_pressure_column_index = proto.total_pressure_col.value
|
|
53
56
|
self.direction_specification = enum.DirectionSpecification(proto.direction_specification)
|
|
57
|
+
self.direction_frame = enum.DirectionFrame(proto.direction_frame)
|
|
54
58
|
self.direction._from_ad_proto(proto.flow_direction)
|
|
55
59
|
return None
|
luminarycloud/params/simulation/physics/fluid/boundary_conditions/inlet/velocity_magnitude_inlet_.py
CHANGED
|
@@ -33,8 +33,10 @@ class VelocityMagnitudeInlet(Inlet):
|
|
|
33
33
|
enum.DirectionSpecification.NORMAL_TO_BOUNDARY
|
|
34
34
|
)
|
|
35
35
|
"Method of defining the flow direction at the inlet."
|
|
36
|
+
direction_frame: enum.DirectionFrame = enum.DirectionFrame.DIRECTION_FRAME_GLOBAL
|
|
37
|
+
"Frame used to define the flow direction."
|
|
36
38
|
direction: Vector3 = field(default_factory=lambda: Vector3(1.0, 0.0, 0.0))
|
|
37
|
-
"Vector (x,y,z) defining the flow direction. Automatically scaled to a unit vector internally."
|
|
39
|
+
"Vector (x,y,z) or (ρ,φ,z) defining the flow direction. Automatically scaled to a unit vector internally."
|
|
38
40
|
pressure: LcFloat = 101325
|
|
39
41
|
"Static pressure at the boundary relative to the material reference pressure."
|
|
40
42
|
|
|
@@ -44,6 +46,7 @@ class VelocityMagnitudeInlet(Inlet):
|
|
|
44
46
|
_proto.inlet_velocity_magnitude.CopyFrom(_to_ad_proto(self.velocity))
|
|
45
47
|
_proto.inlet_velocity_magnitude_col.value = self.velocity_column_index
|
|
46
48
|
_proto.direction_specification = self.direction_specification.value
|
|
49
|
+
_proto.direction_frame = self.direction_frame.value
|
|
47
50
|
_proto.flow_direction.CopyFrom(self.direction._to_ad_proto())
|
|
48
51
|
_proto.farfield_pressure.CopyFrom(_to_ad_proto(self.pressure))
|
|
49
52
|
return _proto
|
|
@@ -54,6 +57,7 @@ class VelocityMagnitudeInlet(Inlet):
|
|
|
54
57
|
self.velocity = _from_ad_proto(proto.inlet_velocity_magnitude)
|
|
55
58
|
self.velocity_column_index = proto.inlet_velocity_magnitude_col.value
|
|
56
59
|
self.direction_specification = enum.DirectionSpecification(proto.direction_specification)
|
|
60
|
+
self.direction_frame = enum.DirectionFrame(proto.direction_frame)
|
|
57
61
|
self.direction._from_ad_proto(proto.flow_direction)
|
|
58
62
|
self.pressure = _from_ad_proto(proto.farfield_pressure)
|
|
59
63
|
return None
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# File: python/sdk/luminarycloud/inference/inference.py
|
|
2
2
|
# Copyright 2025 Luminary Cloud, Inc. All Rights Reserved.
|
|
3
3
|
from datetime import datetime
|
|
4
|
-
from typing import Any, Callable
|
|
5
|
-
from json import loads as json_loads
|
|
4
|
+
from typing import Any, Callable, Dict, Optional
|
|
5
|
+
from json import loads as json_loads, dumps as json_dumps
|
|
6
6
|
from dataclasses import dataclass
|
|
7
7
|
import base64
|
|
8
8
|
import os
|
|
@@ -48,7 +48,11 @@ class ExtAeroInferenceResult:
|
|
|
48
48
|
|
|
49
49
|
|
|
50
50
|
def external_aero_inference(
|
|
51
|
-
project: Project,
|
|
51
|
+
project: Project,
|
|
52
|
+
stl_file: str,
|
|
53
|
+
artifact_url: str,
|
|
54
|
+
parameters: Optional[Dict[str, Any]] = None,
|
|
55
|
+
stencil_size: int = 1,
|
|
52
56
|
) -> ExtAeroInferenceResult:
|
|
53
57
|
"""Performs an inference job returning external aerodynamic results.
|
|
54
58
|
Parameters
|
|
@@ -57,12 +61,12 @@ def external_aero_inference(
|
|
|
57
61
|
The project to which the inference files will be added.
|
|
58
62
|
stl_file : str
|
|
59
63
|
Fullpath the STL file to be used for inference.
|
|
60
|
-
|
|
61
|
-
Fullpath of the model to be used for inference.
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
stencil_size :int
|
|
65
|
-
Size of the stencil to be used for inference.
|
|
64
|
+
artifact_url : str
|
|
65
|
+
Fullpath of the model artifact directory to be used for inference.
|
|
66
|
+
parameters : Dict[str, Any], optional
|
|
67
|
+
Dictionary of parameters to be passed to the inference service (e.g., alpha, beta, etc.).
|
|
68
|
+
stencil_size : int, optional
|
|
69
|
+
Size of the stencil to be used for inference. Defaults to 1.
|
|
66
70
|
|
|
67
71
|
Returns
|
|
68
72
|
ExtAeroInferenceResult
|
|
@@ -71,12 +75,16 @@ def external_aero_inference(
|
|
|
71
75
|
warning:: This feature is experimental and may change or be removed without notice.
|
|
72
76
|
"""
|
|
73
77
|
|
|
74
|
-
result = perform_inference(project, stl_file,
|
|
78
|
+
result = perform_inference(project, stl_file, artifact_url, parameters, stencil_size)
|
|
75
79
|
return ExtAeroInferenceResult(result)
|
|
76
80
|
|
|
77
81
|
|
|
78
82
|
def perform_inference(
|
|
79
|
-
project: Project,
|
|
83
|
+
project: Project,
|
|
84
|
+
stl_file: str,
|
|
85
|
+
artifact_url: str,
|
|
86
|
+
parameters: Optional[Dict[str, Any]] = None,
|
|
87
|
+
stencil_size: int = 1,
|
|
80
88
|
) -> dict[str, Any]:
|
|
81
89
|
"""Creates an inference service job.
|
|
82
90
|
Parameters
|
|
@@ -85,12 +93,12 @@ def perform_inference(
|
|
|
85
93
|
The project to which the inference files will be added.
|
|
86
94
|
stl_file : str
|
|
87
95
|
Fullpath the STL file to be used for inference.
|
|
88
|
-
|
|
89
|
-
Fullpath of the model to be used for inference.
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
stencil_size :int
|
|
93
|
-
Size of the stencil to be used for inference.
|
|
96
|
+
artifact_url : str
|
|
97
|
+
Fullpath of the model artifact directory to be used for inference.
|
|
98
|
+
parameters : Dict[str, Any], optional
|
|
99
|
+
Dictionary of parameters to be passed to the inference service (e.g., alpha, beta, etc.).
|
|
100
|
+
stencil_size : int, optional
|
|
101
|
+
Size of the stencil to be used for inference. Defaults to 1.
|
|
94
102
|
|
|
95
103
|
|
|
96
104
|
Returns
|
|
@@ -123,9 +131,8 @@ def perform_inference(
|
|
|
123
131
|
return download_file
|
|
124
132
|
|
|
125
133
|
stl_url = upload_if_file(stl_file)
|
|
126
|
-
check_url = upload_if_file(checkpoint_file)
|
|
127
134
|
|
|
128
|
-
raw = start_inference_job(project, stl_url,
|
|
135
|
+
raw = start_inference_job(project, stl_url, artifact_url, parameters, stencil_size)
|
|
129
136
|
currated: dict[str, Any] = {}
|
|
130
137
|
for k, v in raw.items():
|
|
131
138
|
if isinstance(v, str) and v.startswith("https://"):
|
|
@@ -144,9 +151,10 @@ def perform_inference(
|
|
|
144
151
|
def start_inference_job(
|
|
145
152
|
project: Project,
|
|
146
153
|
stl_url: str,
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
stencil_size: int,
|
|
154
|
+
artifact_url: str,
|
|
155
|
+
parameters: Optional[Dict[str, Any]] = None,
|
|
156
|
+
stencil_size: int = 1,
|
|
157
|
+
write_visualization_data=False,
|
|
150
158
|
) -> dict[str, Any]:
|
|
151
159
|
"""Creates an inference service job.
|
|
152
160
|
Parameters
|
|
@@ -155,12 +163,14 @@ def start_inference_job(
|
|
|
155
163
|
Reference to a project.
|
|
156
164
|
stl_url : str
|
|
157
165
|
URL of the STL file to be used for inference.
|
|
158
|
-
|
|
159
|
-
URL of the model to be used for inference.
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
stencil_size :int
|
|
163
|
-
Size of the stencil to be used for inference.
|
|
166
|
+
artifact_url : str
|
|
167
|
+
URL of the model artifact directory to be used for inference.
|
|
168
|
+
parameters : Dict[str, Any], optional
|
|
169
|
+
Dictionary of parameters to be passed to the inference service (e.g., alpha, beta, etc.).
|
|
170
|
+
stencil_size : int, optional
|
|
171
|
+
Size of the stencil to be used for inference. Defaults to 1.
|
|
172
|
+
write_visualization_data : bool, optional
|
|
173
|
+
Whether to write LC render data for visualization by Luminary.
|
|
164
174
|
|
|
165
175
|
|
|
166
176
|
Returns
|
|
@@ -170,12 +180,18 @@ def start_inference_job(
|
|
|
170
180
|
warning:: This feature is experimental and may change or be removed without notice.
|
|
171
181
|
"""
|
|
172
182
|
|
|
183
|
+
# Convert parameters dict to bytes if provided
|
|
184
|
+
parameters_bytes = b""
|
|
185
|
+
if parameters is not None:
|
|
186
|
+
parameters_bytes = json_dumps(parameters).encode("utf-8")
|
|
187
|
+
|
|
173
188
|
req = inferencepb.CreateInferenceServiceJobRequest(
|
|
174
189
|
stl_url=stl_url,
|
|
175
|
-
|
|
176
|
-
|
|
190
|
+
artifact_url=artifact_url,
|
|
191
|
+
parameters=parameters_bytes,
|
|
177
192
|
stencil_size=stencil_size,
|
|
178
193
|
project_id=project.id,
|
|
194
|
+
write_visualization_data=write_visualization_data,
|
|
179
195
|
)
|
|
180
196
|
|
|
181
197
|
res: inferencepb.CreateInferenceServiceJobResponse = (
|
|
@@ -33,3 +33,10 @@ from .arguments import (
|
|
|
33
33
|
PipelineArgs as PipelineArgs,
|
|
34
34
|
ArgNamedVariableSet as ArgNamedVariableSet,
|
|
35
35
|
)
|
|
36
|
+
|
|
37
|
+
from .api import (
|
|
38
|
+
create_pipeline as create_pipeline,
|
|
39
|
+
list_pipelines as list_pipelines,
|
|
40
|
+
get_pipeline as get_pipeline,
|
|
41
|
+
create_pipeline_job as create_pipeline_job,
|
|
42
|
+
)
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
# Copyright 2023-2024 Luminary Cloud, Inc. All Rights Reserved.
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
|
|
6
|
+
from luminarycloud._helpers import timestamp_to_datetime
|
|
7
|
+
|
|
8
|
+
from ..enum.pipeline_job_status import PipelineJobStatus
|
|
9
|
+
from ..pipelines import Pipeline, PipelineArgs
|
|
10
|
+
from .._client import get_default_client
|
|
11
|
+
from .._proto.api.v0.luminarycloud.pipelines import pipelines_pb2 as pipelinespb
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass
|
|
15
|
+
class PipelineRecord:
|
|
16
|
+
id: str
|
|
17
|
+
name: str
|
|
18
|
+
description: str | None
|
|
19
|
+
definition_yaml: str
|
|
20
|
+
create_time: datetime
|
|
21
|
+
update_time: datetime
|
|
22
|
+
|
|
23
|
+
def pipeline(self) -> Pipeline:
|
|
24
|
+
return Pipeline._from_yaml(self.definition_yaml)
|
|
25
|
+
|
|
26
|
+
@classmethod
|
|
27
|
+
def from_proto(cls, proto: pipelinespb.Pipeline) -> "PipelineRecord":
|
|
28
|
+
return cls(
|
|
29
|
+
id=proto.id,
|
|
30
|
+
name=proto.name,
|
|
31
|
+
description=proto.description,
|
|
32
|
+
definition_yaml=proto.definition_yaml,
|
|
33
|
+
create_time=timestamp_to_datetime(proto.created_at),
|
|
34
|
+
update_time=timestamp_to_datetime(proto.updated_at),
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@dataclass
|
|
39
|
+
class PipelineJobRecord:
|
|
40
|
+
id: str
|
|
41
|
+
pipeline_id: str
|
|
42
|
+
project_id: str
|
|
43
|
+
name: str
|
|
44
|
+
description: str | None
|
|
45
|
+
status: PipelineJobStatus
|
|
46
|
+
create_time: datetime
|
|
47
|
+
update_time: datetime
|
|
48
|
+
started_at: datetime | None
|
|
49
|
+
completed_at: datetime | None
|
|
50
|
+
|
|
51
|
+
@classmethod
|
|
52
|
+
def from_proto(cls, proto: pipelinespb.PipelineJob) -> "PipelineJobRecord":
|
|
53
|
+
return cls(
|
|
54
|
+
id=proto.id,
|
|
55
|
+
pipeline_id=proto.pipeline_id,
|
|
56
|
+
project_id=proto.project_id,
|
|
57
|
+
name=proto.name,
|
|
58
|
+
description=proto.description,
|
|
59
|
+
status=PipelineJobStatus(proto.status),
|
|
60
|
+
create_time=timestamp_to_datetime(proto.created_at),
|
|
61
|
+
update_time=timestamp_to_datetime(proto.updated_at),
|
|
62
|
+
started_at=(
|
|
63
|
+
timestamp_to_datetime(proto.started_at) if proto.HasField("started_at") else None
|
|
64
|
+
),
|
|
65
|
+
completed_at=(
|
|
66
|
+
timestamp_to_datetime(proto.completed_at)
|
|
67
|
+
if proto.HasField("completed_at")
|
|
68
|
+
else None
|
|
69
|
+
),
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def create_pipeline(
|
|
74
|
+
name: str, pipeline: Pipeline | str, description: str | None = None
|
|
75
|
+
) -> PipelineRecord:
|
|
76
|
+
"""
|
|
77
|
+
Create a new pipeline.
|
|
78
|
+
|
|
79
|
+
Parameters
|
|
80
|
+
----------
|
|
81
|
+
name : str
|
|
82
|
+
Name of the pipeline.
|
|
83
|
+
pipeline : Pipeline | str
|
|
84
|
+
The pipeline to create. Accepts a Pipeline object or a YAML-formatted pipeline definition.
|
|
85
|
+
description : str, optional
|
|
86
|
+
Description of the pipeline.
|
|
87
|
+
"""
|
|
88
|
+
if isinstance(pipeline, Pipeline):
|
|
89
|
+
definition_yaml = pipeline.to_yaml()
|
|
90
|
+
else:
|
|
91
|
+
definition_yaml = pipeline
|
|
92
|
+
req = pipelinespb.CreatePipelineRequest(
|
|
93
|
+
name=name, definition_yaml=definition_yaml, description=description
|
|
94
|
+
)
|
|
95
|
+
res: pipelinespb.CreatePipelineResponse = get_default_client().CreatePipeline(req)
|
|
96
|
+
return PipelineRecord.from_proto(res.pipeline)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def list_pipelines() -> list[PipelineRecord]:
|
|
100
|
+
"""
|
|
101
|
+
List all pipelines.
|
|
102
|
+
"""
|
|
103
|
+
req = pipelinespb.ListPipelinesRequest()
|
|
104
|
+
res: pipelinespb.ListPipelinesResponse = get_default_client().ListPipelines(req)
|
|
105
|
+
return [PipelineRecord.from_proto(p) for p in res.pipelines]
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def get_pipeline(id: str) -> PipelineRecord:
|
|
109
|
+
"""
|
|
110
|
+
Get a pipeline by ID.
|
|
111
|
+
|
|
112
|
+
Parameters
|
|
113
|
+
----------
|
|
114
|
+
id : str
|
|
115
|
+
ID of the pipeline to fetch.
|
|
116
|
+
"""
|
|
117
|
+
req = pipelinespb.GetPipelineRequest(id=id)
|
|
118
|
+
res: pipelinespb.GetPipelineResponse = get_default_client().GetPipeline(req)
|
|
119
|
+
return PipelineRecord.from_proto(res.pipeline)
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def create_pipeline_job(
|
|
123
|
+
pipeline_id: str, args: PipelineArgs, project_id: str, name: str, description: str | None = None
|
|
124
|
+
) -> PipelineJobRecord:
|
|
125
|
+
"""
|
|
126
|
+
Create a new pipeline job.
|
|
127
|
+
|
|
128
|
+
Parameters
|
|
129
|
+
----------
|
|
130
|
+
pipeline_id : str
|
|
131
|
+
ID of the pipeline to invoke.
|
|
132
|
+
args : PipelineArgs
|
|
133
|
+
Arguments to pass to the pipeline.
|
|
134
|
+
project_id : str
|
|
135
|
+
ID of the project to run the pipeline job in.
|
|
136
|
+
name : str
|
|
137
|
+
Name of the pipeline job.
|
|
138
|
+
description : str, optional
|
|
139
|
+
Description of the pipeline job.
|
|
140
|
+
"""
|
|
141
|
+
|
|
142
|
+
col_values = [[] for _ in args.params]
|
|
143
|
+
for row in args.rows:
|
|
144
|
+
for i, v in enumerate(row.row_values):
|
|
145
|
+
col_values[i].append(v)
|
|
146
|
+
|
|
147
|
+
cols = []
|
|
148
|
+
|
|
149
|
+
for i, param in enumerate(args.params):
|
|
150
|
+
if param._represented_type() == str:
|
|
151
|
+
cols.append(
|
|
152
|
+
pipelinespb.PipelineJobArgsColumn(
|
|
153
|
+
string_column=pipelinespb.PipelineJobArgsColumn.StringColumn(
|
|
154
|
+
name=param.name,
|
|
155
|
+
values=col_values[i],
|
|
156
|
+
)
|
|
157
|
+
)
|
|
158
|
+
)
|
|
159
|
+
elif param._represented_type() == int:
|
|
160
|
+
cols.append(
|
|
161
|
+
pipelinespb.PipelineJobArgsColumn(
|
|
162
|
+
int_column=pipelinespb.PipelineJobArgsColumn.IntColumn(
|
|
163
|
+
name=param.name,
|
|
164
|
+
values=col_values[i],
|
|
165
|
+
)
|
|
166
|
+
)
|
|
167
|
+
)
|
|
168
|
+
elif param._represented_type() == float:
|
|
169
|
+
cols.append(
|
|
170
|
+
pipelinespb.PipelineJobArgsColumn(
|
|
171
|
+
double_column=pipelinespb.PipelineJobArgsColumn.DoubleColumn(
|
|
172
|
+
name=param.name,
|
|
173
|
+
values=col_values[i],
|
|
174
|
+
)
|
|
175
|
+
)
|
|
176
|
+
)
|
|
177
|
+
elif param._represented_type() == bool:
|
|
178
|
+
cols.append(
|
|
179
|
+
pipelinespb.PipelineJobArgsColumn(
|
|
180
|
+
bool_column=pipelinespb.PipelineJobArgsColumn.BoolColumn(
|
|
181
|
+
name=param.name,
|
|
182
|
+
values=col_values[i],
|
|
183
|
+
)
|
|
184
|
+
)
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
req = pipelinespb.CreatePipelineJobRequest(
|
|
188
|
+
pipeline_id=pipeline_id,
|
|
189
|
+
args_columns=cols,
|
|
190
|
+
name=name,
|
|
191
|
+
description=description,
|
|
192
|
+
project_id=project_id,
|
|
193
|
+
)
|
|
194
|
+
res: pipelinespb.CreatePipelineJobResponse = get_default_client().CreatePipelineJob(req)
|
|
195
|
+
return PipelineJobRecord.from_proto(res.pipeline_job)
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def get_pipeline_job(id: str) -> PipelineJobRecord:
|
|
199
|
+
"""
|
|
200
|
+
Get a pipeline job by ID.
|
|
201
|
+
"""
|
|
202
|
+
req = pipelinespb.GetPipelineJobRequest(id=id)
|
|
203
|
+
res: pipelinespb.GetPipelineJobResponse = get_default_client().GetPipelineJob(req)
|
|
204
|
+
return PipelineJobRecord.from_proto(res.pipeline_job)
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
def list_pipeline_jobs() -> list[PipelineJobRecord]:
|
|
208
|
+
"""
|
|
209
|
+
List all pipeline jobs.
|
|
210
|
+
"""
|
|
211
|
+
req = pipelinespb.ListPipelineJobsRequest()
|
|
212
|
+
res: pipelinespb.ListPipelineJobsResponse = get_default_client().ListPipelineJobs(req)
|
|
213
|
+
return [PipelineJobRecord.from_proto(p) for p in res.pipeline_jobs]
|