---
title: Upload ZOD data
slug: api-guide/upload-zod-data
createdAt: 2024-12-16T14:25:49.794Z
---

This tutorial will guide you through uploading different [scene types](docId\:yUnPNPwUhZlGG9Wb9Qnk8) using the [Zenseact Open Dataset (ZOD)](https://zod.zenseact.com/). The purpose of this page is to show you some of the steps that might be needed to convert recordings into Kognic scenes.

:::ExpandableHeading{isOpen="true"}
## Prerequisites & Dependencies

1\. To follow along in this guide you need to download the data from [Zenseact Open Dataset](https://zod.zenseact.com/download/). The data should be structured like this:

```text
zod
├── sequences
│   ├── 000000
│   ├── 000002
│   ├── ...
└── trainval-sequences-mini.json
```

2\. You will also need to install the ZOD Python package from PyPI, which provides some abstractions for reading the data:

```bash
pip install zod
```

3\. You need to have a Kognic account and the Kognic Python client installed. If you have not done this yet, read the [Quickstart](docId\:b6im5U-kiWn9UkybzJX6D) guide.
:::

This guide follows the process of uploading scenes using ZOD data, using the example code from [the Kognic IO ZOD examples repository](https://github.com/annotell/kognic-io-examples-python/blob/30c725ad38a1e5a163c28f10163022d4d522acc8/examples/zod) which contains the complete source files for all of the snippets in this page. The examples are runnable, if you have the data available and have Kognic authentication set up.

::::Tabs
:::Tab{title="Cameras Sequence"}
Our example code initialises a Kognic IO Client at the top level, then creates the scene from ZOD data for (potentially) multiple scenes at once using a function.

```python
if __name__ == "__main__":
    client = KognicIOClient()

    upload_cameras_sequence_scenes(
        zod_path=Path("/path/to/zod"),  # change me
        zod_version="mini",
        client=client,
        max_nr_scenes=1,
        max_nr_frames=10,
        dryrun=False,
    )
```
:::

:::Tab{title="Lidars and Cameras Sequence"}
This example follows the same broad structure as the cameras-only sequence with the addition of:

- A LiDAR sensor
- A [caliration](docId:4mFC9aTWcxuPfLNE7V1Iz), to allow projection between 2D and 3D [coordinate systems](docId\:XqF6UaQSoFwvAVmtePdEC).
- Conversion of point clouds from ZOD's packed NumPy arrays.
- Conversion of ego poses for each frame.

As before we initialise a Kognic IO Client at the top-level, then create the scene from ZOD data for (potentially) multiple scenes at once using a function.
:::

:::Tab{title="Aggregated Lidars and Cameras Sequence"}
This example follows the same structure as the LiDAR-and-camera sequence example.

[Aggregated scenes](docId\:Wk30FzM6vJvDcTDkX-Mgh) are a special case of LiDAR + camera sequence scenes where the LiDAR data is aggregated across frames into a single pointcloud. This gives a dense, static pointcloud that represents the entire scene across all frames.

Aggregated scenes may be created by providing a pointcloud on every frame and allowing the Kognic platform to handle aggregation, or, they may be pre-aggregated and uploaded by specifying a pointcloud on the first frame, then nothing on subsequent frames.

In the case of ZOD data, we only have per-frame pointclouds, so the example uploads a pointcloud on every frame and leaves aggregation to the platform. As such it is very similar to the LiDAR-and-camera sequence example, except that:

1\. The scene type is different: AggregatedLidarsAndCamerasSequence instead of LidarsAndCamerasSequence.
:::
::::

```python
def convert_scene(zod_sequence: ZodSequence, external_id: str, max_nr_frames: int) -> AggregatedLidarsAndCamerasSequence:
    frames = convert_frames(zod_sequence, max_nr_frames)
    return AggregatedLidarsAndCamerasSequence(external_id=external_id, frames=frames, calibration_id="<to be set later>")
```

2\. The `Frames` are of an aggregated-scene specific type

```python
frames.append(
    ALCSFrame(
        relative_timestamp=ns_to_ms(frame_ts_ns) - start_ts_ms,
        frame_id=str(frame_ts_ns),
        images=[convert_zod_camera_frame_to_image(camera_frame)],
        point_clouds=[point_cloud],
        ego_vehicle_pose=convert_to_ego_vehicle_pose(ego_pose),
        unix_timestamp=frame_ts_ns,
    )
)
```

3\. Ego pose data is required

Otherwise the two approaches are very similar - refer to the *`Lidars and Cameras Sequence`* tab.
