PointcloudEpisodeFrameCollection

class PointcloudEpisodeFrameCollection(items=None)[source]

Bases: FrameCollection

Collection with PointcloudEpisodeFrame instances. PointcloudEpisodeFrameCollection object is immutable.

Usage Example:
import supervisely as sly
from supervisely.geometry.cuboid_3d import Cuboid3d, Vector3d
from supervisely.pointcloud_annotation.pointcloud_episode_object_collection import PointcloudEpisodeObjectCollection

# Create pointcloud object
obj_class_car = sly.ObjClass('car', Cuboid3d)
pointcloud_obj_car = sly.PointcloudEpisodeObject(obj_class_car)
objects = PointcloudEpisodeObjectCollection([pointcloud_obj_car])

# Create two figures
frame_index_1 = 7
position_1, rotation_1, dimension_1 = Vector3d(-3.4, 28.9, -0.7), Vector3d(0., 0, -0.03), Vector3d(1.8, 3.9, 1.6)
cuboid_1 = Cuboid3d(position_1, rotation_1, dimension_1)

frame_index_2 = 10
position_2, rotation_2, dimension_2 = Vector3d(-3.4, 28.9, -0.7), Vector3d(0., 0, -0.03), Vector3d(1.8, 3.9, 1.6)
cuboid_2 = Cuboid3d(position_2, rotation_2, dimension_2)

figure_1 = sly.PointcloudFigure(pointcloud_obj_car, cuboid_1, frame_index=frame_index_1)
figure_2 = sly.PointcloudFigure(pointcloud_obj_car, cuboid_2, frame_index=frame_index_2)

# Create two frames for collection
frame_1 = sly.PointcloudEpisodeFrame(frame_index_1, figures=[figure_1])
frame_2 = sly.PointcloudEpisodeFrame(frame_index_2, figures=[figure_2])

# Create PointcloudEpisodeFrameCollection
pcd_episodes_fr_collection = sly.PointcloudEpisodeFrameCollection([frame_1, frame_2])

print(pcd_episodes_fr_collection.to_json())
# Output: [
#     {
#         "figures": [
#         {
#             "geometry": {
#             "dimensions": { "x": 1.8, "y": 3.9, "z": 1.6 },
#             "position": { "x": -3.4, "y": 28.9, "z": -0.7 },
#             "rotation": { "x": 0.0, "y": 0, "z": -0.03 }
#             },
#             "geometryType": "cuboid_3d",
#             "key": "c9fb727a9b53432fa0316d0a5b6043bc",
#             "objectKey": "0fc681681b1f4b12909ccf685c53b43e"
#         }
#         ],
#         "index": 7
#     },
#     {
#         "figures": [
#         {
#             "geometry": {
#             "dimensions": { "x": 1.8, "y": 3.9, "z": 1.6 },
#             "position": { "x": -3.4, "y": 28.9, "z": -0.7 },
#             "rotation": { "x": 0.0, "y": 0, "z": -0.03 }
#             },
#             "geometryType": "cuboid_3d",
#             "key": "c3df69c90fa14cf284906ebad1c360ae",
#             "objectKey": "0fc681681b1f4b12909ccf685c53b43e"
#         }
#         ],
#         "index": 10
#     }
# ]

# Add item to PointcloudEpisodeFrameCollection
frame_index_3 = 13
frame_3 = sly.PointcloudEpisodeFrame(frame_index_3)
# Remember that PointcloudEpisodeFrameCollection is immutable, and we need to assign new instance of PointcloudEpisodeFrameCollection to a new variable
new_pcd_episodes_fr_collection = pcd_episodes_fr_collection.add(frame_3)
print(new_pcd_episodes_fr_collection.to_json())
# Output: [
#     {
#         "figures": [
#         {
#             "geometry": {
#             "dimensions": { "x": 1.8, "y": 3.9, "z": 1.6 },
#             "position": { "x": -3.4, "y": 28.9, "z": -0.7 },
#             "rotation": { "x": 0.0, "y": 0, "z": -0.03 }
#             },
#             "geometryType": "cuboid_3d",
#             "key": "d16c2bf646664007bd22bcf2996710ed",
#             "objectKey": "e09431246cc24231a9d76b9ba55ce4e7"
#         }
#         ],
#         "index": 7
#     },
#     {
#         "figures": [
#         {
#             "geometry": {
#             "dimensions": { "x": 1.8, "y": 3.9, "z": 1.6 },
#             "position": { "x": -3.4, "y": 28.9, "z": -0.7 },
#             "rotation": { "x": 0.0, "y": 0, "z": -0.03 }
#             },
#             "geometryType": "cuboid_3d",
#             "key": "9f915e2d4342408ab0d4517f485f9950",
#             "objectKey": "e09431246cc24231a9d76b9ba55ce4e7"
#         }
#         ],
#         "index": 10
#     },
#     { "figures": [], "index": 13 }
# ]

# You can also add multiple items to collection
frame_3 = sly.PointcloudEpisodeFrame(12)
frame_4 = sly.PointcloudEpisodeFrame(15)
# Remember that PointcloudEpisodeFrameCollection is immutable, and we need to assign new instance of PointcloudEpisodeFrameCollection to a new variable
new_pcd_episodes_fr_collection = pcd_episodes_fr_collection.add_items([frame_3, frame_4])
print(new_pcd_episodes_fr_collection.to_json())
# Output: [
#     {
#         "figures": [
#         {
#             "geometry": {
#             "dimensions": { "x": 1.8, "y": 3.9, "z": 1.6 },
#             "position": { "x": -3.4, "y": 28.9, "z": -0.7 },
#             "rotation": { "x": 0.0, "y": 0, "z": -0.03 }
#             },
#             "geometryType": "cuboid_3d",
#             "key": "df14bb10e76c4b4093a137f4ea01e3ba",
#             "objectKey": "a83a21ef7b734bb9949ddf132b42d1f0"
#         }
#         ],
#         "index": 7
#     },
#     {
#         "figures": [
#         {
#             "geometry": {
#             "dimensions": { "x": 1.8, "y": 3.9, "z": 1.6 },
#             "position": { "x": -3.4, "y": 28.9, "z": -0.7 },
#             "rotation": { "x": 0.0, "y": 0, "z": -0.03 }
#             },
#             "geometryType": "cuboid_3d",
#             "key": "6f86a1859da34415a37896ec2c972b47",
#             "objectKey": "a83a21ef7b734bb9949ddf132b42d1f0"
#         }
#         ],
#         "index": 10
#     },
#     { "figures": [], "index": 12 },
#     { "figures": [], "index": 15 }
# ]

# Has key, checks if given key exist in point cloud episodes frame collection
pcd_episodes_fr_collection.has_key(10) # True
pcd_episodes_fr_collection.has_key(22) # False

# Find intersection of given list of instances with collection items
frame_1 = sly.PointcloudEpisodeFrame(1)
frame_2 = sly.PointcloudEpisodeFrame(2)
pcd_episodes_fr_collection = sly.PointcloudEpisodeFrameCollection([frame_1, frame_2])

frame_3 = sly.PointcloudEpisodeFrame(3)

frames_intersections = pcd_episodes_fr_collection.intersection([frame_3])
print(frames_intersections.to_json())
# Output: []

frames_intersections = pcd_episodes_fr_collection.intersection([frame_2])
print(frames_intersections.to_json())
# Output: [
#     {
#         "index": 2,
#         "figures": []
#     }
# ]

# Note, two frames with the same index values are not equal
frame_4 = sly.PointcloudEpisodeFrame(2)
frames_intersections = pcd_episodes_fr_collection.intersection([frame_4])
# Output:
# ValueError: Different values for the same key 2

# Find difference between collection and given list of PointcloudEpisodeFrame
frames_difference = pcd_episodes_fr_collection.difference([frame_2])
print(frames_difference.to_json())
# Output: [
#     {
#         "index": 1,
#         "figures": []
#     }
# ]

# Merge collection and given list of PointcloudEpisodeFrameCollection
frame_3 = sly.PointcloudEpisodeFrame(3)
frame_4 = sly.PointcloudEpisodeFrame(4)
over_collection = sly.PointcloudEpisodeFrameCollection([frame_3, frame_4])
merged_collection = pcd_episodes_fr_collection.merge(over_collection)
print(merged_collection.to_json())
# Output: [
#     { "index": 3, "figures": [] },
#     { "index": 4, "figures": [] },
#     { "index": 1, "figures": [] },
#     { "index": 2, "figures": [] }
# ]

Base class for ObjClassCollection, TagMetaCollection and TagCollection instances. It is an analogue of python’s standard Dict. It allows to store objects inherited from KeyObject.

Parameters:
items : list, optional

List of ObjClassCollection, TagMetaCollection and TagCollection objects.

:raises DuplicateKeyError, when trying to add object with already existing key

Usage Example:
import supervisely as sly

item_cat = sly.TagMeta('cat', sly.TagValueType.NONE)
item_turtle = sly.TagMeta('turtle', sly.TagValueType.ANY_STRING)
collection = sly.collection.key_indexed_collection.KeyIndexedCollection([item_cat, item_turtle])
print(collection.to_json())
# Output: [
#     {
#         "name": "cat",
#         "value_type": "none",
#         "color": "#8A0F12",
#         "hotkey": "",
#         "applicable_type": "all",
#         "classes": []
#     },
#     {
#         "name": "turtle",
#         "value_type": "any_string",
#         "color": "#8A860F",
#         "hotkey": "",
#         "applicable_type": "all",
#         "classes": []
#     }
# ]

# Try to add item with a key that already exists in the collection
dublicate_item = sly.ObjClass('cat', sly.Rectangle)
new_collection = collection.add(dublicate_item)
# Output:
# DuplicateKeyError: "Key 'cat' already exists"

# Add item with a key that not exist in the collection
item_dog = sly.ObjClass('dog', sly.Rectangle)
new_collection = collection.add(item_dog)
print(new_collection.to_json())
# Output: [
#     {
#         "name": "cat",
#         "value_type": "none",
#         "color": "#668A0F",
#         "hotkey": "",
#         "applicable_type": "all",
#         "classes": []
#     },
#     {
#         "name": "turtle",
#         "value_type": "any_string",
#         "color": "#4D0F8A",
#         "hotkey": "",
#         "applicable_type": "all",
#         "classes": []
#     },
#     {
#         "title": "dog",
#         "shape": "rectangle",
#         "color": "#0F7F8A",
#         "geometry_config": {},
#         "hotkey": ""
#     }
# ]

Methods

add

Add given item to collection.

add_items

Add items from given list to collection.

clone

Makes a copy of KeyIndexedCollection with new fields, if fields are given, otherwise it will use fields of the original KeyIndexedCollection.

difference

Find difference between collection and given list of instances.

from_json

Convert a list of json dicts to PointcloudEpisodeFrameCollection.

get

Get a PointcloudEpisodeFrame by its key and set default value if it does not exist.

get_figures_and_keys

Get figures from all frames in collection in json format, keys from all figures in frames in collection.

has_key

Check if given key(item name exist in collection).

intersection

Find intersection of given list of instances with collection items.

items

Get list of all items in collection.

keys

Get list of all keys(item names) in collection.

merge

Merge collection and other KeyIndexedCollection object.

remove_items

Remove items from collection by given list of keys.

to_json

Convert the FrameCollection to a list of json dicts.

Attributes

figures

Get figures from all frames in collection.

item_type

alias of PointcloudEpisodeFrame

classmethod from_json(data, objects, frames_count=None, key_id_map=None)[source]

Convert a list of json dicts to PointcloudEpisodeFrameCollection. Read more about Supervisely format.

Parameters:
data : List[dict]

List with dicts in json format.

objects

Pointcloud episode objects collection.

frames_count : int

Number of frames in pointcloud episodes.

key_id_map=None

Key ID map.

Returns:

Pointcloud episode frames collection.

Return type:

PointcloudEpisodeFrameCollection

Usage Example:
import supervisely as sly

fr_collection_json = [
    {
        "figures": [
            {
                "geometry": {
                    "dimensions": { "x": 1.8, "y": 3.9, "z": 1.6 },
                    "position": { "x": -3.4, "y": 28.9, "z": -0.7 },
                    "rotation": { "x": 0.0, "y": 0, "z": -0.03 }
                },
                "geometryType": "cuboid_3d",
                "key": "c9fb727a9b53432fa0316d0a5b6043bc",
                "objectKey": "0fc681681b1f4b12909ccf685c53b43e"
            }
        ],
        "index": 7
    },
    {
        "figures": [
            {
                "geometry": {
                    "dimensions": { "x": 1.8, "y": 3.9, "z": 1.6 },
                    "position": { "x": -3.4, "y": 28.9, "z": -0.7 },
                    "rotation": { "x": 0.0, "y": 0, "z": -0.03 }
                },
                "geometryType": "cuboid_3d",
                "key": "c3df69c90fa14cf284906ebad1c360ae",
                "objectKey": "0fc681681b1f4b12909ccf685c53b43e"
            }
        ],
        "index": 10
    }
]

objects = []
fr_collection = sly.PointcloudEpisodeFrameCollection.from_json(fr_collection_json, objects)
add(item)

Add given item to collection.

Parameters:
item

ObjClassCollection, TagMetaCollection or TagCollection object.

Returns:

New instance of KeyIndexedCollection

Return type:

KeyIndexedCollection

Usage Example:
import supervisely as sly

item_cat = sly.TagMeta('cat', sly.TagValueType.NONE)
item_turtle = sly.TagMeta('turtle', sly.TagValueType.ANY_STRING)
collection = sly.collection.key_indexed_collection.KeyIndexedCollection([item_cat, item_turtle])

# Remember that KeyIndexedCollection object is immutable, and we need to assign new instance of KeyIndexedCollection to a new variable
item_dog = sly.ObjClass('dog', sly.Rectangle)
new_collection = collection.add(item_dog)
add_items(items)

Add items from given list to collection.

Parameters:
items

List of ObjClassCollection, TagMetaCollection or TagCollection objects.

Returns:

New instance of KeyIndexedCollection

Return type:

KeyIndexedCollection

Usage Example:
import supervisely as sly

item_cat = sly.TagMeta('cat', sly.TagValueType.NONE)
item_turtle = sly.TagMeta('turtle', sly.TagValueType.ANY_STRING)
collection = sly.collection.key_indexed_collection.KeyIndexedCollection([item_cat, item_turtle])

# Remember that KeyIndexedCollection object is immutable, and we need to assign new instance of KeyIndexedCollection to a new variable
item_dog = sly.ObjClass('dog', sly.Rectangle)
item_mouse = sly.ObjClass('mouse', sly.Bitmap)
new_collection = collection.add_items([item_dog, item_mouse])
clone(items=None)

Makes a copy of KeyIndexedCollection with new fields, if fields are given, otherwise it will use fields of the original KeyIndexedCollection.

Parameters:
items=None

List of ObjClassCollection, TagMetaCollection or TagCollection objects.

Returns:

New instance of KeyIndexedCollection

Return type:

KeyIndexedCollection

Usage Example:
import supervisely as sly

item_cat = sly.TagMeta('cat', sly.TagValueType.NONE)
item_turtle = sly.TagMeta('turtle', sly.TagValueType.ANY_STRING)
collection = sly.collection.key_indexed_collection.KeyIndexedCollection([item_cat, item_turtle])

# Remember that KeyIndexedCollection object is immutable, and we need to assign new instance of KeyIndexedCollection to a new variable
new_collection = collection.clone()
difference(other)

Find difference between collection and given list of instances.

Parameters:
other

List of items to subtract from the collection.

Returns:

KeyIndexedCollection object

Return type:

KeyIndexedCollection

Usage Example:
import supervisely as sly

item_cat = sly.TagMeta('cat', sly.TagValueType.NONE)
item_turtle = sly.TagMeta('turtle', sly.TagValueType.ANY_STRING)
collection = sly.collection.key_indexed_collection.KeyIndexedCollection([item_cat, item_turtle])

item_dog = sly.TagMeta('dog', sly.TagValueType.NONE)
item_turtle = sly.TagMeta('turtle', sly.TagValueType.ANY_STRING)
items = [item_dog, item_turtle]

diff = collection.difference(items)
print(diff.to_json())
# Output: [
#     {
#         "name": "cat",
#         "value_type": "none",
#         "color": "#8A150F",
#         "hotkey": "",
#         "applicable_type": "all",
#         "classes": []
#     }
# ]
get(key, default=None)[source]

Get a PointcloudEpisodeFrame by its key and set default value if it does not exist.

Parameters:
key : str

Key of the PointcloudEpisodeFrame.

default : Optional[Any]

Default value to return if the key is not found (default: None).

Returns:

PointcloudEpisodeFrame object.

Return type:

PointcloudEpisodeFrame

Usage Example:
frame_1 = sly.PointcloudEpisodeFrame(1)
frame_2 = sly.PointcloudEpisodeFrame(2)

pcd_episodes_fr_collection = sly.PointcloudEpisodeFrameCollection([frame_1, frame_2])
print(pcd_episodes_fr_collection.get(2).to_json())
# Output: {'index': 2, 'figures': []}
get_figures_and_keys(key_id_map)

Get figures from all frames in collection in json format, keys from all figures in frames in collection.

Parameters:
key_id_map

KeyIdMap object.

Returns:

Figures from all frames in collection in json format, keys from all figures in frames in collection

Return type:

Tuple[List[dict], List[str]]

Usage Example:
import supervisely as sly
from supervisely.video_annotation.key_id_map import KeyIdMap

key_id_map = KeyIdMap()

fr_index_1 = 7
geometry = sly.Rectangle(0, 0, 100, 100)
obj_class_car = sly.ObjClass('car', sly.Rectangle)
video_object_car = sly.VideoObject(obj_class_car)
video_figure_car = sly.VideoFigure(video_object_car, geometry, fr_index_1)
frame_1 = sly.Frame(fr_index_1, figures=[video_figure_car])

fr_index_2 = 10
geometry = sly.Rectangle(0, 0, 500, 600)
obj_class_bus = sly.ObjClass('bus', sly.Rectangle)
video_object_bus = sly.VideoObject(obj_class_bus)
video_figure_bus = sly.VideoFigure(video_object_bus, geometry, fr_index_2)
frame_2 = sly.Frame(fr_index_2, figures=[video_figure_bus])

fr_collection = sly.FrameCollection([frame_1, frame_2])
figures, keys = fr_collection.get_figures_and_keys(key_id_map)
print(keys) # [UUID('0ac041b2-314e-4f6b-9d38-704b341fb383'), UUID('88aa1cb3-b1e3-480f-8ace-6346c9a9daba')]

print(figures)
# Output: [
#     {
#         "key": "a8cae05d6b8c4a67b18004130941fdec",
#         "objectKey": "cc9a9475d360481c9753f8ac3c63f8b7",
#         "geometryType": "rectangle",
#         "geometry": {
#             "points": {
#                 "exterior": [
#                     [
#                         0,
#                         0
#                     ],
#                     [
#                         100,
#                         100
#                     ]
#                 ],
#                 "interior": []
#             }
#         },
#         "meta": {
#             "frame": 7
#         }
#     },
#     {
#         "key": "6e00287acc4644dfb21d67406534080b",
#         "objectKey": "cad78d53ffc84e69a28f5f8941be9021",
#         "geometryType": "rectangle",
#         "geometry": {
#             "points": {
#                 "exterior": [
#                     [
#                         0,
#                         0
#                     ],
#                     [
#                         600,
#                         500
#                     ]
#                 ],
#                 "interior": []
#             }
#         },
#         "meta": {
#             "frame": 10
#         }
#     }
# ]
has_key(key)

Check if given key(item name exist in collection).

Parameters:
key : str

The key to look for in the collection.

Returns:

Is the key in the collection or not

Return type:

bool

Usage Example:
import supervisely as sly

item_cat = sly.TagMeta('cat', sly.TagValueType.NONE)
item_turtle = sly.TagMeta('turtle', sly.TagValueType.ANY_STRING)
collection = sly.collection.key_indexed_collection.KeyIndexedCollection([item_cat, item_turtle])

collection.has_key('cat') # True
collection.has_key('hamster') # False
intersection(other)

Find intersection of given list of instances with collection items.

Parameters:
other

List of items to intersect with the collection.

Raises:

ValueError – if find items with same keys(item names)

Returns:

KeyIndexedCollection object

Return type:

KeyIndexedCollection

Usage Example:
import supervisely as sly

item_cat = sly.TagMeta('cat', sly.TagValueType.NONE)
item_turtle = sly.TagMeta('turtle', sly.TagValueType.ANY_STRING)
collection = sly.collection.key_indexed_collection.KeyIndexedCollection([item_cat, item_turtle])

item_dog = sly.TagMeta('dog', sly.TagValueType.NONE)
item_turtle = sly.TagMeta('turtle', sly.TagValueType.ANY_STRING)
items = [item_dog, item_turtle]

intersection = collection.intersection(items)
print(intersection.to_json())
# Output: [
#     {
#         "name": "turtle",
#         "value_type": "any_string",
#         "color": "#760F8A",
#         "hotkey": "",
#         "applicable_type": "all",
#         "classes": []
#     }
# ]
items()

Get list of all items in collection.

Returns:

List of ObjClassCollection, TagMetaCollection or TagCollection objects

Return type:

List[KeyObject]

Usage Example:
import supervisely as sly

item_cat = sly.TagMeta('cat', sly.TagValueType.NONE)
item_turtle = sly.TagMeta('turtle', sly.TagValueType.ANY_STRING)
collection = sly.collection.key_indexed_collection.KeyIndexedCollection([item_cat, item_turtle])
items = collection.items()
print(items)
# Output:
# [<supervisely.annotation.tag_meta.TagMeta object at 0x7fd08eae4340>,
#  <supervisely.annotation.tag_meta.TagMeta object at 0x7fd08eae4370>]
keys()

Get list of all keys(item names) in collection.

Returns:

List of collection keys

Return type:

List[str]

Usage Example:
import supervisely as sly

item_cat = sly.TagMeta('cat', sly.TagValueType.NONE)
item_turtle = sly.TagMeta('turtle', sly.TagValueType.ANY_STRING)
collection = sly.collection.key_indexed_collection.KeyIndexedCollection([item_cat, item_turtle])
keys = collection.keys() # ['cat', 'turtle']
merge(other)

Merge collection and other KeyIndexedCollection object.

Parameters:
other

Other collection to merge with.

Raises:

ValueError – if item name from given list is in collection but items in both are different

Returns:

KeyIndexedCollection object

Return type:

KeyIndexedCollection

Usage Example:
import supervisely as sly

item_cat = sly.TagMeta('cat', sly.TagValueType.NONE)
item_turtle = sly.TagMeta('turtle', sly.TagValueType.ANY_STRING)
collection = sly.collection.key_indexed_collection.KeyIndexedCollection([item_cat, item_turtle])

item_dog = sly.TagMeta('dog', sly.TagValueType.NONE)
item_turtle = sly.TagMeta('turtle', sly.TagValueType.ANY_STRING)
other_collection = sly.collection.key_indexed_collection.KeyIndexedCollection([item_dog, item_turtle])

merge = collection.merge(other_collection)
print(merge.to_json())
# Output: [
#     {
#         "name": "dog",
#         "value_type": "none",
#         "color": "#8A6C0F",
#         "hotkey": "",
#         "applicable_type": "all",
#         "classes": []
#     },
#     {
#         "name": "cat",
#         "value_type": "none",
#         "color": "#0F4A8A",
#         "hotkey": "",
#         "applicable_type": "all",
#         "classes": []
#     },
#     {
#         "name": "turtle",
#         "value_type": "any_string",
#         "color": "#4F0F8A",
#         "hotkey": "",
#         "applicable_type": "all",
#         "classes": []
#     }
# ]
remove_items(keys)

Remove items from collection by given list of keys. Creates a new instance of KeyIndexedCollection.

Parameters:
keys : List[str]

List of keys(item names) in collection.

Returns:

New instance of KeyIndexedCollection

Return type:

KeyIndexedCollection

to_json(key_id_map=None)

Convert the FrameCollection to a list of json dicts. Read more about Supervisely format.

Parameters:
key_id_map=None

KeyIdMap object.

Returns:

List of dicts in json format

Return type:

List[dict]

Usage Example:
import supervisely as sly

frame_1 = sly.Frame(7)
frame_2 = sly.Frame(10)

# Create FrameCollection
fr_collection = sly.FrameCollection([frame_1, frame_2])
print(fr_collection.to_json())
# Output: [
#     {
#         "index": 7,
#         "figures": []
#     },
#     {
#         "index": 10,
#         "figures": []
#     }
# ]
property figures : list[supervisely.pointcloud_annotation.pointcloud_figure.PointcloudFigure]

Get figures from all frames in collection.

Returns:

List of pointcloud figures from all frames in collection.

Return type:

List[PointcloudFigure]

Usage Example:
import supervisely as sly
from supervisely.geometry.cuboid_3d import Cuboid3d, Vector3d
from supervisely.pointcloud_annotation.pointcloud_episode_object_collection import PointcloudEpisodeObjectCollection

# Create pointcloud object
obj_class_car = sly.ObjClass('car', Cuboid3d)
pointcloud_obj_car = sly.PointcloudEpisodeObject(obj_class_car)
objects = PointcloudEpisodeObjectCollection([pointcloud_obj_car])

# Create two figures
frame_index_1 = 7
position_1, rotation_1, dimension_1 = Vector3d(-3.4, 28.9, -0.7), Vector3d(0., 0, -0.03), Vector3d(1.8, 3.9, 1.6)
cuboid_1 = Cuboid3d(position_1, rotation_1, dimension_1)

frame_index_2 = 10
position_2, rotation_2, dimension_2 = Vector3d(-3.4, 28.9, -0.7), Vector3d(0., 0, -0.03), Vector3d(1.8, 3.9, 1.6)
cuboid_2 = Cuboid3d(position_2, rotation_2, dimension_2)

figure_1 = sly.PointcloudFigure(pointcloud_obj_car, cuboid_1, frame_index=frame_index_1)
figure_1 = sly.PointcloudFigure(pointcloud_obj_car, cuboid_2, frame_index=frame_index_2)

# Create two frames for collection
frame_1 = sly.PointcloudEpisodeFrame(frame_index_1, figures=[figure_1])
frame_2 = sly.PointcloudEpisodeFrame(frame_index_2, figures=[figure_2])

# Create PointcloudEpisodeFrameCollection
pcd_episodes_fr_collection = sly.PointcloudEpisodeFrameCollection([frame_1, frame_2])

print([figure.to_json() for figure in pcd_episodes_fr_collection.figures])
# Output: [
#     {
#         "geometry": {
#         "dimensions": { "x": 1.8, "y": 3.9, "z": 1.6 },
#         "position": { "x": -3.4, "y": 28.9, "z": -0.7 },
#         "rotation": { "x": 0.0, "y": 0, "z": -0.03 }
#         },
#         "geometryType": "cuboid_3d",
#         "key": "e35386df7c994485ba7186e1a8c67361",
#         "objectKey": "c43ac88f2cb74852817390ca3b749ffd"
#     },
#     {
#         "geometry": {
#         "dimensions": { "x": 1.8, "y": 3.9, "z": 1.6 },
#         "position": { "x": -3.4, "y": 28.9, "z": -0.7 },
#         "rotation": { "x": 0.0, "y": 0, "z": -0.03 }
#         },
#         "geometryType": "cuboid_3d",
#         "key": "1b09a434c20f47faab3f0d7efdb4cbbf",
#         "objectKey": "c43ac88f2cb74852817390ca3b749ffd"
#     }
# ]