luminarycloud 0.15.3__py3-none-any.whl → 0.15.4__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/__init__.py +1 -0
- luminarycloud/_helpers/_create_simulation.py +2 -0
- luminarycloud/_helpers/_entity_identifier.py +6 -0
- luminarycloud/_helpers/named_variables.py +6 -15
- luminarycloud/_helpers/warnings/experimental.py +6 -2
- luminarycloud/_proto/api/v0/luminarycloud/geometry/geometry_pb2.py +77 -55
- luminarycloud/_proto/api/v0/luminarycloud/geometry/geometry_pb2.pyi +33 -0
- luminarycloud/_proto/api/v0/luminarycloud/geometry/geometry_pb2_grpc.py +33 -0
- luminarycloud/_proto/api/v0/luminarycloud/geometry/geometry_pb2_grpc.pyi +10 -0
- luminarycloud/_proto/api/v0/luminarycloud/physics_ai/physics_ai_pb2.py +45 -15
- luminarycloud/_proto/api/v0/luminarycloud/physics_ai/physics_ai_pb2.pyi +104 -22
- luminarycloud/_proto/api/v0/luminarycloud/simulation_template/simulation_template_pb2.py +12 -12
- luminarycloud/_proto/api/v0/luminarycloud/simulation_template/simulation_template_pb2.pyi +10 -2
- luminarycloud/_proto/api/v0/luminarycloud/vis/vis_pb2.py +221 -143
- luminarycloud/_proto/api/v0/luminarycloud/vis/vis_pb2.pyi +154 -7
- luminarycloud/_proto/api/v0/luminarycloud/vis/vis_pb2_grpc.py +33 -0
- luminarycloud/_proto/api/v0/luminarycloud/vis/vis_pb2_grpc.pyi +10 -0
- luminarycloud/_proto/assistant/assistant_pb2.py +82 -61
- luminarycloud/_proto/assistant/assistant_pb2.pyi +37 -0
- luminarycloud/_proto/assistant/assistant_pb2_grpc.py +34 -0
- luminarycloud/_proto/assistant/assistant_pb2_grpc.pyi +12 -0
- luminarycloud/_proto/client/simulation_pb2.py +349 -309
- luminarycloud/_proto/client/simulation_pb2.pyi +97 -2
- luminarycloud/_proto/fvm/solver_results_pb2.py +25 -11
- luminarycloud/_proto/fvm/solver_results_pb2.pyi +24 -1
- luminarycloud/_proto/geometry/geometry_pb2.py +64 -64
- luminarycloud/_proto/namedvariableset/namedvariableset_pb2.py +49 -0
- luminarycloud/_proto/namedvariableset/namedvariableset_pb2.pyi +53 -0
- luminarycloud/_wrapper.py +26 -7
- luminarycloud/enum/__init__.py +2 -0
- luminarycloud/enum/physics_ai_lifecycle_state.py +30 -0
- luminarycloud/enum/quantity_type.py +43 -0
- luminarycloud/enum/vis_enums.py +6 -2
- luminarycloud/geometry.py +46 -2
- luminarycloud/named_variable_set.py +10 -5
- luminarycloud/params/enum/_enum_wrappers.py +68 -0
- luminarycloud/params/simulation/_lib.py +1 -1
- luminarycloud/params/simulation/adaptive_mesh_refinement/boundary_layer_profile_.py +5 -6
- luminarycloud/params/simulation/adaptive_mesh_refinement_.py +6 -7
- luminarycloud/params/simulation/adjoint_.py +3 -4
- luminarycloud/params/simulation/basic/gravity/gravity_off_.py +3 -4
- luminarycloud/params/simulation/basic/gravity/gravity_on_.py +3 -4
- luminarycloud/params/simulation/basic/gravity_.py +3 -4
- luminarycloud/params/simulation/body_frame_.py +3 -4
- luminarycloud/params/simulation/entity_relationships/volume_material_relationship_.py +9 -6
- luminarycloud/params/simulation/entity_relationships/volume_physics_relationship_.py +9 -6
- luminarycloud/params/simulation/entity_relationships_.py +3 -4
- luminarycloud/params/simulation/general_.py +3 -4
- luminarycloud/params/simulation/material/fluid/boussinesq_approximation/boussinesq_off_.py +3 -4
- luminarycloud/params/simulation/material/fluid/boussinesq_approximation/boussinesq_on_.py +5 -6
- luminarycloud/params/simulation/material/fluid/boussinesq_approximation_.py +3 -4
- luminarycloud/params/simulation/material/fluid/material_model/ideal_gas_.py +5 -6
- luminarycloud/params/simulation/material/fluid/material_model/incompressible_fluid_.py +4 -5
- luminarycloud/params/simulation/material/fluid/material_model/incompressible_fluid_with_energy_.py +5 -6
- luminarycloud/params/simulation/material/fluid/material_model_.py +3 -4
- luminarycloud/params/simulation/material/fluid/thermal_conductivity_model/prescribed_conductivity_.py +4 -5
- luminarycloud/params/simulation/material/fluid/thermal_conductivity_model/prescribed_prandtl_number_.py +4 -5
- luminarycloud/params/simulation/material/fluid/thermal_conductivity_model/temperature_dependent_conductivity_.py +3 -4
- luminarycloud/params/simulation/material/fluid/thermal_conductivity_model_.py +3 -4
- luminarycloud/params/simulation/material/fluid/viscosity_model/prescribed_viscosity_.py +4 -5
- luminarycloud/params/simulation/material/fluid/viscosity_model/sutherland_.py +6 -7
- luminarycloud/params/simulation/material/fluid/viscosity_model/temperature_dependent_viscosity_.py +3 -4
- luminarycloud/params/simulation/material/fluid/viscosity_model_.py +3 -4
- luminarycloud/params/simulation/material/material_fluid_.py +4 -5
- luminarycloud/params/simulation/material/material_solid_.py +6 -7
- luminarycloud/params/simulation/material_entity_.py +6 -5
- luminarycloud/params/simulation/monitor_plane_.py +4 -5
- luminarycloud/params/simulation/motion_data/frame_transforms/no_transform_.py +3 -4
- luminarycloud/params/simulation/motion_data/frame_transforms/rotational_transform_.py +3 -4
- luminarycloud/params/simulation/motion_data/frame_transforms/translational_transform_.py +3 -4
- luminarycloud/params/simulation/motion_data/frame_transforms_.py +3 -4
- luminarycloud/params/simulation/motion_data/motion_type/constant_angular_motion_.py +3 -4
- luminarycloud/params/simulation/motion_data/motion_type/constant_translation_motion_.py +3 -4
- luminarycloud/params/simulation/motion_data/motion_type_.py +3 -4
- luminarycloud/params/simulation/motion_data_.py +3 -4
- luminarycloud/params/simulation/multi_physics_coupling_options_.py +3 -4
- luminarycloud/params/simulation/output_.py +3 -4
- luminarycloud/params/simulation/particle_group/particle_group_type/actuator_disk/actuator_disk_orientation_selection/actuator_disk_specify_normal_vector_.py +3 -4
- luminarycloud/params/simulation/particle_group/particle_group_type/actuator_disk/actuator_disk_orientation_selection/actuator_disk_specify_rotation_angles_.py +3 -4
- luminarycloud/params/simulation/particle_group/particle_group_type/actuator_disk/actuator_disk_orientation_selection_.py +3 -4
- luminarycloud/params/simulation/particle_group/particle_group_type/actuator_disk_.py +5 -6
- luminarycloud/params/simulation/particle_group/particle_group_type/actuator_line_.py +3 -4
- luminarycloud/params/simulation/particle_group/particle_group_type/probe_points_.py +3 -4
- luminarycloud/params/simulation/particle_group/particle_group_type/source_points_.py +3 -4
- luminarycloud/params/simulation/particle_group/particle_group_type_.py +3 -4
- luminarycloud/params/simulation/particle_group_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/adjoint_controls_fluid_.py +4 -5
- luminarycloud/params/simulation/physics/fluid/basic_fluid_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/boundary_conditions/farfield_.py +9 -10
- luminarycloud/params/simulation/physics/fluid/boundary_conditions/inlet/fan_curve_inlet_.py +5 -6
- luminarycloud/params/simulation/physics/fluid/boundary_conditions/inlet/mach_inlet_.py +5 -6
- luminarycloud/params/simulation/physics/fluid/boundary_conditions/inlet/mass_flow_inlet_.py +4 -5
- luminarycloud/params/simulation/physics/fluid/boundary_conditions/inlet/total_pressure_inlet_.py +4 -5
- luminarycloud/params/simulation/physics/fluid/boundary_conditions/inlet/velocity_components_inlet_.py +4 -5
- luminarycloud/params/simulation/physics/fluid/boundary_conditions/inlet/velocity_magnitude_inlet_.py +5 -6
- luminarycloud/params/simulation/physics/fluid/boundary_conditions/inlet_.py +4 -5
- luminarycloud/params/simulation/physics/fluid/boundary_conditions/outlet/outlet_strategy/fan_curve_outlet_.py +5 -6
- luminarycloud/params/simulation/physics/fluid/boundary_conditions/outlet/outlet_strategy/outlet_pressure_.py +4 -5
- luminarycloud/params/simulation/physics/fluid/boundary_conditions/outlet/outlet_strategy/outlet_target_corrected_mass_flow_rate_.py +7 -8
- luminarycloud/params/simulation/physics/fluid/boundary_conditions/outlet/outlet_strategy/outlet_target_mass_flow_rate_.py +5 -6
- luminarycloud/params/simulation/physics/fluid/boundary_conditions/outlet/outlet_strategy_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/boundary_conditions/outlet_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/boundary_conditions/symmetry_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/boundary_conditions/turbulence_boundary_conditions_.py +9 -10
- luminarycloud/params/simulation/physics/fluid/boundary_conditions/wall/energy/prescribed_heat_flux_.py +4 -5
- luminarycloud/params/simulation/physics/fluid/boundary_conditions/wall/energy/prescribed_temperature_.py +4 -5
- luminarycloud/params/simulation/physics/fluid/boundary_conditions/wall/momentum/no_slip_.py +4 -5
- luminarycloud/params/simulation/physics/fluid/boundary_conditions/wall/momentum/slip_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/boundary_conditions/wall/momentum/wall_model_.py +4 -5
- luminarycloud/params/simulation/physics/fluid/boundary_conditions/wall/wall_energy_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/boundary_conditions/wall/wall_momentum_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/boundary_conditions/wall_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/boundary_conditions_fluid_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/initialization/fluid_existing_solution_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/initialization/fluid_farfield_values_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/initialization/fluid_prescribed_values_.py +5 -6
- luminarycloud/params/simulation/physics/fluid/initialization/turbulence_initialization_.py +9 -10
- luminarycloud/params/simulation/physics/fluid/initialization_fluid_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/physical_behavior/blade_element_airfoil_data_.py +4 -5
- luminarycloud/params/simulation/physics/fluid/physical_behavior/physical_behavior_model/actuator_disk_model/actuator_disk_blade_element_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/physical_behavior/physical_behavior_model/actuator_disk_model/actuator_disk_radial_distribution_.py +6 -7
- luminarycloud/params/simulation/physics/fluid/physical_behavior/physical_behavior_model/actuator_disk_model/actuator_disk_uniform_thrust_.py +4 -5
- luminarycloud/params/simulation/physics/fluid/physical_behavior/physical_behavior_model/actuator_disk_model/fan_curve_internal_.py +4 -5
- luminarycloud/params/simulation/physics/fluid/physical_behavior/physical_behavior_model/actuator_disk_model_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/physical_behavior/physical_behavior_model/actuator_line_model/actuator_line_blade_element_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/physical_behavior/physical_behavior_model/actuator_line_model_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/physical_behavior/physical_behavior_model/blade_element_params_.py +5 -6
- luminarycloud/params/simulation/physics/fluid/physical_behavior/physical_behavior_model/particle_source_model/general_acceleration_source_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/physical_behavior/physical_behavior_model/particle_source_model/general_mass_source_.py +4 -5
- luminarycloud/params/simulation/physics/fluid/physical_behavior/physical_behavior_model/particle_source_model_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/physical_behavior/physical_behavior_model_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/physical_behavior_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/porous_behavior_.py +4 -5
- luminarycloud/params/simulation/physics/fluid/solution_controls/fluid_relaxation_method/fluid_explicit_relaxation_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/solution_controls/fluid_relaxation_method/fluid_implicit_relaxation/robust_startup/robust_startup_off_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/solution_controls/fluid_relaxation_method/fluid_implicit_relaxation/robust_startup/robust_startup_on_.py +4 -5
- luminarycloud/params/simulation/physics/fluid/solution_controls/fluid_relaxation_method/fluid_implicit_relaxation/robust_startup_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/solution_controls/fluid_relaxation_method/fluid_implicit_relaxation_.py +8 -9
- luminarycloud/params/simulation/physics/fluid/solution_controls/fluid_relaxation_method_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/solution_controls/pseudo_time_step_method/cfl_based_.py +4 -5
- luminarycloud/params/simulation/physics/fluid/solution_controls/pseudo_time_step_method/fixed_pseudo_time_step_.py +4 -5
- luminarycloud/params/simulation/physics/fluid/solution_controls/pseudo_time_step_method_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/solution_controls_fluid_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/spatial_discretization/convective_scheme/ec2_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/spatial_discretization/convective_scheme/fds_.py +5 -6
- luminarycloud/params/simulation/physics/fluid/spatial_discretization/convective_scheme/ld2_.py +5 -6
- luminarycloud/params/simulation/physics/fluid/spatial_discretization/convective_scheme/rhie_chow_.py +4 -5
- luminarycloud/params/simulation/physics/fluid/spatial_discretization/convective_scheme_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/spatial_discretization/convective_scheme_order/first_order_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/spatial_discretization/convective_scheme_order/second_order_.py +8 -9
- luminarycloud/params/simulation/physics/fluid/spatial_discretization/convective_scheme_order_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/spatial_discretization_fluid_.py +4 -5
- luminarycloud/params/simulation/physics/fluid/turbulence/des_formulation/ddes_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/turbulence/des_formulation/ddes_vtm_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/turbulence/des_formulation/iddes_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/turbulence/des_formulation_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/turbulence/komega_sst/constants/custom_komega_sst_constants_.py +16 -17
- luminarycloud/params/simulation/physics/fluid/turbulence/komega_sst/constants/default_komega_sst_constants_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/turbulence/komega_sst/komega_sst_constants_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/turbulence/komega_sst_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/turbulence/spalart_allmaras/constants/custom_spalart_allmaras_constants_.py +15 -16
- luminarycloud/params/simulation/physics/fluid/turbulence/spalart_allmaras/constants/default_spalart_allmaras_constants_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/turbulence/spalart_allmaras/spalart_allmaras_constants_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/turbulence/spalart_allmaras_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/turbulence/sub_grid_scale_model/amd_.py +4 -5
- luminarycloud/params/simulation/physics/fluid/turbulence/sub_grid_scale_model/sigma_.py +4 -5
- luminarycloud/params/simulation/physics/fluid/turbulence/sub_grid_scale_model/smagorinsky_.py +4 -5
- luminarycloud/params/simulation/physics/fluid/turbulence/sub_grid_scale_model/vreman_.py +4 -5
- luminarycloud/params/simulation/physics/fluid/turbulence/sub_grid_scale_model/wale_.py +4 -5
- luminarycloud/params/simulation/physics/fluid/turbulence/sub_grid_scale_model_.py +3 -4
- luminarycloud/params/simulation/physics/fluid/turbulence_.py +5 -6
- luminarycloud/params/simulation/physics/fluid_.py +7 -6
- luminarycloud/params/simulation/physics/heat/adjoint_controls_heat_.py +3 -4
- luminarycloud/params/simulation/physics/heat/boundary_conditions/heat_bc_convection_.py +5 -6
- luminarycloud/params/simulation/physics/heat/boundary_conditions/heat_bc_heat_flux_.py +4 -5
- luminarycloud/params/simulation/physics/heat/boundary_conditions/heat_bc_integrated_heat_flux_.py +4 -5
- luminarycloud/params/simulation/physics/heat/boundary_conditions/heat_bc_symmetry_.py +3 -4
- luminarycloud/params/simulation/physics/heat/boundary_conditions/heat_bc_temperature_.py +4 -5
- luminarycloud/params/simulation/physics/heat/boundary_conditions_heat_.py +3 -4
- luminarycloud/params/simulation/physics/heat/heat_source/heat_source_type/heat_source_type_power_.py +4 -5
- luminarycloud/params/simulation/physics/heat/heat_source/heat_source_type/heat_source_type_power_per_unit_of_volume_.py +4 -5
- luminarycloud/params/simulation/physics/heat/heat_source/heat_source_type_.py +3 -4
- luminarycloud/params/simulation/physics/heat/heat_source_.py +3 -4
- luminarycloud/params/simulation/physics/heat/initialization/heat_existing_solution_.py +3 -4
- luminarycloud/params/simulation/physics/heat/initialization/heat_prescribed_values_.py +4 -5
- luminarycloud/params/simulation/physics/heat/initialization_heat_.py +3 -4
- luminarycloud/params/simulation/physics/heat/solution_controls/heat_relaxation_method/heat_implicit_relaxation_.py +3 -4
- luminarycloud/params/simulation/physics/heat/solution_controls/heat_relaxation_method_.py +3 -4
- luminarycloud/params/simulation/physics/heat/solution_controls_heat_.py +3 -4
- luminarycloud/params/simulation/physics/heat/spatial_discretization_heat_.py +5 -6
- luminarycloud/params/simulation/physics/heat_.py +5 -5
- luminarycloud/params/simulation/physics/periodic_pair/periodicity_type/rotational_periodicity_.py +3 -4
- luminarycloud/params/simulation/physics/periodic_pair/periodicity_type/translational_periodicity_.py +3 -4
- luminarycloud/params/simulation/physics/periodic_pair/periodicity_type_.py +3 -4
- luminarycloud/params/simulation/physics/periodic_pair_.py +3 -4
- luminarycloud/params/simulation/physics/solution_controls/linear_solver_type/gauss_seidel_.py +3 -4
- luminarycloud/params/simulation/physics/solution_controls/linear_solver_type/krylov_amg_.py +4 -5
- luminarycloud/params/simulation/physics/solution_controls/linear_solver_type_.py +4 -5
- luminarycloud/params/simulation/physics_.py +6 -5
- luminarycloud/params/simulation/simulation_param_.py +3 -4
- luminarycloud/params/simulation/sliding_interfaces_.py +3 -4
- luminarycloud/params/simulation/surface_name_.py +3 -4
- luminarycloud/params/simulation/time/compute_statistics/compute_statistics_off_.py +3 -4
- luminarycloud/params/simulation/time/compute_statistics/compute_statistics_on_.py +3 -4
- luminarycloud/params/simulation/time/compute_statistics_.py +3 -4
- luminarycloud/params/simulation/time/time_marching/time_explicit_.py +3 -4
- luminarycloud/params/simulation/time/time_marching/time_implicit_.py +3 -4
- luminarycloud/params/simulation/time/time_marching_.py +3 -4
- luminarycloud/params/simulation/time/time_step_ramp/time_step_ramp_off_.py +3 -4
- luminarycloud/params/simulation/time/time_step_ramp/time_step_ramp_on_.py +4 -5
- luminarycloud/params/simulation/time/time_step_ramp_.py +3 -4
- luminarycloud/params/simulation/time_.py +4 -5
- luminarycloud/params/simulation/volume_entity_.py +6 -5
- luminarycloud/physics_ai/__init__.py +2 -0
- luminarycloud/physics_ai/architectures.py +42 -8
- luminarycloud/physics_ai/inference.py +0 -2
- luminarycloud/physics_ai/models.py +44 -15
- luminarycloud/project.py +54 -3
- luminarycloud/simulation_template.py +21 -6
- luminarycloud/solution.py +1 -1
- luminarycloud/types/__init__.py +2 -0
- luminarycloud/types/adfloat.py +50 -8
- luminarycloud/types/ids.py +2 -0
- luminarycloud/vis/__init__.py +12 -2
- luminarycloud/vis/data_extraction.py +546 -0
- luminarycloud/vis/display.py +61 -6
- luminarycloud/vis/filters.py +183 -42
- luminarycloud/vis/interactive_scene.py +1 -0
- luminarycloud/vis/primitives.py +38 -0
- luminarycloud/vis/vis_util.py +56 -0
- luminarycloud/vis/visualization.py +224 -70
- {luminarycloud-0.15.3.dist-info → luminarycloud-0.15.4.dist-info}/METADATA +2 -1
- {luminarycloud-0.15.3.dist-info → luminarycloud-0.15.4.dist-info}/RECORD +234 -228
- luminarycloud/_proto/luminarycloud/luminarycloud_api.pb +0 -0
- {luminarycloud-0.15.3.dist-info → luminarycloud-0.15.4.dist-info}/WHEEL +0 -0
luminarycloud/vis/filters.py
CHANGED
|
@@ -1,51 +1,20 @@
|
|
|
1
1
|
from luminarycloud.types import Vector3, Vector3Like
|
|
2
2
|
from ..types.vector3 import _to_vector3
|
|
3
|
-
from luminarycloud.enum import
|
|
3
|
+
from luminarycloud.enum import (
|
|
4
|
+
VisQuantity,
|
|
5
|
+
StreamlineDirection,
|
|
6
|
+
SurfaceStreamlineMode,
|
|
7
|
+
FieldComponent,
|
|
8
|
+
)
|
|
9
|
+
import luminarycloud.enum.quantity_type as quantity_type
|
|
4
10
|
from .._proto.api.v0.luminarycloud.vis import vis_pb2
|
|
5
11
|
from abc import ABC, abstractmethod
|
|
6
|
-
import
|
|
12
|
+
import math
|
|
7
13
|
import dataclasses as dc
|
|
8
14
|
from .display import Field, DisplayAttributes
|
|
9
15
|
from typing import List, Any, cast
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def generate_id(prefix: str) -> str:
|
|
13
|
-
return prefix + "".join(random.choices(string.ascii_lowercase, k=24))
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
@dc.dataclass
|
|
17
|
-
class Plane:
|
|
18
|
-
"""
|
|
19
|
-
This class defines a plane.
|
|
20
|
-
|
|
21
|
-
.. warning:: This feature is experimental and may change or be removed in the future.
|
|
22
|
-
|
|
23
|
-
"""
|
|
24
|
-
|
|
25
|
-
origin: Vector3Like = dc.field(default_factory=lambda: Vector3(x=0, y=0, z=0))
|
|
26
|
-
"""A point defined on the plane. Default: [0,0,0]."""
|
|
27
|
-
normal: Vector3Like = dc.field(default_factory=lambda: Vector3(x=1, y=0, z=0))
|
|
28
|
-
"""The vector orthogonal to the plane. Default: [0,1,0]"""
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
@dc.dataclass
|
|
32
|
-
class Box:
|
|
33
|
-
"""
|
|
34
|
-
This class defines a box used for filter such as box clip.
|
|
35
|
-
|
|
36
|
-
.. warning:: This feature is experimental and may change or be removed in the future.
|
|
37
|
-
|
|
38
|
-
"""
|
|
39
|
-
|
|
40
|
-
center: Vector3Like = dc.field(default_factory=lambda: Vector3(x=0, y=0, z=0))
|
|
41
|
-
"""A point defined at the center of the box. Default: [0,0,0]."""
|
|
42
|
-
lengths: Vector3Like = dc.field(default_factory=lambda: Vector3(x=1, y=1, z=1))
|
|
43
|
-
"""The the legnths of each side of the box. Default: [1,1,1]"""
|
|
44
|
-
angles: Vector3Like = dc.field(default_factory=lambda: Vector3(x=0, y=0, z=0))
|
|
45
|
-
"""
|
|
46
|
-
The rotation of the box specified in Euler angles (degrees) and applied
|
|
47
|
-
in XYZ ordering. Default: [0,0,0]
|
|
48
|
-
"""
|
|
16
|
+
from .primitives import Box, Plane
|
|
17
|
+
from .vis_util import generate_id
|
|
49
18
|
|
|
50
19
|
|
|
51
20
|
class Filter(ABC):
|
|
@@ -71,6 +40,10 @@ class Filter(ABC):
|
|
|
71
40
|
def _to_proto(self) -> vis_pb2.Filter:
|
|
72
41
|
pass
|
|
73
42
|
|
|
43
|
+
@abstractmethod
|
|
44
|
+
def _from_proto(self, filter: vis_pb2.Filter) -> None:
|
|
45
|
+
pass
|
|
46
|
+
|
|
74
47
|
def set_parent(self, filter: Any) -> None:
|
|
75
48
|
"""
|
|
76
49
|
Set this filter's parent filter. This controls what data the filter uses
|
|
@@ -157,6 +130,20 @@ class Slice(Filter):
|
|
|
157
130
|
vis_filter.slice.project_vectors = self.project_vectors
|
|
158
131
|
return vis_filter
|
|
159
132
|
|
|
133
|
+
def _from_proto(self, filter: vis_pb2.Filter) -> None:
|
|
134
|
+
typ = filter.WhichOneof("value")
|
|
135
|
+
if typ != "slice":
|
|
136
|
+
raise TypeError(f"Expected 'slice', got {typ}")
|
|
137
|
+
self.id = filter.id
|
|
138
|
+
self.name = filter.name
|
|
139
|
+
self.project_vectors = filter.slice.project_vectors
|
|
140
|
+
origin = Vector3()
|
|
141
|
+
origin._from_proto(filter.slice.plane.origin)
|
|
142
|
+
self.plane.origin = origin
|
|
143
|
+
normal = Vector3()
|
|
144
|
+
normal._from_proto(filter.slice.plane.normal)
|
|
145
|
+
self.plane.normal = normal
|
|
146
|
+
|
|
160
147
|
|
|
161
148
|
class Isosurface(Filter):
|
|
162
149
|
"""
|
|
@@ -206,6 +193,18 @@ class Isosurface(Filter):
|
|
|
206
193
|
vis_filter.contour.iso_values.append(val)
|
|
207
194
|
return vis_filter
|
|
208
195
|
|
|
196
|
+
def _from_proto(self, filter: vis_pb2.Filter) -> None:
|
|
197
|
+
typ = filter.WhichOneof("value")
|
|
198
|
+
if typ != "contour":
|
|
199
|
+
raise TypeError(f"Expected 'contour', got {typ}")
|
|
200
|
+
self.id = filter.id
|
|
201
|
+
self.name = filter.name
|
|
202
|
+
self.field.quantity = VisQuantity(filter.contour.field.quantity_typ)
|
|
203
|
+
self.field.component = FieldComponent(filter.contour.field.component)
|
|
204
|
+
self.isovalues.clear()
|
|
205
|
+
for val in filter.contour.iso_values:
|
|
206
|
+
self.isovalues.append(val)
|
|
207
|
+
|
|
209
208
|
|
|
210
209
|
class PlaneClip(Filter):
|
|
211
210
|
"""
|
|
@@ -254,6 +253,21 @@ class PlaneClip(Filter):
|
|
|
254
253
|
vis_filter.clip.inverted = self.inverted
|
|
255
254
|
return vis_filter
|
|
256
255
|
|
|
256
|
+
def _from_proto(self, filter: vis_pb2.Filter) -> None:
|
|
257
|
+
typ = filter.WhichOneof("value")
|
|
258
|
+
if typ != "clip":
|
|
259
|
+
raise TypeError(f"Expected 'clip', got {typ}")
|
|
260
|
+
clip_typ = filter.clip.WhichOneof("clip_function")
|
|
261
|
+
if clip_typ != "plane":
|
|
262
|
+
raise TypeError(f"Expected 'plane clip', got {clip_typ}")
|
|
263
|
+
self.id = filter.id
|
|
264
|
+
self.name = filter.name
|
|
265
|
+
self.plane.normal = Vector3()
|
|
266
|
+
self.plane.normal._from_proto(filter.clip.plane.normal)
|
|
267
|
+
self.plane.origin = Vector3()
|
|
268
|
+
self.plane.origin._from_proto(filter.clip.plane.origin)
|
|
269
|
+
self.inverted = filter.clip.inverted
|
|
270
|
+
|
|
257
271
|
|
|
258
272
|
class BoxClip(Filter):
|
|
259
273
|
"""
|
|
@@ -306,6 +320,27 @@ class BoxClip(Filter):
|
|
|
306
320
|
vis_filter.clip.inverted = self.inverted
|
|
307
321
|
return vis_filter
|
|
308
322
|
|
|
323
|
+
def _from_proto(self, filter: vis_pb2.Filter) -> None:
|
|
324
|
+
typ = filter.WhichOneof("value")
|
|
325
|
+
if typ != "clip":
|
|
326
|
+
raise TypeError(f"Expected 'clip', got {typ}")
|
|
327
|
+
clip_typ = filter.clip.WhichOneof("clip_function")
|
|
328
|
+
if clip_typ != "box":
|
|
329
|
+
raise TypeError(f"Expected 'box', got {clip_typ}")
|
|
330
|
+
self.id = filter.id
|
|
331
|
+
self.name = filter.name
|
|
332
|
+
self.box.center = Vector3()
|
|
333
|
+
self.box.center._from_proto(filter.clip.box.center)
|
|
334
|
+
self.box.lengths = Vector3()
|
|
335
|
+
self.box.lengths._from_proto(filter.clip.box.lengths)
|
|
336
|
+
self.box.angles = Vector3()
|
|
337
|
+
self.box.angles._from_proto(filter.clip.box.angles)
|
|
338
|
+
# Backend units are radians, convert back to degrees
|
|
339
|
+
self.box.angles.x = self.box.angles.x * (180 / math.pi)
|
|
340
|
+
self.box.angles.y = self.box.angles.y * (180 / math.pi)
|
|
341
|
+
self.box.angles.z = self.box.angles.z * (180 / math.pi)
|
|
342
|
+
self.inverted = filter.clip.inverted
|
|
343
|
+
|
|
309
344
|
|
|
310
345
|
class VectorGlyphs(Filter):
|
|
311
346
|
"""
|
|
@@ -376,10 +411,27 @@ class FixedSizeVectorGlyphs(VectorGlyphs):
|
|
|
376
411
|
vis_filter.glyph.fixed_size_glyphs = self.size
|
|
377
412
|
vis_filter.glyph.n_glyphs = self.sampling_rate
|
|
378
413
|
vis_filter.glyph.sampling_mode = vis_pb2.GLYPH_SAMPLING_MODE_EVERY_NTH
|
|
414
|
+
if not quantity_type._is_vector(self.field.quantity):
|
|
415
|
+
raise ValueError("FixedSizeVectorGlyphs: field must be a vector type")
|
|
379
416
|
vis_filter.glyph.field.quantity_typ = self.field.quantity.value
|
|
380
417
|
vis_filter.glyph.field.component = self.field.component.value
|
|
381
418
|
return vis_filter
|
|
382
419
|
|
|
420
|
+
def _from_proto(self, filter: vis_pb2.Filter) -> None:
|
|
421
|
+
typ = filter.WhichOneof("value")
|
|
422
|
+
if typ != "glyph":
|
|
423
|
+
raise TypeError(f"Expected 'glyph', got {typ}")
|
|
424
|
+
glyph_typ = filter.glyph.WhichOneof("glyph_size")
|
|
425
|
+
if glyph_typ != "fixed_size_glyphs":
|
|
426
|
+
raise TypeError(f"Expected 'fixed size', got {typ}")
|
|
427
|
+
self.id = filter.id
|
|
428
|
+
self.name = filter.name
|
|
429
|
+
self.n_glyphs = filter.glyph.n_glyphs
|
|
430
|
+
self.size = filter.glyph.fixed_size_glyphs
|
|
431
|
+
self.sampling_rate = filter.glyph.n_glyphs
|
|
432
|
+
self.field.quantity = VisQuantity(filter.glyph.field.quantity_typ)
|
|
433
|
+
self.field.component = FieldComponent(filter.glyph.field.component)
|
|
434
|
+
|
|
383
435
|
|
|
384
436
|
class ScaledVectorGlyphs(VectorGlyphs):
|
|
385
437
|
"""
|
|
@@ -420,10 +472,27 @@ class ScaledVectorGlyphs(VectorGlyphs):
|
|
|
420
472
|
vis_filter.glyph.glyph_scale_size = self.scale
|
|
421
473
|
vis_filter.glyph.n_glyphs = self.sampling_rate
|
|
422
474
|
vis_filter.glyph.sampling_mode = vis_pb2.GLYPH_SAMPLING_MODE_EVERY_NTH
|
|
475
|
+
if not quantity_type._is_vector(self.field.quantity):
|
|
476
|
+
raise ValueError("ScaledVectorGyph: field must be a vector type")
|
|
423
477
|
vis_filter.glyph.field.quantity_typ = self.field.quantity.value
|
|
424
478
|
vis_filter.glyph.field.component = self.field.component.value
|
|
425
479
|
return vis_filter
|
|
426
480
|
|
|
481
|
+
def _from_proto(self, filter: vis_pb2.Filter) -> None:
|
|
482
|
+
typ = filter.WhichOneof("value")
|
|
483
|
+
if typ != "glyph":
|
|
484
|
+
raise TypeError(f"Expected 'glyph', got {typ}")
|
|
485
|
+
glyph_typ = filter.glyph.WhichOneof("glyph_size")
|
|
486
|
+
if glyph_typ != "glyph_scale_size":
|
|
487
|
+
raise TypeError(f"Expected 'scaled size', got {typ}")
|
|
488
|
+
self.id = filter.id
|
|
489
|
+
self.name = filter.name
|
|
490
|
+
self.n_glyphs = filter.glyph.n_glyphs
|
|
491
|
+
self.scale = filter.glyph.glyph_scale_size
|
|
492
|
+
self.sampling_rate = filter.glyph.n_glyphs
|
|
493
|
+
self.field.quantity = VisQuantity(filter.glyph.field.quantity_typ)
|
|
494
|
+
self.field.component = FieldComponent(filter.glyph.field.component)
|
|
495
|
+
|
|
427
496
|
|
|
428
497
|
class Threshold(Filter):
|
|
429
498
|
"""
|
|
@@ -496,6 +565,20 @@ class Threshold(Filter):
|
|
|
496
565
|
vis_filter.threshold.strict = self.strict
|
|
497
566
|
return vis_filter
|
|
498
567
|
|
|
568
|
+
def _from_proto(self, filter: vis_pb2.Filter) -> None:
|
|
569
|
+
typ = filter.WhichOneof("value")
|
|
570
|
+
if typ != "threshold":
|
|
571
|
+
raise TypeError(f"Expected 'threshold', got {typ}")
|
|
572
|
+
self.id = filter.id
|
|
573
|
+
self.name = filter.name
|
|
574
|
+
self.min_value = filter.threshold.range.min
|
|
575
|
+
self.max_value = filter.threshold.range.max
|
|
576
|
+
self.smooth = filter.threshold.smooth
|
|
577
|
+
self.invert = filter.threshold.invert
|
|
578
|
+
self.strict = filter.threshold.strict
|
|
579
|
+
self.field.quantity = VisQuantity(filter.threshold.field.quantity_typ)
|
|
580
|
+
self.field.component = FieldComponent(filter.threshold.field.component)
|
|
581
|
+
|
|
499
582
|
|
|
500
583
|
class Streamlines(Filter):
|
|
501
584
|
"""
|
|
@@ -575,9 +658,29 @@ class RakeStreamlines(Streamlines):
|
|
|
575
658
|
vis_filter.streamlines.max_length = self.max_length
|
|
576
659
|
vis_filter.streamlines.rake.start.CopyFrom(_to_vector3(self.start)._to_proto())
|
|
577
660
|
vis_filter.streamlines.rake.end.CopyFrom(_to_vector3(self.end)._to_proto())
|
|
661
|
+
if not quantity_type._is_vector(self.field.quantity):
|
|
662
|
+
raise ValueError("RakeStreamlines: field must be a vector type")
|
|
578
663
|
vis_filter.streamlines.field.quantity_typ = self.field.quantity.value
|
|
579
664
|
return vis_filter
|
|
580
665
|
|
|
666
|
+
def _from_proto(self, filter: vis_pb2.Filter) -> None:
|
|
667
|
+
typ = filter.WhichOneof("value")
|
|
668
|
+
if typ != "streamlines":
|
|
669
|
+
raise TypeError(f"Expected 'streamlines', got {typ}")
|
|
670
|
+
s_typ = filter.streamlines.WhichOneof("seed_type")
|
|
671
|
+
if s_typ != "rake":
|
|
672
|
+
raise TypeError(f"Expected 'rake streamlines', got {s_typ}")
|
|
673
|
+
self.id = filter.id
|
|
674
|
+
self.name = filter.name
|
|
675
|
+
self.n_streamlines = filter.streamlines.n_streamlines
|
|
676
|
+
self.max_length = filter.streamlines.max_length
|
|
677
|
+
|
|
678
|
+
self.start = Vector3()
|
|
679
|
+
self.start._from_proto(filter.streamlines.rake.start)
|
|
680
|
+
self.end = Vector3()
|
|
681
|
+
self.end._from_proto(filter.streamlines.rake.end)
|
|
682
|
+
self.field.quantity = VisQuantity(filter.streamlines.field.quantity_typ)
|
|
683
|
+
|
|
581
684
|
|
|
582
685
|
class SurfaceStreamlines(Streamlines):
|
|
583
686
|
"""
|
|
@@ -693,9 +796,28 @@ class SurfaceStreamlines(Streamlines):
|
|
|
693
796
|
raise ValueError("SurfaceStreamlines: need at least one surfaces specified.")
|
|
694
797
|
for id in self._surface_names:
|
|
695
798
|
vis_filter.streamlines.surface.surface_names.append(id)
|
|
799
|
+
if not quantity_type._is_vector(self.field.quantity):
|
|
800
|
+
raise ValueError("SurfaceStreamlines: field must be a vector type")
|
|
801
|
+
vis_filter.streamlines.field.component = self.field.component.value
|
|
696
802
|
vis_filter.streamlines.field.quantity_typ = self.field.quantity.value
|
|
697
803
|
return vis_filter
|
|
698
804
|
|
|
805
|
+
def _from_proto(self, filter: vis_pb2.Filter) -> None:
|
|
806
|
+
typ = filter.WhichOneof("value")
|
|
807
|
+
if typ != "streamlines":
|
|
808
|
+
raise TypeError(f"Expected 'streamlines', got {typ}")
|
|
809
|
+
s_typ = filter.streamlines.WhichOneof("seed_type")
|
|
810
|
+
if s_typ != "surface":
|
|
811
|
+
raise TypeError(f"Expected 'surface streamlines', got {s_typ}")
|
|
812
|
+
self.id = filter.id
|
|
813
|
+
self.name = filter.name
|
|
814
|
+
self.max_length = filter.streamlines.max_length
|
|
815
|
+
self.offset = filter.streamlines.surface.offset
|
|
816
|
+
self._surface_names.clear()
|
|
817
|
+
for s in filter.streamlines.surface.surface_names:
|
|
818
|
+
self._surface_names.append(s)
|
|
819
|
+
self.field.quantity = VisQuantity(filter.streamlines.field.quantity_typ)
|
|
820
|
+
|
|
699
821
|
|
|
700
822
|
class SurfaceLIC(Filter):
|
|
701
823
|
"""
|
|
@@ -737,7 +859,7 @@ class SurfaceLIC(Filter):
|
|
|
737
859
|
|
|
738
860
|
def add_surface(self, id: str) -> None:
|
|
739
861
|
"""
|
|
740
|
-
Add a surface to
|
|
862
|
+
Add a surface to compute the surface LIC on. Adding no
|
|
741
863
|
surfaces indicates that all surfaces will be used.
|
|
742
864
|
|
|
743
865
|
Parameters
|
|
@@ -780,3 +902,22 @@ class SurfaceLIC(Filter):
|
|
|
780
902
|
vis_filter.surface_lic.field.quantity_typ = self.field.quantity.value
|
|
781
903
|
vis_filter.surface_lic.contrast = self.contrast
|
|
782
904
|
return vis_filter
|
|
905
|
+
|
|
906
|
+
def _from_proto(self, filter: vis_pb2.Filter) -> None:
|
|
907
|
+
typ = filter.WhichOneof("value")
|
|
908
|
+
if typ != "surface_lic":
|
|
909
|
+
raise TypeError(f"Expected 'surface lic', got {typ}")
|
|
910
|
+
l_typ = filter.surface_lic.WhichOneof("lic_type")
|
|
911
|
+
if l_typ != "geometry":
|
|
912
|
+
# there is only one type of surface lic currently.
|
|
913
|
+
raise TypeError(f"Expected geometry', got {l_typ}")
|
|
914
|
+
self.id = filter.id
|
|
915
|
+
self.name = filter.name
|
|
916
|
+
self.contrast = filter.surface_lic.contrast
|
|
917
|
+
self._surface_names = []
|
|
918
|
+
for s in filter.surface_lic.geometry.surface_names:
|
|
919
|
+
self._surface_names.append(s)
|
|
920
|
+
if not quantity_type._is_vector(self.field.quantity):
|
|
921
|
+
raise ValueError("SurfaceLIC: field must be a vector type")
|
|
922
|
+
self.field.quantity = VisQuantity(filter.surface_lic.field.quantity_typ)
|
|
923
|
+
self.field.component = FieldComponent(filter.surface_lic.field.component)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Copyright 2023-2024 Luminary Cloud, Inc. All Rights Reserved.
|
|
2
|
+
import dataclasses as dc
|
|
3
|
+
from luminarycloud.types import Vector3, Vector3Like
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@dc.dataclass
|
|
7
|
+
class Plane:
|
|
8
|
+
"""
|
|
9
|
+
This class defines a plane.
|
|
10
|
+
|
|
11
|
+
.. warning:: This feature is experimental and may change or be removed in the future.
|
|
12
|
+
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
origin: Vector3Like = dc.field(default_factory=lambda: Vector3(x=0, y=0, z=0))
|
|
16
|
+
"""A point defined on the plane. Default: [0,0,0]."""
|
|
17
|
+
normal: Vector3Like = dc.field(default_factory=lambda: Vector3(x=1, y=0, z=0))
|
|
18
|
+
"""The vector orthogonal to the plane. Default: [0,1,0]"""
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dc.dataclass
|
|
22
|
+
class Box:
|
|
23
|
+
"""
|
|
24
|
+
This class defines a box used for filter such as box clip.
|
|
25
|
+
|
|
26
|
+
.. warning:: This feature is experimental and may change or be removed in the future.
|
|
27
|
+
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
center: Vector3Like = dc.field(default_factory=lambda: Vector3(x=0, y=0, z=0))
|
|
31
|
+
"""A point defined at the center of the box. Default: [0,0,0]."""
|
|
32
|
+
lengths: Vector3Like = dc.field(default_factory=lambda: Vector3(x=1, y=1, z=1))
|
|
33
|
+
"""The the legnths of each side of the box. Default: [1,1,1]"""
|
|
34
|
+
angles: Vector3Like = dc.field(default_factory=lambda: Vector3(x=0, y=0, z=0))
|
|
35
|
+
"""
|
|
36
|
+
The rotation of the box specified in Euler angles (degrees) and applied
|
|
37
|
+
in XYZ ordering. Default: [0,0,0]
|
|
38
|
+
"""
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Copyright 2023-2024 Luminary Cloud, Inc. All Rights Reserved.
|
|
2
|
+
import io
|
|
3
|
+
import requests
|
|
4
|
+
import string, random
|
|
5
|
+
import luminarycloud._proto.api.v0.luminarycloud.common.common_pb2 as common_pb2
|
|
6
|
+
from ..enum.vis_enums import RenderStatusType, VisQuantity
|
|
7
|
+
from .._proto.api.v0.luminarycloud.vis import vis_pb2
|
|
8
|
+
from .._client import get_default_client
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def generate_id(prefix: str) -> str:
|
|
12
|
+
return prefix + "".join(random.choices(string.ascii_lowercase, k=24))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class _InternalToken:
|
|
16
|
+
"""Marker class to control instantiation access for vis outputs."""
|
|
17
|
+
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _download_file(file: common_pb2.File) -> "io.BytesIO":
|
|
22
|
+
buffer = io.BytesIO()
|
|
23
|
+
if file.signed_url:
|
|
24
|
+
response = requests.get(file.signed_url, stream=True)
|
|
25
|
+
response.raise_for_status()
|
|
26
|
+
for chunk in response.iter_content(chunk_size=8192):
|
|
27
|
+
buffer.write(chunk)
|
|
28
|
+
elif file.full_contents:
|
|
29
|
+
buffer.write(file.full_contents)
|
|
30
|
+
else:
|
|
31
|
+
raise Exception("file respose contains no data.")
|
|
32
|
+
# Reset buffer position to the beginning for reading
|
|
33
|
+
buffer.seek(0)
|
|
34
|
+
return buffer
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _get_status(project_id: str, extract_id: str) -> RenderStatusType:
|
|
38
|
+
"""
|
|
39
|
+
Get a previously created set of render outputs by project and extract id. This
|
|
40
|
+
can be used by both extracts and images since the status type is just an alias.
|
|
41
|
+
|
|
42
|
+
.. warning:: This feature is experimental and may change or be removed in the future.
|
|
43
|
+
|
|
44
|
+
Parameters
|
|
45
|
+
----------
|
|
46
|
+
project_id : str
|
|
47
|
+
The project id to of the extract.
|
|
48
|
+
extract_id: str
|
|
49
|
+
The id to of the extract.
|
|
50
|
+
|
|
51
|
+
"""
|
|
52
|
+
req = vis_pb2.GetExtractRequest()
|
|
53
|
+
req.extract_id = extract_id
|
|
54
|
+
req.project_id = project_id
|
|
55
|
+
res: vis_pb2.GetExtractResponse = get_default_client().GetExtract(req)
|
|
56
|
+
return RenderStatusType(res.extract.status)
|