Source code for flexcompute.flow_report.scene
"""Read-only cloud resource for reusable Flow360 visualization scenes."""
from __future__ import annotations
from typing import Any, Literal
import pydantic as pd
from . import models
from ._flow360_adapter import DEFAULT_FLOW360_ADAPTER, Flow360Adapter
class SceneVisualizationPayload(models.VisualizationViewSetup):
"""Versioned Workbench visualization setting stored by a Scene."""
schema_version: Literal[1]
def _as_report_setup(self) -> models.VisualizationViewSetup:
return models.VisualizationViewSetup.model_validate(
self.model_dump(exclude={"schema_version"})
)
class SceneViewpointPayload(models.ReportCameraParams):
"""Versioned camera stored by a Scene in canonical metres."""
schema_version: Literal[1]
def _as_report_camera(self) -> models.ReportCameraParams:
return models.ReportCameraParams.model_validate(self.model_dump(exclude={"schema_version"}))
class SceneVisualizationSetting(models.ReportBaseModel):
"""Visualization setting returned with a Scene."""
id: str = pd.Field(min_length=1)
project_id: str = pd.Field(min_length=1)
resource_type: models.ResourceType
resource_item_id: str = pd.Field(min_length=1)
payload: SceneVisualizationPayload
def _as_report_setup(self) -> models.VisualizationViewSetup:
return self.payload._as_report_setup()
class SceneViewpoint(models.ReportBaseModel):
"""Viewpoint returned with a Scene."""
id: str = pd.Field(min_length=1)
project_id: str = pd.Field(min_length=1)
payload: SceneViewpointPayload
def _as_report_camera(self) -> models.ReportCameraParams:
return self.payload._as_report_camera()
class _SceneInfo(models.ReportBaseModel):
"""Complete response returned by ``GET /v2/scenes/{sceneId}``."""
id: str = pd.Field(min_length=1)
project_id: str = pd.Field(min_length=1)
name: str = pd.Field(min_length=1)
resource_type: models.ResourceType
resource_item_id: str = pd.Field(min_length=1)
created_at: int
updated_at: int
created_by: str = pd.Field(min_length=1)
updated_by: str = pd.Field(min_length=1)
visualization_setting: SceneVisualizationSetting
viewpoint: SceneViewpoint
@pd.model_validator(mode="after")
def _validate_child_metadata(self):
setting = self.visualization_setting
if setting.project_id != self.project_id:
raise ValueError("scene visualization setting belongs to a different project")
if setting.resource_type != self.resource_type:
raise ValueError("scene visualization setting has a different resource type")
if setting.resource_item_id != self.resource_item_id:
raise ValueError("scene visualization setting belongs to a different resource item")
if self.viewpoint.project_id != self.project_id:
raise ValueError("scene viewpoint belongs to a different project")
return self
[docs]
class Scene:
"""A read-only visualization Scene loaded from the active Flow360 environment."""
_cloud_resource_type_name = "Scene"
_adapter = DEFAULT_FLOW360_ADAPTER
def __init__(
self,
*,
info: _SceneInfo,
environment: Any,
adapter: Flow360Adapter,
):
self._info = info
self._environment = environment
self._flow360_adapter = adapter
[docs]
@classmethod
def from_cloud(cls, scene_id: str) -> "Scene":
"""Load a Scene and its visualization setting and viewpoint.
Before applying ``visualization_setting`` to multiple resources, obtain each
resource's capabilities and call ``check_visualization_setup`` before creating
or updating the Report.
"""
if not isinstance(scene_id, str):
raise TypeError("scene_id must be a string")
normalized_scene_id = scene_id.strip()
if not normalized_scene_id:
raise ValueError("scene_id must not be empty")
adapter = cls._adapter
environment = adapter.current_environment()
response = adapter.get_scene(normalized_scene_id, environment=environment)
return cls(
info=_SceneInfo.model_validate(response),
environment=environment,
adapter=adapter,
)
@property
def id(self) -> str:
"""Cloud Scene ID."""
return self._info.id
@property
def project_id(self) -> str:
"""Project containing this Scene."""
return self._info.project_id
@property
def name(self) -> str:
"""Scene name."""
return self._info.name
@property
def resource_type(self) -> models.ResourceType:
"""Resource type from which the Scene setting was captured."""
return self._info.resource_type
@property
def resource_item_id(self) -> str:
"""Resource ID from which the Scene setting was captured."""
return self._info.resource_item_id
@property
def created_by(self) -> str:
"""User ID that created this Scene."""
return self._info.created_by
@property
def updated_by(self) -> str:
"""User ID that last updated this Scene."""
return self._info.updated_by
@property
def created_at(self) -> int:
"""Scene creation timestamp returned by the API."""
return self._info.created_at
@property
def updated_at(self) -> int:
"""Scene update timestamp returned by the API."""
return self._info.updated_at
@property
def visualization_setting(self) -> SceneVisualizationSetting:
"""A defensive copy of the Scene's Workbench visualization setting."""
return self._info.visualization_setting.model_copy(deep=True)
@property
def viewpoint(self) -> SceneViewpoint:
"""A defensive copy of the Scene's canonical-metre viewpoint."""
return self._info.viewpoint.model_copy(deep=True)
def __repr__(self) -> str:
return f"Scene(id={self.id!r}, name={self.name!r}, resource_type={self.resource_type!r})"