luminarycloud 0.15.5__py3-none-any.whl → 0.16.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 (52) hide show
  1. luminarycloud/_helpers/__init__.py +1 -0
  2. luminarycloud/_helpers/_code_representation.py +18 -3
  3. luminarycloud/_helpers/download.py +67 -1
  4. luminarycloud/_proto/api/v0/luminarycloud/inference/inference_pb2.py +9 -9
  5. luminarycloud/_proto/api/v0/luminarycloud/inference/inference_pb2.pyi +7 -4
  6. luminarycloud/_proto/api/v0/luminarycloud/physics_ai/physics_ai_pb2.py +45 -21
  7. luminarycloud/_proto/api/v0/luminarycloud/physics_ai/physics_ai_pb2.pyi +65 -0
  8. luminarycloud/_proto/api/v0/luminarycloud/physics_ai/physics_ai_pb2_grpc.py +34 -0
  9. luminarycloud/_proto/api/v0/luminarycloud/physics_ai/physics_ai_pb2_grpc.pyi +12 -0
  10. luminarycloud/_proto/api/v0/luminarycloud/thirdpartyintegration/onshape/onshape_pb2.py +194 -7
  11. luminarycloud/_proto/api/v0/luminarycloud/thirdpartyintegration/onshape/onshape_pb2.pyi +403 -1
  12. luminarycloud/_proto/api/v0/luminarycloud/thirdpartyintegration/onshape/onshape_pb2_grpc.py +171 -0
  13. luminarycloud/_proto/api/v0/luminarycloud/thirdpartyintegration/onshape/onshape_pb2_grpc.pyi +64 -0
  14. luminarycloud/_proto/api/v0/luminarycloud/upload/upload_pb2.py +4 -2
  15. luminarycloud/_proto/api/v0/luminarycloud/upload/upload_pb2_grpc.py +34 -0
  16. luminarycloud/_proto/api/v0/luminarycloud/upload/upload_pb2_grpc.pyi +12 -0
  17. luminarycloud/_proto/assistant/assistant_pb2.py +82 -61
  18. luminarycloud/_proto/assistant/assistant_pb2.pyi +40 -0
  19. luminarycloud/_proto/assistant/assistant_pb2_grpc.py +34 -0
  20. luminarycloud/_proto/assistant/assistant_pb2_grpc.pyi +12 -0
  21. luminarycloud/_proto/base/base_pb2.py +7 -6
  22. luminarycloud/_proto/base/base_pb2.pyi +4 -0
  23. luminarycloud/_proto/client/simulation_pb2.py +188 -186
  24. luminarycloud/_proto/client/simulation_pb2.pyi +10 -2
  25. luminarycloud/_proto/geometry/geometry_pb2.py +62 -62
  26. luminarycloud/_proto/geometry/geometry_pb2.pyi +5 -1
  27. luminarycloud/_proto/inferenceservice/inferenceservice_pb2.py +11 -11
  28. luminarycloud/_proto/inferenceservice/inferenceservice_pb2.pyi +12 -4
  29. luminarycloud/_proto/quantity/quantity_pb2.py +11 -2
  30. luminarycloud/_proto/quantity/quantity_pb2.pyi +6 -0
  31. luminarycloud/_proto/table/table_pb2.pyi +4 -2
  32. luminarycloud/_proto/upload/upload_pb2.py +27 -7
  33. luminarycloud/_proto/upload/upload_pb2.pyi +31 -0
  34. luminarycloud/enum/quantity_type.py +15 -0
  35. luminarycloud/mesh.py +8 -1
  36. luminarycloud/params/simulation/physics/fluid/solution_controls/fluid_relaxation_method/fluid_implicit_relaxation/robust_startup/__init__.py +1 -0
  37. luminarycloud/params/simulation/physics/fluid/solution_controls/fluid_relaxation_method/fluid_implicit_relaxation/robust_startup/robust_startup_auto_.py +30 -0
  38. luminarycloud/params/simulation/physics/fluid/solution_controls/fluid_relaxation_method/fluid_implicit_relaxation/robust_startup/robust_startup_on_.py +1 -1
  39. luminarycloud/params/simulation/physics/fluid/solution_controls/fluid_relaxation_method/fluid_implicit_relaxation_.py +6 -2
  40. luminarycloud/params/simulation/physics/fluid/solution_controls_fluid_.py +4 -0
  41. luminarycloud/physics_ai/__init__.py +4 -0
  42. luminarycloud/physics_ai/inference.py +140 -4
  43. luminarycloud/physics_ai/solution.py +60 -0
  44. luminarycloud/tables.py +6 -8
  45. luminarycloud/vis/data_extraction.py +4 -5
  46. luminarycloud/vis/display.py +26 -11
  47. luminarycloud/vis/filters.py +98 -65
  48. luminarycloud/vis/primitives.py +3 -2
  49. luminarycloud/vis/visualization.py +197 -40
  50. {luminarycloud-0.15.5.dist-info → luminarycloud-0.16.0.dist-info}/METADATA +1 -1
  51. {luminarycloud-0.15.5.dist-info → luminarycloud-0.16.0.dist-info}/RECORD +52 -50
  52. {luminarycloud-0.15.5.dist-info → luminarycloud-0.16.0.dist-info}/WHEEL +0 -0
@@ -15,9 +15,10 @@ from .display import Field, DisplayAttributes
15
15
  from typing import List, Any, cast
16
16
  from .primitives import Box, Plane
17
17
  from .vis_util import generate_id
18
+ from .._helpers._code_representation import CodeRepr
18
19
 
19
20
 
20
- class Filter(ABC):
21
+ class Filter(ABC, CodeRepr):
21
22
  """
22
23
  This is the base class for all filters. Each derived filter class
23
24
  is responsible for providing a _to_proto method to convert to a filter
@@ -95,7 +96,7 @@ class Slice(Filter):
95
96
  Specifies this filter's appearance.
96
97
  """
97
98
 
98
- def __init__(self, name: str) -> None:
99
+ def __init__(self, name: str = "") -> None:
99
100
  super().__init__(generate_id("slice-"))
100
101
  self._plane = Plane()
101
102
  self._project_vectors: bool = False
@@ -166,7 +167,7 @@ class Isosurface(Filter):
166
167
  Specifies this filter's appearance.
167
168
  """
168
169
 
169
- def __init__(self, name: str) -> None:
170
+ def __init__(self, name: str = "") -> None:
170
171
  super().__init__(generate_id("contour-"))
171
172
  self.isovalues: List[float] = []
172
173
  self.field: Field = Field()
@@ -233,11 +234,9 @@ class PlaneClip(Filter):
233
234
  are removed. Default: False
234
235
  """
235
236
 
236
- def __init__(self, name: str) -> None:
237
+ def __init__(self, name: str = "") -> None:
237
238
  super().__init__(generate_id("planeClip-"))
238
239
  self._plane: Plane = Plane()
239
- # TODO(matt): We could make this a prop to that is unsettable. Or we could
240
- # not use ids and force that the filter names are unique.
241
240
  self.name = name
242
241
  self.inverted: bool = False
243
242
 
@@ -296,7 +295,7 @@ class BoxClip(Filter):
296
295
  Default : False
297
296
  """
298
297
 
299
- def __init__(self, name: str) -> None:
298
+ def __init__(self, name: str = "") -> None:
300
299
  super().__init__(generate_id("boxClip-"))
301
300
  self._box: Box = Box()
302
301
  self.name = name
@@ -358,17 +357,11 @@ class VectorGlyphs(Filter):
358
357
 
359
358
  """
360
359
 
361
- def __init__(self, name: str) -> None:
360
+ def __init__(self, name: str = "") -> None:
362
361
  super().__init__(generate_id("vector-"))
363
362
  self.name: str = name
364
- # TODO(matt): we should be able to help set some reasonable defaults bases
365
- # on the mesh size (i.e., number of points) and bounds (the default glyph size).
366
- # The scene has accesss to this theoretically. Perhaps the scene class can be used
367
- # as a factory.
368
363
  self._sampling_rate: int = 500
369
- self.field: Field = Field()
370
- # TODO(matt): we should only allow vectors somehow
371
- self.field.quantity = VisQuantity.VELOCITY
364
+ self.quantity: VisQuantity = VisQuantity.VELOCITY
372
365
 
373
366
  @property
374
367
  def sampling_rate(self) -> int:
@@ -403,11 +396,11 @@ class FixedSizeVectorGlyphs(VectorGlyphs):
403
396
  The size in world units (meters) of the glyphs.
404
397
  display_attrs (DisplayAttributes)
405
398
  Specifies this filters appearance.
406
- field: Field
399
+ quantity: VisQuantity
407
400
  The vector field to use for glyph generation. Default: Velocity
408
401
  """
409
402
 
410
- def __init__(self, name: str) -> None:
403
+ def __init__(self, name: str = "") -> None:
411
404
  super().__init__(name)
412
405
  self.size: float = 1.0
413
406
 
@@ -418,10 +411,10 @@ class FixedSizeVectorGlyphs(VectorGlyphs):
418
411
  vis_filter.glyph.fixed_size_glyphs = self.size
419
412
  vis_filter.glyph.n_glyphs = self.sampling_rate
420
413
  vis_filter.glyph.sampling_mode = vis_pb2.GLYPH_SAMPLING_MODE_EVERY_NTH
421
- if not quantity_type._is_vector(self.field.quantity):
414
+ if not quantity_type._is_vector(self.quantity):
422
415
  raise ValueError("FixedSizeVectorGlyphs: field must be a vector type")
423
- vis_filter.glyph.field.quantity_typ = self.field.quantity.value
424
- vis_filter.glyph.field.component = self.field.component.value
416
+ vis_filter.glyph.field.quantity_typ = self.quantity.value
417
+ vis_filter.glyph.field.component = vis_pb2.Field.COMPONENT_UNSPECIFIED
425
418
  return vis_filter
426
419
 
427
420
  def _from_proto(self, filter: vis_pb2.Filter) -> None:
@@ -436,8 +429,7 @@ class FixedSizeVectorGlyphs(VectorGlyphs):
436
429
  self.n_glyphs = filter.glyph.n_glyphs
437
430
  self.size = filter.glyph.fixed_size_glyphs
438
431
  self.sampling_rate = filter.glyph.n_glyphs
439
- self.field.quantity = VisQuantity(filter.glyph.field.quantity_typ)
440
- self.field.component = FieldComponent(filter.glyph.field.component)
432
+ self.quantity = VisQuantity(filter.glyph.field.quantity_typ)
441
433
 
442
434
 
443
435
  class ScaledVectorGlyphs(VectorGlyphs):
@@ -464,11 +456,11 @@ class ScaledVectorGlyphs(VectorGlyphs):
464
456
  0.5 and the scale is 2 then the resulting world space size is 1 meter. Default: 1.
465
457
  display_attrs (DisplayAttributes)
466
458
  Specifies this filters appearance.
467
- field: Field
459
+ quantity: VisQuantity
468
460
  The vector field to use for glyph generation. Default: Velocity
469
461
  """
470
462
 
471
- def __init__(self, name: str) -> None:
463
+ def __init__(self, name: str = "") -> None:
472
464
  super().__init__(name)
473
465
  self.scale: float = 1.0
474
466
 
@@ -479,10 +471,10 @@ class ScaledVectorGlyphs(VectorGlyphs):
479
471
  vis_filter.glyph.glyph_scale_size = self.scale
480
472
  vis_filter.glyph.n_glyphs = self.sampling_rate
481
473
  vis_filter.glyph.sampling_mode = vis_pb2.GLYPH_SAMPLING_MODE_EVERY_NTH
482
- if not quantity_type._is_vector(self.field.quantity):
474
+ if not quantity_type._is_vector(self.quantity):
483
475
  raise ValueError("ScaledVectorGyph: field must be a vector type")
484
- vis_filter.glyph.field.quantity_typ = self.field.quantity.value
485
- vis_filter.glyph.field.component = self.field.component.value
476
+ vis_filter.glyph.field.quantity_typ = self.quantity.value
477
+ vis_filter.glyph.field.component = vis_pb2.Field.COMPONENT_UNSPECIFIED
486
478
  return vis_filter
487
479
 
488
480
  def _from_proto(self, filter: vis_pb2.Filter) -> None:
@@ -497,8 +489,7 @@ class ScaledVectorGlyphs(VectorGlyphs):
497
489
  self.n_glyphs = filter.glyph.n_glyphs
498
490
  self.scale = filter.glyph.glyph_scale_size
499
491
  self.sampling_rate = filter.glyph.n_glyphs
500
- self.field.quantity = VisQuantity(filter.glyph.field.quantity_typ)
501
- self.field.component = FieldComponent(filter.glyph.field.component)
492
+ self.quantity = VisQuantity(filter.glyph.field.quantity_typ)
502
493
 
503
494
 
504
495
  class Threshold(Filter):
@@ -533,7 +524,7 @@ class Threshold(Filter):
533
524
  Specifies this filter's appearance.
534
525
  """
535
526
 
536
- def __init__(self, name: str) -> None:
527
+ def __init__(self, name: str = "") -> None:
537
528
  super().__init__(generate_id("threshold-"))
538
529
  self.field: Field = Field()
539
530
  self.min_value: float = 0.0
@@ -610,14 +601,13 @@ class Streamlines(Filter):
610
601
  Specifies this filter's appearance.
611
602
  """
612
603
 
613
- def __init__(self, name: str) -> None:
604
+ def __init__(self, name: str = "") -> None:
614
605
  super().__init__(generate_id("streamlines-"))
615
606
  self.name: str = name
616
607
  self.n_streamlines: int = 100
617
608
  self.max_length: float = 10
618
609
  self.direction: StreamlineDirection = StreamlineDirection.FORWARD
619
- self.field: Field = Field()
620
- self.field.quantity = VisQuantity.VELOCITY
610
+ self.quantity: VisQuantity = VisQuantity.VELOCITY
621
611
 
622
612
 
623
613
  class RakeStreamlines(Streamlines):
@@ -640,7 +630,7 @@ class RakeStreamlines(Streamlines):
640
630
  The number of seed particles to place on the rake. Default: 100
641
631
  max_length: float
642
632
  The maximum path length of the particle in meters. Default: 10
643
- field: Field
633
+ quantity: VisQuantity
644
634
  The vector field to used for the particle advection. Default: Velocity
645
635
  start: Vector3Like
646
636
  The start point of the rake. Default: [0,0,0].
@@ -652,10 +642,10 @@ class RakeStreamlines(Streamlines):
652
642
  Specifies this filter's appearance.
653
643
  """
654
644
 
655
- def __init__(self, name: str) -> None:
645
+ def __init__(self, name: str = "") -> None:
656
646
  super().__init__(name)
657
- self.start: Vector3Like = dc.field(default_factory=lambda: Vector3(x=0, y=0, z=0))
658
- self.end: Vector3Like = dc.field(default_factory=lambda: Vector3(x=1, y=0, z=0))
647
+ self.start: Vector3Like = Vector3(x=0, y=0, z=0)
648
+ self.end: Vector3Like = Vector3(x=1, y=0, z=0)
659
649
 
660
650
  def _to_proto(self) -> vis_pb2.Filter:
661
651
  # Type checking
@@ -663,8 +653,8 @@ class RakeStreamlines(Streamlines):
663
653
  raise TypeError(f"Expected 'int', got {type(self.n_streamlines).__name__}")
664
654
  if not isinstance(self.max_length, (float, int)):
665
655
  raise TypeError(f"Expected 'float or int', got {type(self.max_length).__name__}")
666
- if not isinstance(self.field, Field):
667
- raise TypeError(f"Expected 'Field', got {type(self.field).__name__}")
656
+ if not isinstance(self.quantity, VisQuantity):
657
+ raise TypeError(f"Expected 'VisQuantity', got {type(self.quantity).__name__}")
668
658
 
669
659
  vis_filter = vis_pb2.Filter()
670
660
  vis_filter.id = self.id
@@ -673,9 +663,9 @@ class RakeStreamlines(Streamlines):
673
663
  vis_filter.streamlines.max_length = self.max_length
674
664
  vis_filter.streamlines.rake.start.CopyFrom(_to_vector3(self.start)._to_proto())
675
665
  vis_filter.streamlines.rake.end.CopyFrom(_to_vector3(self.end)._to_proto())
676
- if not quantity_type._is_vector(self.field.quantity):
666
+ if not quantity_type._is_vector(self.quantity):
677
667
  raise ValueError("RakeStreamlines: field must be a vector type")
678
- vis_filter.streamlines.field.quantity_typ = self.field.quantity.value
668
+ vis_filter.streamlines.field.quantity_typ = self.quantity.value
679
669
  return vis_filter
680
670
 
681
671
  def _from_proto(self, filter: vis_pb2.Filter) -> None:
@@ -694,7 +684,7 @@ class RakeStreamlines(Streamlines):
694
684
  self.start._from_proto(filter.streamlines.rake.start)
695
685
  self.end = Vector3()
696
686
  self.end._from_proto(filter.streamlines.rake.end)
697
- self.field.quantity = VisQuantity(filter.streamlines.field.quantity_typ)
687
+ self.quantity = VisQuantity(filter.streamlines.field.quantity_typ)
698
688
 
699
689
 
700
690
  class SurfaceStreamlines(Streamlines):
@@ -741,7 +731,7 @@ class SurfaceStreamlines(Streamlines):
741
731
  particles further into the volume based on the surface normal. Default: 0.0
742
732
  max_length: float
743
733
  The maximum path length of the particle in meters. Default: 10
744
- field: Field
734
+ quantity: VisQuantity
745
735
  The vector field to used for the particle advection. Default: Velocity
746
736
  name : str
747
737
  A user provided name for the filter.
@@ -749,7 +739,7 @@ class SurfaceStreamlines(Streamlines):
749
739
  Specifies this filter's appearance.
750
740
  """
751
741
 
752
- def __init__(self, name: str) -> None:
742
+ def __init__(self, name: str = "") -> None:
753
743
  super().__init__(name)
754
744
  self.offset: float = 0.0
755
745
  self._surface_names: List[str] = []
@@ -783,8 +773,8 @@ class SurfaceStreamlines(Streamlines):
783
773
  raise TypeError(f"Expected 'float or int', got {type(self.max_length).__name__}")
784
774
  if not isinstance(self.offset, (float, int)):
785
775
  raise TypeError(f"Expected 'float or int', got {type(self.offset).__name__}")
786
- if not isinstance(self.field, Field):
787
- raise TypeError(f"Expected 'Field', got {type(self.field).__name__}")
776
+ if not isinstance(self.quantity, VisQuantity):
777
+ raise TypeError(f"Expected 'VisQuantity', got {type(self.quantity).__name__}")
788
778
  if not isinstance(self.mode, SurfaceStreamlineMode):
789
779
  raise TypeError(f"Expected 'SurfaceStreamlinesMode', got {type(self.mode).__name__}")
790
780
 
@@ -796,12 +786,12 @@ class SurfaceStreamlines(Streamlines):
796
786
  project = False
797
787
  # Prevent common mistakes that cause confusion.
798
788
  if self.mode == SurfaceStreamlineMode.ADVECT_ON_SURFACE:
799
- if self.field.quantity == VisQuantity.VELOCITY:
789
+ if self.quantity == VisQuantity.VELOCITY:
800
790
  raise ValueError(
801
791
  "SurfacesStreamines: velocity is 0 on surfaces and will produce no data"
802
792
  )
803
793
  project = True
804
- elif self.field.quantity == VisQuantity.WALL_SHEAR_STRESS:
794
+ elif self.quantity == VisQuantity.WALL_SHEAR_STRESS:
805
795
  raise ValueError(
806
796
  "SurfacesStreamines: wall shear stress is 0 in the volume and will produce no data "
807
797
  )
@@ -811,10 +801,9 @@ class SurfaceStreamlines(Streamlines):
811
801
  raise ValueError("SurfaceStreamlines: need at least one surfaces specified.")
812
802
  for id in self._surface_names:
813
803
  vis_filter.streamlines.surface.surface_names.append(id)
814
- if not quantity_type._is_vector(self.field.quantity):
815
- raise ValueError("SurfaceStreamlines: field must be a vector type")
816
- vis_filter.streamlines.field.component = self.field.component.value
817
- vis_filter.streamlines.field.quantity_typ = self.field.quantity.value
804
+ if not quantity_type._is_vector(self.quantity):
805
+ raise ValueError("SurfaceStreamlines: quantity must be a vector type")
806
+ vis_filter.streamlines.field.quantity_typ = self.quantity.value
818
807
  return vis_filter
819
808
 
820
809
  def _from_proto(self, filter: vis_pb2.Filter) -> None:
@@ -831,7 +820,15 @@ class SurfaceStreamlines(Streamlines):
831
820
  self._surface_names.clear()
832
821
  for s in filter.streamlines.surface.surface_names:
833
822
  self._surface_names.append(s)
834
- self.field.quantity = VisQuantity(filter.streamlines.field.quantity_typ)
823
+ self.quantity = VisQuantity(filter.streamlines.field.quantity_typ)
824
+
825
+ def _to_code(self, hide_defaults: bool = True, use_tmp_objs: bool = True) -> str:
826
+ code = super()._to_code(hide_defaults=hide_defaults)
827
+ # We need to explicity write the code for the surfaces since its
828
+ # technically a private variable.
829
+ for s in self._surface_names:
830
+ code += f".add_surface('{s}')\n"
831
+ return code
835
832
 
836
833
 
837
834
  class SurfaceLIC(Filter):
@@ -855,7 +852,7 @@ class SurfaceLIC(Filter):
855
852
 
856
853
  Attributes:
857
854
  -----------
858
- field: Field
855
+ quantity: VisQuantity
859
856
  Specifies the field used to advect particles for the surface LIC.
860
857
  Default: WALL_SHEER_STRESS
861
858
  contrast: float
@@ -864,13 +861,12 @@ class SurfaceLIC(Filter):
864
861
  higher values mean more contrast. Default: 1
865
862
  """
866
863
 
867
- def __init__(self, name: str) -> None:
864
+ def __init__(self, name: str = "") -> None:
868
865
  super().__init__(generate_id("surface-lic-"))
869
866
  self.name = name
870
867
  self.contrast: float = 1.0
871
868
  self._surface_names: List[str] = []
872
- self.field: Field = Field()
873
- self.field.quantity = VisQuantity.WALL_SHEAR_STRESS
869
+ self.quantity: VisQuantity = VisQuantity.WALL_SHEAR_STRESS
874
870
 
875
871
  def add_surface(self, id: str) -> None:
876
872
  """
@@ -898,9 +894,9 @@ class SurfaceLIC(Filter):
898
894
  vis_filter.name = self.name
899
895
  # Prevent common mistakes that cause confusion. The only current option
900
896
  # is to be on a surface, so no velocity.
901
- if not isinstance(self.field, Field):
902
- raise TypeError(f"Expected 'Field', got {type(self.field).__name__}")
903
- if self.field.quantity == VisQuantity.VELOCITY:
897
+ if not isinstance(self.quantity, VisQuantity):
898
+ raise TypeError(f"Expected 'VisQuantity', got {type(self.quantity).__name__}")
899
+ if self.quantity == VisQuantity.VELOCITY:
904
900
  raise ValueError("SurfaceLIC: velocity is 0 on surfaces and will produce no data")
905
901
  if not isinstance(self.contrast, (int, float)):
906
902
  raise TypeError(f"Expected 'int or float', got {type(self.contrast).__name__}")
@@ -914,7 +910,7 @@ class SurfaceLIC(Filter):
914
910
  geometry = vis_pb2.SurfaceLICGeomtery()
915
911
  vis_filter.surface_lic.geometry.CopyFrom(geometry)
916
912
 
917
- vis_filter.surface_lic.field.quantity_typ = self.field.quantity.value
913
+ vis_filter.surface_lic.field.quantity_typ = self.quantity.value
918
914
  vis_filter.surface_lic.contrast = self.contrast
919
915
  return vis_filter
920
916
 
@@ -932,7 +928,44 @@ class SurfaceLIC(Filter):
932
928
  self._surface_names = []
933
929
  for s in filter.surface_lic.geometry.surface_names:
934
930
  self._surface_names.append(s)
935
- if not quantity_type._is_vector(self.field.quantity):
936
- raise ValueError("SurfaceLIC: field must be a vector type")
937
- self.field.quantity = VisQuantity(filter.surface_lic.field.quantity_typ)
938
- self.field.component = FieldComponent(filter.surface_lic.field.component)
931
+ if not quantity_type._is_vector(self.quantity):
932
+ raise ValueError("SurfaceLIC: quantity must be a vector type")
933
+ self.quantity = VisQuantity(filter.surface_lic.field.quantity_typ)
934
+
935
+ def _to_code(self, hide_defaults: bool = True, use_tmp_objs: bool = True) -> str:
936
+ code = super()._to_code(hide_defaults=hide_defaults)
937
+ # We need to explicity write the code for the surfaces since its
938
+ # technically a private variable.
939
+ for s in self._surface_names:
940
+ code += f".add_surface('{s}')\n"
941
+ return code
942
+
943
+
944
+ def _filter_to_obj_name(filter: Filter) -> str:
945
+ """
946
+ Helper function to convert a filter to a code object name used in code gen.
947
+ """
948
+ if not isinstance(filter, Filter):
949
+ raise TypeError(f"Expected 'Filter', got {type(filter).__name__}")
950
+ if isinstance(filter, Slice):
951
+ return "slice"
952
+ elif isinstance(filter, Isosurface):
953
+ return "isosurface"
954
+ elif isinstance(filter, PlaneClip):
955
+ return "plane_clip"
956
+ elif isinstance(filter, BoxClip):
957
+ return "box_clip"
958
+ elif isinstance(filter, FixedSizeVectorGlyphs):
959
+ return "fixed_size_vector_glyphs"
960
+ elif isinstance(filter, ScaledVectorGlyphs):
961
+ return "scaled_vector_glyphs"
962
+ elif isinstance(filter, Threshold):
963
+ return "threshold"
964
+ elif isinstance(filter, RakeStreamlines):
965
+ return "rake_streamlines"
966
+ elif isinstance(filter, SurfaceStreamlines):
967
+ return "surface_streamlines"
968
+ elif isinstance(filter, SurfaceLIC):
969
+ return "surface_lic"
970
+ else:
971
+ raise TypeError(f"Unknown filter type: {type(filter).__name__}")
@@ -1,10 +1,11 @@
1
1
  # Copyright 2023-2024 Luminary Cloud, Inc. All Rights Reserved.
2
2
  import dataclasses as dc
3
3
  from luminarycloud.types import Vector3, Vector3Like
4
+ from .._helpers._code_representation import CodeRepr
4
5
 
5
6
 
6
7
  @dc.dataclass
7
- class Plane:
8
+ class Plane(CodeRepr):
8
9
  """
9
10
  This class defines a plane.
10
11
 
@@ -19,7 +20,7 @@ class Plane:
19
20
 
20
21
 
21
22
  @dc.dataclass
22
- class Box:
23
+ class Box(CodeRepr):
23
24
  """
24
25
  This class defines a box used for filter such as box clip.
25
26