> ## Documentation Index
> Fetch the complete documentation index at: https://docs.encord.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Images & Videos

Once you have imported your [local data](/sdk-documentation/index-sdk/sdk-upload-data#upload-local-data-to-an-existing-folder) or [cloud data](/sdk-documentation/getting-started-sdk/sdk-register-data-aws) into Encord, you can import your labels/annotations for the data.

<Info>You MUST call the [initialise\_labels](/sdk-documentation/sdk-references/objects.ontology_labels_impl#labelrowv2-objects#initialise-labels) function (once per data unit) before you can import your labels/annotations.</Info>

The process to import labels into Encord consists of the following:

1. Import the dependencies.
2. Authenticate your Encord client.
3. Specify the Annotate Project with the data you want to label.
4. Specify the label row you want to import your label to. This specifies the data unit (image, image group, image sequence, video, or DICOM series) you want to add your labels to.
5. Use the [initialise\_labels](/sdk-documentation/sdk-references/objects.ontology_labels_impl#labelrowv2-objects#initialise-labels) function ONCE to prepare the row for your labels.
6. Apply your labels to the label row.
7. Save the label row.

<Note>One label row is equivalent to one data unit. You only need to use the [initialise\_labels](/sdk-documentation/sdk-references/objects.ontology_labels_impl#labelrowv2-objects#initialise-labels) function and save the label row ONCE per data unit, regardless of how many labels are added to the data unit. However, any future changes to a data unit need to be initialized and saved.</Note>

## Object Labels

<AccordionGroup>
  <Accordion title="Bounding Box">
    **Basic**

    This example includes the following:

    * Single image labeling
    * Image Group labeling
    * Image Sequence labeling
    * Video labeling

    **Advanced**

    This example includes the following:

    * Single image labeling
    * Image Group labeling
    * Image Sequence labeling
    * Video labeling
    * Radio button options
    * Checklist options
    * Text input
    * Number input

    **Bounding Box Ontology**

    ![Bounding Box Ontology](https://storage.googleapis.com/docs-media.encord.com/static/img/sdk/labels-bounding-box-cherries.png)

    <CodeGroup>
      ```python Bounding Boxes Images/Videos - Basic expandable theme={"dark"}

      from encord import EncordUserClient, Project
      from encord.objects import Object, ObjectInstance
      from encord.objects.coordinates import BoundingBoxCoordinates

      # User input
      SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"  # Replace with the file path to your SSH private key
      PROJECT_ID = "00000000-0000-0000-0000-000000000000"  # Replace with the unique Project ID
      BUNDLE_SIZE = 10

      # Data unit titles in your Project.
      IMAGE_TITLE = "cherries-001.jpg"
      IMG_GROUP_TITLE = "cherries-ig"
      IMG_SEQUENCE_TITLE = "cherries-is"
      VIDEO_TITLE = "cherries-vid-001.mp4"

      # Authorize connection to Encord
      user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path=SSH_PATH,
          # For US platform users use domain="https://api.us.encord.com"
          domain="https://api.encord.com",
      )

      project: Project = user_client.get_project(PROJECT_ID)

      # Find bounding box object "Cherries" in the ontology.
      ontology_structure = project.ontology_structure
      box_ontology_object: Object = ontology_structure.get_child_by_title(title="Cherries", type_=Object)
      assert box_ontology_object is not None, "Bounding box object 'Cherries' not found in ontology."

      # Initialise label rows
      label_rows = {}
      all_titles = [IMAGE_TITLE, IMG_GROUP_TITLE, IMG_SEQUENCE_TITLE, VIDEO_TITLE]

      with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
          for title in all_titles:
              rows = project.list_label_rows_v2(data_title_eq=title)
              assert isinstance(rows, list), f"Expected list for '{title}', got {type(rows)}"
              if not rows:
                  print(f"Skipping: No label row found for {title}")
                  continue
              lr = rows[0]
              lr.initialise_labels(bundle=bundle)
              assert lr.ontology_structure is not None, f"Ontology not initialized for '{title}'"
              label_rows[title] = lr

      # Coordinates for the bounding box
      box = BoundingBoxCoordinates(height=0.35, width=0.35, top_left_x=0.1, top_left_y=0.1)

      # Create instances and attach to frames
      label_rows_to_save = []

      # 1. One image > annotate frame 0
      image_lr = label_rows.get(IMAGE_TITLE)
      if image_lr is not None:
          inst: ObjectInstance = box_ontology_object.create_instance()
          inst.set_for_frames(coordinates=box, frames=0)
          image_lr.add_object_instance(inst)
          label_rows_to_save.append(image_lr)

      # 2. One image group > annotate frame 0
      img_group_lr = label_rows.get(IMG_GROUP_TITLE)
      if img_group_lr is not None:
          inst: ObjectInstance = box_ontology_object.create_instance()
          inst.set_for_frames(coordinates=box, frames=0)
          img_group_lr.add_object_instance(inst)
          label_rows_to_save.append(img_group_lr)

      # 3. One image sequence > annotate frame 0
      img_sequence_lr = label_rows.get(IMG_SEQUENCE_TITLE)
      if img_sequence_lr is not None:
          inst: ObjectInstance = box_ontology_object.create_instance()
          inst.set_for_frames(coordinates=box, frames=0)
          img_sequence_lr.add_object_instance(inst)
          label_rows_to_save.append(img_sequence_lr)

      # 4. One video > reuse SAME instance across 3 consecutive frames (frames 100, 101, 102)
      video_lr = label_rows.get(VIDEO_TITLE)
      if video_lr is not None:
          inst: ObjectInstance = box_ontology_object.create_instance()
          consecutive_frames = [100, 101, 102]
          for f in consecutive_frames:
              inst.set_for_frames(coordinates=box, frames=f)
          video_lr.add_object_instance(inst)
          label_rows_to_save.append(video_lr)

      # Save the label rows
      with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
          for lr in label_rows_to_save:
              lr.save(bundle=bundle)
              print(f"Saved label row for {lr.data_title}")

      print("Done: created one bounding box on image, image group, image sequence, and 3 video frames.")
      ```

      ```python Bounding Boxes Images/Videos - Advanced expandable theme={"dark"}
      # Import dependencies
      from encord import EncordUserClient, Project
      from encord.objects import ChecklistAttribute, Object, ObjectInstance, Option, RadioAttribute, TextAttribute
      from encord.objects.attributes import NumericAttribute
      from encord.objects.coordinates import BoundingBoxCoordinates

      SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"
      # SSH_PATH = get_ssh_key() # replace it with access key
      PROJECT_ID = "00000000-0000-0000-0000-000000000000"
      BUNDLE_SIZE = 100

      # Create user client using access key
      user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path=SSH_PATH,
          # For US platform users use "https://api.us.encord.com"
          domain="https://api.encord.com",
      )

      # Get project for which labels are to be added
      project: Project = user_client.get_project(PROJECT_ID)

      # Create radio button attribute for cherry type
      ontology_structure = project.ontology_structure

      # Find a bounding box annotation object in the project ontology
      box_ontology_object: Object = ontology_structure.get_child_by_title(title="Cherries", type_=Object)
      assert box_ontology_object is not None, "Bounding box object 'Cherries' not found in ontology."

      # Find radio attribute in the ontology
      cherry_type_radio_attribute = ontology_structure.get_child_by_title(type_=RadioAttribute, title="Type?")
      assert cherry_type_radio_attribute is not None, "Radio attribute 'Type?' not found in ontology."

      # Find number attribute in the ontology
      cherry_quality_number_attribute = ontology_structure.get_child_by_title(type_=NumericAttribute, title="Overall Quality")
      assert cherry_quality_number_attribute is not None, "Number attribute 'Overall Quality' not found in ontology."

      # Create options for the radio buttons
      bing_option = cherry_type_radio_attribute.get_child_by_title(type_=Option, title="Bing")
      king_option = cherry_type_radio_attribute.get_child_by_title(type_=Option, title="King")
      rainier_option = cherry_type_radio_attribute.get_child_by_title(type_=Option, title="Rainier")
      other_cherry_option = cherry_type_radio_attribute.get_child_by_title(type_=Option, title="Other cherry type")

      assert all([bing_option, king_option, rainier_option, other_cherry_option]), (
          "One or more cherry type options are missing."
      )

      # Bing Qualities
      bing_checklist_attribute = ontology_structure.get_child_by_title(type_=ChecklistAttribute, title="Bing Qualities?")
      assert bing_checklist_attribute is not None, "Checklist attribute 'Bing Qualities?' not found."

      bing_plump_option = bing_checklist_attribute.get_child_by_title(type_=Option, title="Plump")
      bing_juicy_option = bing_checklist_attribute.get_child_by_title(type_=Option, title="Juicy")
      bing_large_option = bing_checklist_attribute.get_child_by_title(type_=Option, title="Large")
      assert all([bing_plump_option, bing_juicy_option, bing_large_option]), "One or more Bing quality options are missing."

      # King Qualities
      king_checklist_attribute = ontology_structure.get_child_by_title(type_=ChecklistAttribute, title="King Qualities?")
      assert king_checklist_attribute is not None, "Checklist attribute 'King Qualities?' not found."

      king_plump_option = king_checklist_attribute.get_child_by_title(type_=Option, title="Plump")
      king_juicy_option = king_checklist_attribute.get_child_by_title(type_=Option, title="Juicy")
      king_large_option = king_checklist_attribute.get_child_by_title(type_=Option, title="Large")
      assert all([king_plump_option, king_juicy_option, king_large_option]), "One or more King quality options are missing."

      # Rainier Qualities
      rainier_checklist_attribute = ontology_structure.get_child_by_title(
          type_=ChecklistAttribute, title="Rainier Qualities?"
      )
      assert rainier_checklist_attribute is not None, "Checklist attribute 'Rainier Qualities?' not found."

      rainier_plump_option = rainier_checklist_attribute.get_child_by_title(type_=Option, title="Plump")
      rainier_juicy_option = rainier_checklist_attribute.get_child_by_title(type_=Option, title="Juicy")
      rainier_large_option = rainier_checklist_attribute.get_child_by_title(type_=Option, title="Large")
      assert all([rainier_plump_option, rainier_juicy_option, rainier_large_option]), (
          "One or more Rainier quality options are missing."
      )

      # Other Cherry Types
      other_cherry_option_text_attribute = ontology_structure.get_child_by_title(
          type_=TextAttribute, title="Specify cherry type"
      )
      assert other_cherry_option_text_attribute is not None, "Text attribute 'Specify cherry type' not found in ontology."

      # Dictionary of labels per data unit and per frame with cherry type specified, including quality options
      video_frame_labels = {
          "cherries-001.jpg": {
              0: {
                  "label_ref": "cherry_001",
                  "coordinates": BoundingBoxCoordinates(height=0.4, width=0.4, top_left_x=0.0, top_left_y=0.0),
                  "cherry_type": "Bing",
                  "bing_quality_options": "Plump, Juicy",
                  "cherry_quality": 4
              }
          },
          "cherries-010.jpg": {
              0: [
                  {
                      "label_ref": "cherry_002",
                      "coordinates": BoundingBoxCoordinates(height=0.4, width=0.4, top_left_x=0.0, top_left_y=0.0),
                      "cherry_type": "King",
                      "king_quality_options": "Plump, Juicy, Large",
                      "cherry_quality": 9
                  },
                  {
                      "label_ref": "cherry_003",
                      "coordinates": BoundingBoxCoordinates(height=0.2, width=0.1, top_left_x=0.5, top_left_y=0.0),
                      "cherry_type": "Rainier",
                      "rainier_quality_options": "Plump",
                      "cherry_quality": 5
                  },
                  {
                      "label_ref": "cherry_004",
                      "coordinates": BoundingBoxCoordinates(height=0.2, width=0.1, top_left_x=0.7, top_left_y=0.0),
                      "cherry_type": "Other cherry type",
                      "Specify cherry type": "Morello",
                      "cherry_quality": 3
                  },
              ],
          },
          "cherries-ig": {
              0: {
                  "label_ref": "cherry_005",
                  "coordinates": BoundingBoxCoordinates(height=0.4, width=0.4, top_left_x=0.0, top_left_y=0.0),
                  "cherry_type": "Bing",
                  "bing_quality_options": "Plump, Juicy",
                  "cherry_quality": 7
              },
              2: [
                  {
                      "label_ref": "cherry_006",
                      "coordinates": BoundingBoxCoordinates(height=0.1, width=0.2, top_left_x=0.5, top_left_y=0.0),
                      "cherry_type": "King",
                      "king_quality_options": "Large",
                      "cherry_quality": 6
                  },
                  {
                      "label_ref": "cherry_007",
                      "coordinates": BoundingBoxCoordinates(height=0.1, width=0.2, top_left_x=0.0, top_left_y=0.5),
                      "cherry_type": "Rainier",
                      "rainier_quality_options": "Plump",
                      "cherry_quality": 6
                  },
                  {
                      "label_ref": "cherry_008",
                      "coordinates": BoundingBoxCoordinates(height=0.2, width=0.1, top_left_x=0.8, top_left_y=0.0),
                      "cherry_type": "Other cherry type",
                      "Specify cherry type": "Queen Anne",
                      "cherry_quality": 3
                  },
              ],
          },
          "cherries-is": {
              0: {
                  "label_ref": "cherry_009",
                  "coordinates": BoundingBoxCoordinates(height=0.4, width=0.4, top_left_x=0.0, top_left_y=0.0),
                  "cherry_type": "Bing",
                  "bing_quality_options": "Plump",
                  "cherry_quality": 4
              },
              3: [
                  {
                      "label_ref": "cherry_010",
                      "coordinates": BoundingBoxCoordinates(height=0.4, width=0.4, top_left_x=0.5, top_left_y=0.0),
                      "cherry_type": "King",
                      "king_quality_options": "Plump, Juicy, Large",
                      "cherry_quality": 8
                  },
                  {
                      "label_ref": "cherry_011",
                      "coordinates": BoundingBoxCoordinates(height=0.3, width=0.3, top_left_x=0.0, top_left_y=0.5),
                      "cherry_type": "Rainier",
                      "rainier_quality_options": "Plump",
                  },
                  {
                      "label_ref": "cherry_012",
                      "coordinates": BoundingBoxCoordinates(height=0.2, width=0.1, top_left_x=0.9, top_left_y=0.0),
                      "cherry_type": "Other cherry type",
                      "Specify cherry type": "Lambert",
                      "cherry_quality": 4
                  },
              ],
          },
          "cherries-vid-001.mp4": {
              103: [
                  {
                      "label_ref": "cherry_013",
                      "coordinates": BoundingBoxCoordinates(height=0.5, width=0.5, top_left_x=0.0, top_left_y=0.0),
                      "cherry_type": "Rainier",
                      "rainier_quality_options": "Plump",
                       "cherry_quality": 5
                  },
                  {
                      "label_ref": "cherry_014",
                      "coordinates": BoundingBoxCoordinates(height=0.2, width=0.2, top_left_x=0.6, top_left_y=0.0),
                      "cherry_type": "Bing",
                      "bing_quality_options": "Plump, Juicy, Large",
                      "cherry_quality": 9
                  },
                  {
                      "label_ref": "cherry_015",
                      "coordinates": BoundingBoxCoordinates(height=0.2, width=0.1, top_left_x=0.8, top_left_y=0.6),
                      "cherry_type": "Other cherry type",
                      "Specify cherry type": "Sweetheart",
                      "cherry_quality": 7
                  },
              ],
              104: [
                  {
                      "label_ref": "cherry_016",
                      "coordinates": BoundingBoxCoordinates(height=0.5, width=0.5, top_left_x=0.0, top_left_y=0.0),
                      "cherry_type": "Rainier",
                      "rainier_quality_options": "Plump",
                      "cherry_quality": 7
                  },
                  {
                      "label_ref": "cherry_014",
                      "coordinates": BoundingBoxCoordinates(height=0.2, width=0.2, top_left_x=0.6, top_left_y=0.0),
                      "cherry_type": "Bing",
                      "bing_quality_options": "Plump, Juicy, Large",
                      "cherry_quality": 9
                  },
                  {
                      "label_ref": "cherry_017",
                      "coordinates": BoundingBoxCoordinates(height=0.2, width=0.1, top_left_x=0.8, top_left_y=0.6),
                      "cherry_type": "Other cherry type",
                      "Specify cherry type": "Sweetheart",
                      "cherry_quality": 2
                  },
              ],
              105: [
                  {
                      "label_ref": "cherry_016",
                      "coordinates": BoundingBoxCoordinates(height=0.5, width=0.5, top_left_x=0.0, top_left_y=0.0),
                      "cherry_type": "Rainier",
                      "rainier_quality_options": "Plump",
                       "cherry_quality": 7
                  },
                  {
                      "label_ref": "cherry_014",
                      "coordinates": BoundingBoxCoordinates(height=0.2, width=0.2, top_left_x=0.6, top_left_y=0.0),
                      "cherry_type": "Bing",
                      "bing_quality_options": "Plump, Juicy, Large",
                      "cherry_quality": 9
                  },
                  {
                      "label_ref": "cherry_017",
                      "coordinates": BoundingBoxCoordinates(height=0.2, width=0.1, top_left_x=0.8, top_left_y=0.6),
                      "cherry_type": "Other cherry type",
                      "Specify cherry type": "Sweetheart",
                      "cherry_quality": 3
                  },
              ],
          },
      }

      # Cache initialized label rows
      label_row_map = {}

      # Step 1: Initialize all label rows using a bundle
      with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
          for data_unit in video_frame_labels.keys():
              label_rows = project.list_label_rows_v2(data_title_eq=data_unit)
              assert isinstance(label_rows, list), f"Expected list of label rows for '{data_unit}', got {type(label_rows)}"

              if not label_rows:
                  print(f"Skipping: No label row found for {data_unit}")
                  continue

              label_row = label_rows[0]
              label_row.initialise_labels(bundle=bundle)
              assert label_row.ontology_structure is not None, f"Ontology not initialized for label row: {data_unit}"

              label_row_map[data_unit] = label_row  # Cache initialized label row for later use

      # Step 2: Process all frames/annotations and prepare label rows to save
      label_rows_to_save = []

      for data_unit, frame_coordinates in video_frame_labels.items():
          label_row = label_row_map.get(data_unit)
          if not label_row:
              print(f"Skipping: No initialized label row found for {data_unit}")
              continue

          object_instances_by_label_ref = {}

          # Loop through the frames for the current data unit
          for frame_number, items in frame_coordinates.items():
              assert isinstance(frame_number, int), f"Frame number must be int, got {type(frame_number)}"
              if not isinstance(items, list):
                  items = [items]

              for item in items:
                  label_ref = item["label_ref"]
                  coord = item["coordinates"]
                  cherry_type = item["cherry_type"]
                  cherry_quality = item["cherry_quality"]

                  assert cherry_type in {
                      "Bing",
                      "King",
                      "Rainier",
                      "Other cherry type",
                  }, f"Unexpected cherry type '{cherry_type}' in data unit '{data_unit}'"

                  # Check if label_ref already exists for reusability
                  if label_ref not in object_instances_by_label_ref:
                      box_object_instance: ObjectInstance = box_ontology_object.create_instance()
                      assert box_object_instance is not None, "Failed to create ObjectInstance"

                      object_instances_by_label_ref[label_ref] = box_object_instance
                      checklist_attribute = None

                      # Set cherry quality attribute 
                      box_object_instance.set_answer(attribute=cherry_quality_number_attribute, answer=cherry_quality)

                      # Set cherry type attribute
                      if cherry_type == "Bing":
                          assert bing_option is not None, "Missing 'bing_option'"
                          box_object_instance.set_answer(attribute=cherry_type_radio_attribute, answer=bing_option)
                          checklist_attribute = bing_checklist_attribute
                      elif cherry_type == "King":
                          assert king_option is not None, "Missing 'king_option'"
                          box_object_instance.set_answer(attribute=cherry_type_radio_attribute, answer=king_option)
                          checklist_attribute = king_checklist_attribute
                      elif cherry_type == "Rainier":
                          assert rainier_option is not None, "Missing 'rainier_option'"
                          box_object_instance.set_answer(attribute=cherry_type_radio_attribute, answer=rainier_option)
                          checklist_attribute = rainier_checklist_attribute
                      elif cherry_type == "Other cherry type":
                          assert other_cherry_option is not None, "Missing 'other_cherry_option'"
                          box_object_instance.set_answer(attribute=cherry_type_radio_attribute, answer=other_cherry_option)
                          text_answer = item.get("Specify cherry type", "")
                          assert isinstance(text_answer, str), "'Specify cherry type' must be a string"
                          box_object_instance.set_answer(attribute=other_cherry_option_text_attribute, answer=text_answer)

                      # Set checklist attributes
                      checklist_answers = []
                      quality_key = f"{cherry_type.lower()}_quality_options"
                      quality_options = item.get(quality_key, "").split(", ")

                      for quality in quality_options:
                          if quality == "Plump":
                              checklist_answers.append(
                                  bing_plump_option
                                  if cherry_type == "Bing"
                                  else king_plump_option
                                  if cherry_type == "King"
                                  else rainier_plump_option
                              )
                          elif quality == "Juicy":
                              checklist_answers.append(
                                  bing_juicy_option
                                  if cherry_type == "Bing"
                                  else king_juicy_option
                                  if cherry_type == "King"
                                  else rainier_juicy_option
                              )
                          elif quality == "Large":
                              checklist_answers.append(
                                  bing_large_option
                                  if cherry_type == "Bing"
                                  else king_large_option
                                  if cherry_type == "King"
                                  else rainier_large_option
                              )

                      if checklist_attribute and checklist_answers:
                          box_object_instance.set_answer(
                              attribute=checklist_attribute, answer=checklist_answers, overwrite=True
                          )

                  else:
                      # Reuse existing instance across frames
                      box_object_instance = object_instances_by_label_ref[label_ref]

                  # Assign the object to the frame and track it
                  box_object_instance.set_for_frames(coordinates=coord, frames=frame_number)

          # Add object instances to label_row **only if they have frames assigned**
          for box_object_instance in object_instances_by_label_ref.values():
              assert isinstance(box_object_instance, ObjectInstance), "Expected ObjectInstance type"
              if box_object_instance.get_annotation_frames():  # Ensures it has at least one frame
                  label_row.add_object_instance(box_object_instance)

          label_rows_to_save.append(label_row)

      # Step 3: Save all label rows using a bundle
      with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
          for label_row in label_rows_to_save:
              assert label_row is not None, "Trying to save a None label row"
              label_row.save(bundle=bundle)
              print(f"Saved label row for {label_row.data_title}")

      print("Labels with cherry type radio buttons, checklist attributes, text labels, and number attributes added for all data units.")
      ```
    </CodeGroup>
  </Accordion>
</AccordionGroup>

<AccordionGroup>
  <Accordion title="Rotatable Bounding Box">
    **Basic**

    This example includes the following:

    * Single image labeling
    * Image Group labeling
    * Image Sequence labeling
    * Video labeling

    **Advanced**

    This example includes the following:

    * Single image labeling
    * Image Group labeling
    * Image Sequence labeling
    * Video labeling
    * Radio button options
    * Checklist options
    * Text input
    * Number input

    **Rotatable Bounding Box Ontology**

    ![Rotatable Bounding Box Ontology](https://storage.googleapis.com/docs-media.encord.com/static/img/sdk/labels-rbb-persimmons.png)

    <CodeGroup>
      ```python Rotatable Bounding Boxes Images/Videos - Basic expandable theme={"dark"}

      from encord import EncordUserClient, Project
      from encord.objects import Object, ObjectInstance
      from encord.objects.coordinates import RotatableBoundingBoxCoordinates

      # User input
      SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"  # Replace with the file path to your SSH private key
      PROJECT_ID = "00000000-0000-0000-0000-000000000000"  # Replace with the unique Project ID
      BUNDLE_SIZE = 10

      # Data unit titles in your project
      IMAGE_TITLE = "persimmons-001.jpg"
      IMG_GROUP_TITLE = "persimmons-ig"
      IMG_SEQUENCE_TITLE = "persimmons-is"
      VIDEO_TITLE = "persimmons-vid-001.mp4"

      # Authorize connection to Encord
      user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path=SSH_PATH,
          # For US platform users use domain="https://api.us.encord.com"
          domain="https://api.encord.com",
      )

      project: Project = user_client.get_project(PROJECT_ID)

      # Find rotatable bbox object "Persimmons" in the ontology
      ontology_structure = project.ontology_structure
      rbbox_ontology_object: Object = ontology_structure.get_child_by_title(title="Persimmons", type_=Object)
      assert rbbox_ontology_object is not None, "Rotatable bbox object 'Persimmons' not found in ontology."

      # Initialise label rows
      label_rows = {}
      all_titles = [IMAGE_TITLE, IMG_GROUP_TITLE, IMG_SEQUENCE_TITLE, VIDEO_TITLE]

      with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
          for title in all_titles:
              rows = project.list_label_rows_v2(data_title_eq=title)
              assert isinstance(rows, list), f"Expected list for '{title}', got {type(rows)}"
              if not rows:
                  print(f"Skipping: No label row found for {title}")
                  continue
              lr = rows[0]
              lr.initialise_labels(bundle=bundle)
              assert lr.ontology_structure is not None, f"Ontology not initialized for '{title}'"
              label_rows[title] = lr

      # Coordinates for the rotatable bounding box
      rbbox = RotatableBoundingBoxCoordinates(height=0.35, width=0.35, top_left_x=0.1, top_left_y=0.1, theta=25)

      # Create instances and attach to frames
      label_rows_to_save = []

      # 1. One image > annotate frame 0
      image_lr = label_rows.get(IMAGE_TITLE)
      if image_lr is not None:
          inst: ObjectInstance = rbbox_ontology_object.create_instance()
          inst.set_for_frames(coordinates=rbbox, frames=0)
          image_lr.add_object_instance(inst)
          label_rows_to_save.append(image_lr)

      # 2. One image group > annotate frame 0
      img_group_lr = label_rows.get(IMG_GROUP_TITLE)
      if img_group_lr is not None:
          inst: ObjectInstance = rbbox_ontology_object.create_instance()
          inst.set_for_frames(coordinates=rbbox, frames=0)
          img_group_lr.add_object_instance(inst)
          label_rows_to_save.append(img_group_lr)

      # 3. One image sequence > annotate frame 0
      img_sequence_lr = label_rows.get(IMG_SEQUENCE_TITLE)
      if img_sequence_lr is not None:
          inst: ObjectInstance = rbbox_ontology_object.create_instance()
          inst.set_for_frames(coordinates=rbbox, frames=0)
          img_sequence_lr.add_object_instance(inst)
          label_rows_to_save.append(img_sequence_lr)

      # 4 One video > reuse SAME instance across 3 consecutive frames (frames 100, 101, 102)
      video_lr = label_rows.get(VIDEO_TITLE)
      if video_lr is not None:
          inst: ObjectInstance = rbbox_ontology_object.create_instance()
          consecutive_frames = [100, 101, 102]
          for f in consecutive_frames:
              inst.set_for_frames(coordinates=rbbox, frames=f)
          video_lr.add_object_instance(inst)
          label_rows_to_save.append(video_lr)

      # Save label rows
      with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
          for lr in label_rows_to_save:
              lr.save(bundle=bundle)
              print(f"Saved label row for {lr.data_title}")

      print("Done: created one rotatable bounding box on image, image group, image sequence, and 3 video frames.")
      ```

      ```python Rotatable Bounding Boxes Images/Videos - Advanced expandable theme={"dark"}

      # Import dependencies
      from encord import EncordUserClient, Project
      from encord.objects import ChecklistAttribute, Object, ObjectInstance, Option, RadioAttribute, TextAttribute
      from encord.objects.coordinates import RotatableBoundingBoxCoordinates
      from encord.objects.attributes import NumericAttribute

      # User input
      SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"
      PROJECT_ID = "00000000-0000-0000-0000-000000000000"
      BUNDLE_SIZE = 100

      # Create user client using access key
      user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path=SSH_PATH,
          # For US platform users use "https://api.us.encord.com"
          domain="https://api.encord.com",
      )

      # Get project for which labels are to be added
      project: Project = user_client.get_project(PROJECT_ID)
      assert project is not None, "Project not found — check PROJECT_ID"

      # Create radio button attribute for persimmon type
      ontology_structure = project.ontology_structure
      assert ontology_structure is not None, "Ontology structure is missing from the project"

      # Find a bounding box annotation object in the project ontology
      rbbox_ontology_object: Object = ontology_structure.get_child_by_title(title="Persimmons", type_=Object)
      assert rbbox_ontology_object is not None, "Object 'Persimmons' not found in ontology"

      # Get radio attribute for persimmon type
      persimmon_type_radio_attribute = ontology_structure.get_child_by_title(type_=RadioAttribute, title="Type?")
      assert persimmon_type_radio_attribute is not None, "Radio attribute 'Type?' not found"

      # Create radio options
      hachiya_option = persimmon_type_radio_attribute.get_child_by_title(type_=Option, title="Hachiya")
      assert hachiya_option is not None, "Option 'Hachiya' not found under 'Type?'"

      fuyu_option = persimmon_type_radio_attribute.get_child_by_title(type_=Option, title="Fuyu")
      assert fuyu_option is not None, "Option 'Fuyu' not found under 'Type?'"

      rjb_option = persimmon_type_radio_attribute.get_child_by_title(type_=Option, title="Rojo Brilliante")
      assert rjb_option is not None, "Option 'Rojo Brilliante' not found under 'Type?'"

      other_persimmon_option = persimmon_type_radio_attribute.get_child_by_title(type_=Option, title="Other persimmon type")
      assert other_persimmon_option is not None, "Option 'Other persimmon type' not found under 'Type?'"

      # Hachiya Qualities
      hachiya_checklist_attribute = ontology_structure.get_child_by_title(
          type_=ChecklistAttribute, title="Hachiya Qualities?"
      )
      assert hachiya_checklist_attribute is not None, "Checklist attribute 'Hachiya Qualities?' not found"

      hachiya_plump_option = hachiya_checklist_attribute.get_child_by_title(type_=Option, title="Plump")
      assert hachiya_plump_option is not None, "Option 'Plump' not found under 'Hachiya Qualities?'"

      hachiya_juicy_option = hachiya_checklist_attribute.get_child_by_title(type_=Option, title="Juicy")
      assert hachiya_juicy_option is not None, "Option 'Juicy' not found under 'Hachiya Qualities?'"

      hachiya_large_option = hachiya_checklist_attribute.get_child_by_title(type_=Option, title="Large")
      assert hachiya_large_option is not None, "Option 'Large' not found under 'Hachiya Qualities?'"

      # Fuyu Qualities
      fuyu_checklist_attribute = ontology_structure.get_child_by_title(type_=ChecklistAttribute, title="Fuyu Qualities?")
      assert fuyu_checklist_attribute is not None, "Checklist attribute 'Fuyu Qualities?' not found"

      fuyu_plump_option = fuyu_checklist_attribute.get_child_by_title(type_=Option, title="Plump")
      assert fuyu_plump_option is not None, "Option 'Plump' not found under 'Fuyu Qualities?'"

      fuyu_juicy_option = fuyu_checklist_attribute.get_child_by_title(type_=Option, title="Juicy")
      assert fuyu_juicy_option is not None, "Option 'Juicy' not found under 'Fuyu Qualities?'"

      fuyu_large_option = fuyu_checklist_attribute.get_child_by_title(type_=Option, title="Large")
      assert fuyu_large_option is not None, "Option 'Large' not found under 'Fuyu Qualities?'"

      # Rojo Brilliante Qualities
      rjb_checklist_attribute = ontology_structure.get_child_by_title(
          type_=ChecklistAttribute, title="Rojo Brilliante Qualities?"
      )
      assert rjb_checklist_attribute is not None, "Checklist attribute 'Rojo Brilliante Qualities?' not found"

      rjb_plump_option = rjb_checklist_attribute.get_child_by_title(type_=Option, title="Plump")
      assert rjb_plump_option is not None, "Option 'Plump' not found under 'Rojo Brilliante Qualities?'"

      rjb_juicy_option = rjb_checklist_attribute.get_child_by_title(type_=Option, title="Juicy")
      assert rjb_juicy_option is not None, "Option 'Juicy' not found under 'Rojo Brilliante Qualities?'"

      rjb_large_option = rjb_checklist_attribute.get_child_by_title(type_=Option, title="Large")
      assert rjb_large_option is not None, "Option 'Large' not found under 'Rojo Brilliante Qualities?'"

      # Other persimmon type text input
      other_persimmon_option_text_attribute = ontology_structure.get_child_by_title(
          type_=TextAttribute, title="Specify persimmon type"
      )
      assert other_persimmon_option_text_attribute is not None, "Text attribute 'Specify persimmon type' not found"

      # Find number attribute in the ontology
      quality_number_attribute = ontology_structure.get_child_by_title(type_=NumericAttribute, title="Overall Quality")
      assert quality_number_attribute is not None, "Number attribute 'Overall Quality' not found in ontology."

      # Dictionary of labels per data unit and per frame with persimmon type specified, including quality options
      video_frame_labels = {
          "persimmons-001.jpg": {
              0: {
                  "label_ref": "persimmon_001",
                  "coordinates": RotatableBoundingBoxCoordinates(
                      height=0.4, width=0.4, top_left_x=0.05, top_left_y=0.55, theta=23
                  ),
                  "persimmon_type": "Rojo Brilliante",
                  "rjb_quality_options": "Plump, Juicy",
                  "quality_number": 6
              },
          },
          "persimmons-010.jpg": {
              0: [
                  {
                      "label_ref": "persimmon_002",
                      "coordinates": RotatableBoundingBoxCoordinates(
                          height=0.4, width=0.4, top_left_x=0.05, top_left_y=0.55, theta=23
                      ),
                      "persimmon_type": "Fuyu",
                      "fuyu_quality_options": "Plump, Juicy, Large",
                      "quality_number": 9
                  },
                  {
                      "label_ref": "persimmon_003",
                      "coordinates": RotatableBoundingBoxCoordinates(
                          height=0.2, width=0.1, top_left_x=0.2, top_left_y=0.2, theta=25
                      ),
                      "persimmon_type": "Rojo Brilliante",
                      "rjb_quality_options": "Plump",
                      "quality_number": 5
                  },
                  {
                      "label_ref": "persimmon_004",
                      "coordinates": RotatableBoundingBoxCoordinates(
                          height=0.2, width=0.1, top_left_x=0.3, top_left_y=0.3, theta=27
                      ),
                      "persimmon_type": "Other persimmon type",
                      "Specify persimmon type": "Triumph",
                      "quality_number": 4
                  },
              ],
          },
          "persimmons-ig": {
              0: {
                  "label_ref": "persimmon_005",
                  "coordinates": RotatableBoundingBoxCoordinates(
                      height=0.4, width=0.4, top_left_x=0.05, top_left_y=0.55, theta=23
                  ),
                  "persimmon_type": "Hachiya",
                  "hachiya_quality_options": "Plump, Juicy",
                  "quality_number": 7
              },
              2: [
                  {
                      "label_ref": "persimmon_006",
                      "coordinates": RotatableBoundingBoxCoordinates(
                          height=0.1, width=0.2, top_left_x=0.2, top_left_y=0.2, theta=23
                      ),
                      "persimmon_type": "Fuyu",
                      "fuyu_quality_options": "Large",
                      "quality_number": 8
                  },
                  {
                      "label_ref": "persimmon_007",
                      "coordinates": RotatableBoundingBoxCoordinates(
                          height=0.1, width=0.2, top_left_x=0.4, top_left_y=0.2, theta=127
                      ),
                      "persimmon_type": "Rojo Brilliante",
                      "rjb_quality_options": "Plump",
                      "quality_number": 6
                  },
                  {
                      "label_ref": "persimmon_008",
                      "coordinates": RotatableBoundingBoxCoordinates(
                          height=0.2, width=0.1, top_left_x=0.6, top_left_y=0.3, theta=137
                      ),
                      "persimmon_type": "Other persimmon type",
                      "Specify persimmon type": "Hiro",
                      "quality_number": 6
                  },
              ],
          },
          "persimmons-is": {
              0: {
                  "label_ref": "persimmon_009",
                  "coordinates": RotatableBoundingBoxCoordinates(
                      height=0.4, width=0.4, top_left_x=0.05, top_left_y=0.55, theta=23
                  ),
                  "persimmon_type": "Hachiya",
                  "hachiya_quality_options": "Plump",
                  "quality_number": 7
              },
              3: [
                  {
                      "label_ref": "persimmon_010",
                      "coordinates": RotatableBoundingBoxCoordinates(
                          height=0.4, width=0.4, top_left_x=0.05, top_left_y=0.05, theta=23
                      ),
                      "persimmon_type": "Fuyu",
                      "fuyu_quality_options": "Plump, Juicy, Large",
                      "quality_number": 9
                  },
                  {
                      "label_ref": "persimmon_011",
                      "coordinates": RotatableBoundingBoxCoordinates(
                          height=0.3, width=0.3, top_left_x=0.5, top_left_y=0.05, theta=23
                      ),
                      "persimmon_type": "Rojo Brilliante",
                      "rjb_quality_options": "Plump, Juicy",
                      "quality_number": 9
                  },
                  {
                      "label_ref": "persimmon_012",
                      "coordinates": RotatableBoundingBoxCoordinates(
                          height=0.2, width=0.1, top_left_x=0.7, top_left_y=0.05, theta=23
                      ),
                      "persimmon_type": "Other persimmon type",
                      "Specify persimmon type": "Maru",
                      "quality_number": 8
                  },
              ],
          },
          "persimmons-vid-001.mp4": {
              103: [
                  {
                      "label_ref": "persimmon_013",
                      "coordinates": RotatableBoundingBoxCoordinates(
                          height=0.5, width=0.5, top_left_x=0.05, top_left_y=0.55, theta=23
                      ),
                      "persimmon_type": "Rojo Brilliante",
                      "rjb_quality_options": "Plump",
                      "quality_number": 7
                  },
                  {
                      "label_ref": "persimmon_014",
                      "coordinates": RotatableBoundingBoxCoordinates(
                          height=0.2, width=0.2, top_left_x=0.3, top_left_y=0.2, theta=23
                      ),
                      "persimmon_type": "Hachiya",
                      "hachiya_quality_options": "Plump, Juicy, Large",
                      "quality_number": 9
                  },
                  {
                      "label_ref": "persimmon_015",
                      "coordinates": RotatableBoundingBoxCoordinates(
                          height=0.2, width=0.1, top_left_x=0.6, top_left_y=0.2, theta=23
                      ),
                      "persimmon_type": "Other persimmon type",
                      "Specify persimmon type": "Triumph",
                      "quality_number": 2
                  },
              ],
              104: [
                  {
                      "label_ref": "persimmon_016",
                      "coordinates": RotatableBoundingBoxCoordinates(
                          height=0.5, width=0.5, top_left_x=0.05, top_left_y=0.55, theta=23
                      ),
                      "persimmon_type": "Rojo Brilliante",
                      "rjb_quality_options": "Plump",
                      "quality_number": 5
                  },
                  {
                      "label_ref": "persimmon_014",
                      "coordinates": RotatableBoundingBoxCoordinates(
                          height=0.2, width=0.2, top_left_x=0.3, top_left_y=0.2, theta=23
                      ),
                      "persimmon_type": "Hachiya",
                      "hachiya_quality_options": "Plump, Juicy, Large",
                      "quality_number": 9
                  },
                  {
                      "label_ref": "persimmon_017",
                      "coordinates": RotatableBoundingBoxCoordinates(
                          height=0.2, width=0.1, top_left_x=0.6, top_left_y=0.2, theta=23
                      ),
                      "persimmon_type": "Other persimmon type",
                      "Specify persimmon type": "Hiro",
                      "quality_number": 4
                  },
              ],
              105: [
                  {
                      "label_ref": "persimmon_016",
                      "coordinates": RotatableBoundingBoxCoordinates(
                          height=0.5, width=0.5, top_left_x=0.05, top_left_y=0.55, theta=23
                      ),
                      "persimmon_type": "Rojo Brilliante",
                      "rjb_quality_options": "Plump",
                      "quality_number": 7
                  },
                  {
                      "label_ref": "persimmon_014",
                      "coordinates": RotatableBoundingBoxCoordinates(
                          height=0.2, width=0.2, top_left_x=0.3, top_left_y=0.2, theta=23
                      ),
                      "persimmon_type": "Hachiya",
                      "hachiya_quality_options": "Plump, Juicy, Large",
                      "quality_number": 8
                  },
                  {
                      "label_ref": "persimmon_017",
                      "coordinates": RotatableBoundingBoxCoordinates(
                          height=0.2, width=0.1, top_left_x=0.6, top_left_y=0.2, theta=23
                      ),
                      "persimmon_type": "Other persimmon type",
                      "Specify persimmon type": "Maru",
                      "quality_number": 5
                  },
              ],
          },
      }

      # Cache label rows after initialization
      label_row_map = {}

      # Step 1: Initialize all label rows with a bundle
      with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
          for data_unit in video_frame_labels.keys():
              label_rows = project.list_label_rows_v2(data_title_eq=data_unit)
              assert isinstance(label_rows, list), f"Expected list of label rows for '{data_unit}', got {type(label_rows)}"
              assert label_rows, f"No label row found for {data_unit}"

              label_row = label_rows[0]
              assert label_row is not None, f"Label row is None for {data_unit}"

              label_row.initialise_labels(bundle=bundle)
              assert label_row.ontology_structure is not None, f"Ontology not initialized for label row: {data_unit}"

              label_row_map[data_unit] = label_row  # Cache it for processing later

      # Step 2: Process labels and collect label rows to save
      label_rows_to_save = []

      for data_unit, frame_coordinates in video_frame_labels.items():
          label_row = label_row_map.get(data_unit)
          assert label_row is not None, f"Missing initialized label row for {data_unit}"

          object_instances_by_label_ref = {}

          for frame_number, items in frame_coordinates.items():
              assert isinstance(frame_number, int), f"Frame number must be int, got {type(frame_number)}"

              if not isinstance(items, list):
                  items = [items]

              for item in items:
                  label_ref = item["label_ref"]
                  coord = item["coordinates"]
                  persimmon_type = item["persimmon_type"]
                  quality_number = item["quality_number"]

                  assert persimmon_type in {
                      "Hachiya",
                      "Fuyu",
                      "Rojo Brilliante",
                      "Other persimmon type",
                  }, f"Unexpected persimmon type '{persimmon_type}' in {data_unit}"

                  if label_ref not in object_instances_by_label_ref:
                      rbbox_object_instance: ObjectInstance = rbbox_ontology_object.create_instance()
                      assert rbbox_object_instance is not None, f"Failed to create ObjectInstance for {label_ref}"

                      # Set quality number attribute 
                      rbbox_object_instance.set_answer(attribute=quality_number_attribute, answer=quality_number)

                      checklist_attribute = None
                      quality_options = []

                      # Set persimmon type and checklist attributes
                      if persimmon_type == "Hachiya":
                          assert hachiya_option is not None, "Missing 'hachiya_option'"
                          rbbox_object_instance.set_answer(attribute=persimmon_type_radio_attribute, answer=hachiya_option)
                          checklist_attribute = hachiya_checklist_attribute
                          quality_options = item.get("hachiya_quality_options", "").split(", ")
                      elif persimmon_type == "Fuyu":
                          assert fuyu_option is not None, "Missing 'fuyu_option'"
                          rbbox_object_instance.set_answer(attribute=persimmon_type_radio_attribute, answer=fuyu_option)
                          checklist_attribute = fuyu_checklist_attribute
                          quality_options = item.get("fuyu_quality_options", "").split(", ")
                      elif persimmon_type == "Rojo Brilliante":
                          assert rjb_option is not None, "Missing 'rjb_option'"
                          rbbox_object_instance.set_answer(attribute=persimmon_type_radio_attribute, answer=rjb_option)
                          checklist_attribute = rjb_checklist_attribute
                          quality_options = item.get("rjb_quality_options", "").split(", ")
                      elif persimmon_type == "Other persimmon type":
                          assert other_persimmon_option is not None, "Missing 'other_persimmon_option'"
                          rbbox_object_instance.set_answer(
                              attribute=persimmon_type_radio_attribute, answer=other_persimmon_option
                          )
                          text_answer = item.get("Specify persimmon type", "")
                          assert isinstance(text_answer, str), "'Specify persimmon type' must be a string"
                          rbbox_object_instance.set_answer(
                              attribute=other_persimmon_option_text_attribute, answer=text_answer
                          )
                          quality_options = []

                      # Set checklist answers based on quality options
                      checklist_answers = []
                      for quality in quality_options:
                          option = None
                          if quality == "Plump":
                              option = (
                                  hachiya_plump_option
                                  if persimmon_type == "Hachiya"
                                  else fuyu_plump_option
                                  if persimmon_type == "Fuyu"
                                  else rjb_plump_option
                                  if persimmon_type == "Rojo Brilliante"
                                  else None
                              )
                          elif quality == "Juicy":
                              option = (
                                  hachiya_juicy_option
                                  if persimmon_type == "Hachiya"
                                  else fuyu_juicy_option
                                  if persimmon_type == "Fuyu"
                                  else rjb_juicy_option
                                  if persimmon_type == "Rojo Brilliante"
                                  else None
                              )
                          elif quality == "Large":
                              option = (
                                  hachiya_large_option
                                  if persimmon_type == "Hachiya"
                                  else fuyu_large_option
                                  if persimmon_type == "Fuyu"
                                  else rjb_large_option
                                  if persimmon_type == "Rojo Brilliante"
                                  else None
                              )

                          if option:
                              checklist_answers.append(option)
                          else:
                              assert persimmon_type == "Other persimmon type", (
                                  f"Invalid quality '{quality}' for persimmon type '{persimmon_type}'"
                              )

                      if checklist_attribute and checklist_answers:
                          rbbox_object_instance.set_answer(
                              attribute=checklist_attribute, answer=checklist_answers, overwrite=True
                          )

                      object_instances_by_label_ref[label_ref] = rbbox_object_instance

                  else:
                      rbbox_object_instance = object_instances_by_label_ref[label_ref]

                  # Assign coordinates for this frame
                  rbbox_object_instance.set_for_frames(coordinates=coord, frames=frame_number)

          # Add object instances to label_row **only if they have frames assigned**
          for rbbox_object_instance in object_instances_by_label_ref.values():
              assert isinstance(rbbox_object_instance, ObjectInstance), "Expected ObjectInstance type"
              if rbbox_object_instance.get_annotation_frames():
                  label_row.add_object_instance(rbbox_object_instance)

          # Collect for saving in the next bundle
          label_rows_to_save.append(label_row)

      # Step 3: Save all label rows with a bundle
      with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
          for label_row in label_rows_to_save:
              assert label_row is not None, "Trying to save a None label row"
              label_row.save(bundle=bundle)
              print(f"Saved label row for {label_row.data_title}")

      print("Labels with persimmon type radio buttons, checklist attributes, number attributes, and text labels added for all data units.")

      ```
    </CodeGroup>
  </Accordion>
</AccordionGroup>

<AccordionGroup>
  <Accordion title="Polygons (Advanced)">
    Polygons can have simple and complex shapes, including being enclosed in one another, and encompassing separate regions. In each case the polygon's coordinates are arranged in a different way.

    **Basic**

    This example includes the following:

    * Single image labeling
    * Image Group labeling
    * Image Sequence labeling
    * Video labeling

    **Advanced**

    This example includes the following:

    * Single image labeling
    * Image Group labeling
    * Image Sequence labeling
    * Video labeling
    * Radio button options
    * Checklist options
    * Text input
    * Number input

    **Polygon Coordinates**

    Specifying coordinates for polygons uses this format:

    <CodeGroup>
      ```python Simple theme={"dark"}

      PolygonCoordinates(polygons=[[[PointCoordinate(x1, y1), PointCoordinate(x2, y2),...]]]

      ```

      ```python Donut theme={"dark"}

      PolygonCoordinates(polygons=
      [
          [
              [PointCoordinate(x1, y1), PointCoordinate(x2, y2),...], # Outer ring
              [PointCoordinate(x1, y1), PointCoordinate(x2, y2),...], # Inner ring
          ]
      ]

      ```

      ```python Multiple Polygons theme={"dark"}

      PolygonCoordinates(polygons=
      [
          [
              [PointCoordinate(x1, y1), PointCoordinate(x2, y2),...], # Polygon 1
          ],
          [
              [PointCoordinate(x1, y1), PointCoordinate(x2, y2),...], # Polygon 2
          ],
          [
              [PointCoordinate(x1, y1), PointCoordinate(x2, y2),...], # Polygon 3
          ],

      ]

      ```

      ```python Donut with Object Inside theme={"dark"}

      PolygonCoordinates(polygons=
      [
          [
              [PointCoordinate(x1, y1), PointCoordinate(x2, y2),...], # Outer ring
              [PointCoordinate(x1, y1), PointCoordinate(x2, y2),...], # Inner ring
          ],
          [
              [PointCoordinate(x1, y1), PointCoordinate(x2, y2),...], # Polygon inside
          ],

      ]

      ```
    </CodeGroup>

    **Simple Polygon**

    Import a simple polygon using the recommended method.

    <div class="flex justify-center">
      <img src="https://storage.googleapis.com/docs-media.encord.com/static/img/polygon2.png" />
    </div>

    **Donut**

    Import a complex polygon with a hole in it.

    <div class="flex justify-center">
      <img src="https://storage.googleapis.com/docs-media.encord.com/static/img/polygon3.png" />
    </div>

    **Multiple Polygons**

    Import a complex polygon that is in multiple parts.

    <div class="flex justify-center">
      <img src="https://storage.googleapis.com/docs-media.encord.com/static/img/polygon 4.png" />
    </div>

    **Donut with Object Inside**

    Imports a complex polygon that has a hole in it with another polygon inside.

    <div class="flex justify-center">
      <img src="https://storage.googleapis.com/docs-media.encord.com/static/img/polygon5.png" />
    </div>

    **Polygons Ontology**

    This ontology applies for all polygon shapes (simple, donut, multiple polygons, donut with object inside).

    ![Polygons Ontology](https://storage.googleapis.com/docs-media.encord.com/static/img/sdk/labels-polygons-blueberries.png)

    <CodeGroup title="Complex Polygons - Simple">
      ```python Simple - Basic expandable theme={"dark"}

      from encord import EncordUserClient, Project
      from encord.objects import Object, ObjectInstance
      from encord.objects.coordinates import PointCoordinate, PolygonCoordinates

      # User input
      SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"  # Replace with the file path to your SSH private key
      PROJECT_ID = "00000000-0000-0000-0000-000000000000"  # Replace with the unique Project ID
      BUNDLE_SIZE = 10

      # Data unit titles in your Project
      IMAGE_TITLE = "blueberries-001.jpg"
      IMG_GROUP_TITLE = "blueberries-ig"
      IMG_SEQUENCE_TITLE = "blueberries-is"
      VIDEO_TITLE = "blueberries-vid-001.mp4"

      # Authorize connection to Encord
      user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path=SSH_PATH,
          # For US platform users use domain="https://api.us.encord.com"
          domain="https://api.encord.com",
      )

      project: Project = user_client.get_project(PROJECT_ID)

      # Find the polygon object "Blueberries" in the ontology
      ontology_structure = project.ontology_structure
      polygon_ontology_object: Object = ontology_structure.get_child_by_title(title="Blueberries", type_=Object)
      assert polygon_ontology_object is not None, "Polygon object 'Blueberries' not found in ontology."

      # Initialise label rows
      label_rows = {}
      all_titles = [IMAGE_TITLE, IMG_GROUP_TITLE, IMG_SEQUENCE_TITLE, VIDEO_TITLE]

      with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
          for title in all_titles:
              rows = project.list_label_rows_v2(data_title_eq=title)
              assert isinstance(rows, list), f"Expected list for '{title}', got {type(rows)}"
              if not rows:
                  print(f"Skipping: No label row found for {title}")
                  continue
              lr = rows[0]
              lr.initialise_labels(bundle=bundle)
              assert lr.ontology_structure is not None, f"Ontology not initialized for '{title}'"
              label_rows[title] = lr

      # Coordinates: A simple 5-point polygon (single ring)
      poly = PolygonCoordinates(
          polygons=[
              [
                  [
                      PointCoordinate(0.10, 0.10),
                      PointCoordinate(0.20, 0.15),
                      PointCoordinate(0.25, 0.25),
                      PointCoordinate(0.15, 0.30),
                      PointCoordinate(0.08, 0.22),
                  ]
              ]
          ]
      )

      # Create instances and attach to frames
      label_rows_to_save = []

      # 1. One image > annotate frame 0
      image_lr = label_rows.get(IMAGE_TITLE)
      if image_lr is not None:
          inst: ObjectInstance = polygon_ontology_object.create_instance()
          inst.set_for_frames(coordinates=poly, frames=0)
          image_lr.add_object_instance(inst)
          label_rows_to_save.append(image_lr)

      # 2. One image group > annotate frame 0
      img_group_lr = label_rows.get(IMG_GROUP_TITLE)
      if img_group_lr is not None:
          inst: ObjectInstance = polygon_ontology_object.create_instance()
          inst.set_for_frames(coordinates=poly, frames=0)
          img_group_lr.add_object_instance(inst)
          label_rows_to_save.append(img_group_lr)

      # 3. One image sequence > annotate frame 0
      img_sequence_lr = label_rows.get(IMG_SEQUENCE_TITLE)
      if img_sequence_lr is not None:
          inst: ObjectInstance = polygon_ontology_object.create_instance()
          inst.set_for_frames(coordinates=poly, frames=0)
          img_sequence_lr.add_object_instance(inst)
          label_rows_to_save.append(img_sequence_lr)

      # 4. One video > reuse SAME instance across 3 consecutive frames (frames 100, 101, 102)
      video_lr = label_rows.get(VIDEO_TITLE)
      if video_lr is not None:
          inst: ObjectInstance = polygon_ontology_object.create_instance()
          consecutive_frames = [100, 101, 102]
          for f in consecutive_frames:
              inst.set_for_frames(coordinates=poly, frames=f)
          video_lr.add_object_instance(inst)
          label_rows_to_save.append(video_lr)

      # Save label rows
      with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
          for lr in label_rows_to_save:
              lr.save(bundle=bundle)
              print(f"Saved label row for {lr.data_title}")

      print("Done: created one polygon on image, image group, image sequence, and 3 video frames.")
      ```

      ```python Simple - Advanced expandable theme={"dark"}

      # Import dependencies
      from pathlib import Path

      from encord import EncordUserClient, Project
      from encord.objects import ChecklistAttribute, Object, ObjectInstance, Option, RadioAttribute, TextAttribute
      from encord.objects.coordinates import PointCoordinate, PolygonCoordinates
      from encord.objects.attributes import NumericAttribute

      # User input
      SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"
      # SSH_PATH = get_ssh_key() # replace it with access key
      PROJECT_ID = "00000000-0000-0000-0000-000000000000"
      BUNDLE_SIZE = 100

      # Create user client using access key
      user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path=SSH_PATH,
          # For US platform users use "https://api.us.encord.com"
          domain="https://api.encord.com",
      )

      # Get project for which labels are to be added
      project: Project = user_client.get_project(PROJECT_ID)
      assert project is not None, "Project not found — check PROJECT_ID"

      # Get ontology structure
      ontology_structure = project.ontology_structure
      assert ontology_structure is not None, "Ontology structure is missing in the project"

      # Find polygon object for blueberries
      polygon_ontology_object: Object = ontology_structure.get_child_by_title(title="Blueberries", type_=Object)
      assert polygon_ontology_object is not None, "Object 'Blueberries' not found in ontology"

      # Get radio attribute for blueberry type
      blueberry_type_radio_attribute = ontology_structure.get_child_by_title(type_=RadioAttribute, title="Type?")
      assert blueberry_type_radio_attribute is not None, "Radio attribute 'Type?' not found"

      # Get radio options
      bluegold_option = blueberry_type_radio_attribute.get_child_by_title(type_=Option, title="Bluegold")
      assert bluegold_option is not None, "Option 'Bluegold' not found under radio attribute 'Type?'"

      duke_option = blueberry_type_radio_attribute.get_child_by_title(type_=Option, title="Duke")
      assert duke_option is not None, "Option 'Duke' not found under radio attribute 'Type?'"

      blueray_option = blueberry_type_radio_attribute.get_child_by_title(type_=Option, title="Blueray")
      assert blueray_option is not None, "Option 'Blueray' not found under radio attribute 'Type?'"

      other_blueberry_option = blueberry_type_radio_attribute.get_child_by_title(type_=Option, title="Other blueberry type")
      assert other_blueberry_option is not None, "Option 'Other blueberry type' not found under radio attribute 'Type?'"

      # Find number attribute in the ontology
      blueberry_quality_number_attribute = ontology_structure.get_child_by_title(type_=NumericAttribute, title="Overall Quality")
      assert blueberry_quality_number_attribute is not None, "Number attribute 'Overall Quality' not found in ontology."

      # Bluegold Qualities
      bluegold_checklist_attribute = ontology_structure.get_child_by_title(
          type_=ChecklistAttribute, title="Bluegold Qualities?"
      )
      assert bluegold_checklist_attribute is not None, "Checklist attribute 'Bluegold Qualities?' not found"

      bluegold_plump_option = bluegold_checklist_attribute.get_child_by_title(type_=Option, title="Plump")
      assert bluegold_plump_option is not None, "Option 'Plump' not found under 'Bluegold Qualities?'"

      bluegold_juicy_option = bluegold_checklist_attribute.get_child_by_title(type_=Option, title="Juicy")
      assert bluegold_juicy_option is not None, "Option 'Juicy' not found under 'Bluegold Qualities?'"

      bluegold_large_option = bluegold_checklist_attribute.get_child_by_title(type_=Option, title="Large")
      assert bluegold_large_option is not None, "Option 'Large' not found under 'Bluegold Qualities?'"

      # Duke Qualities
      duke_checklist_attribute = ontology_structure.get_child_by_title(type_=ChecklistAttribute, title="Duke Qualities?")
      assert duke_checklist_attribute is not None, "Checklist attribute 'Duke Qualities?' not found"

      duke_plump_option = duke_checklist_attribute.get_child_by_title(type_=Option, title="Plump")
      assert duke_plump_option is not None, "Option 'Plump' not found under 'Duke Qualities?'"

      duke_juicy_option = duke_checklist_attribute.get_child_by_title(type_=Option, title="Juicy")
      assert duke_juicy_option is not None, "Option 'Juicy' not found under 'Duke Qualities?'"

      duke_large_option = duke_checklist_attribute.get_child_by_title(type_=Option, title="Large")
      assert duke_large_option is not None, "Option 'Large' not found under 'Duke Qualities?'"

      # Blueray Qualities
      blueray_checklist_attribute = ontology_structure.get_child_by_title(
          type_=ChecklistAttribute, title="Blueray Qualities?"
      )
      assert blueray_checklist_attribute is not None, "Checklist attribute 'Blueray Qualities?' not found"

      blueray_plump_option = blueray_checklist_attribute.get_child_by_title(type_=Option, title="Plump")
      assert blueray_plump_option is not None, "Option 'Plump' not found under 'Blueray Qualities?'"

      blueray_juicy_option = blueray_checklist_attribute.get_child_by_title(type_=Option, title="Juicy")
      assert blueray_juicy_option is not None, "Option 'Juicy' not found under 'Blueray Qualities?'"

      blueray_large_option = blueray_checklist_attribute.get_child_by_title(type_=Option, title="Large")
      assert blueray_large_option is not None, "Option 'Large' not found under 'Blueray Qualities?'"

      # Other blueberry type — text input
      other_blueberry_option_text_attribute = ontology_structure.get_child_by_title(
          type_=TextAttribute, title="Specify blueberry type"
      )
      assert other_blueberry_option_text_attribute is not None, "Text attribute 'Specify blueberry type' not found"


      # Dictionary of labels per data unit and per frame with blueberry type specified, including quality options
      video_frame_labels = {
          "blueberries-001.jpg": {
              0: {
                  "label_ref": "blueberry_001",
                  "coordinates": PolygonCoordinates(
                      polygons=[
                          [
                              [
                                  PointCoordinate(0.01, 0.02),
                                  PointCoordinate(0.03, 0.03),
                                  PointCoordinate(0.05, 0.02),
                                  PointCoordinate(0.04, 0.01),
                                  PointCoordinate(0.02, 0.01),
                              ]
                          ]
                      ]
                  ),
                  "blueberry_type": "Bluegold",
                  "bluegold_quality_options": "Plump, Juicy",
                  "blueberry_quality": 8
              }
          },
          "blueberries-010.jpg": {
              0: [
                  {
                      "label_ref": "blueberry_002",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              [
                                  [
                                      PointCoordinate(0.01, 0.02),
                                      PointCoordinate(0.03, 0.03),
                                      PointCoordinate(0.05, 0.02),
                                      PointCoordinate(0.04, 0.01),
                                      PointCoordinate(0.02, 0.01),
                                  ]
                              ]
                          ]
                      ),
                      "blueberry_type": "Duke",
                      "duke_quality_options": "Plump, Juicy, Large",
                      "blueberry_quality": 9
                  },
                  {
                      "label_ref": "blueberry_003",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              [
                                  [
                                      PointCoordinate(0.04, 0.05),
                                      PointCoordinate(0.06, 0.06),
                                      PointCoordinate(0.08, 0.05),
                                      PointCoordinate(0.07, 0.04),
                                      PointCoordinate(0.05, 0.04),
                                  ]
                              ]
                          ]
                      ),
                      "blueberry_type": "Blueray",
                      "blueray_quality_options": "Plump",
                      "blueberry_quality": 5
                  },
                  {
                      "label_ref": "blueberry_004",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              [
                                  [
                                      PointCoordinate(0.07, 0.02),
                                      PointCoordinate(0.09, 0.03),
                                      PointCoordinate(0.11, 0.02),
                                      PointCoordinate(0.10, 0.01),
                                      PointCoordinate(0.08, 0.01),
                                  ]
                              ]
                          ]
                      ),
                      "blueberry_type": "Other blueberry type",
                      "Specify blueberry type": "Highbush",
                      "blueberry_quality": 3
                  },
              ],
          },
          "blueberries-ig": {
              0: {
                  "label_ref": "blueberry_005",
                  "coordinates": PolygonCoordinates(
                      polygons=[
                          [
                              [
                                  PointCoordinate(0.01, 0.02),
                                  PointCoordinate(0.03, 0.03),
                                  PointCoordinate(0.05, 0.02),
                                  PointCoordinate(0.04, 0.01),
                                  PointCoordinate(0.02, 0.01),
                              ]
                          ]
                      ]
                  ),
                  "blueberry_type": "Bluegold",
                  "bluegold_quality_options": "Plump, Juicy",
                  "blueberry_quality": 8
              },
              2: [
                  {
                      "label_ref": "blueberry_006",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              [
                                  [
                                      PointCoordinate(0.01, 0.02),
                                      PointCoordinate(0.03, 0.03),
                                      PointCoordinate(0.05, 0.02),
                                      PointCoordinate(0.04, 0.01),
                                      PointCoordinate(0.02, 0.01),
                                  ]
                              ]
                          ]
                      ),
                      "blueberry_type": "Duke",
                      "duke_quality_options": "Large",
                      "blueberry_quality": 4
                  },
                  {
                      "label_ref": "blueberry_007",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              [
                                  [
                                      PointCoordinate(0.04, 0.05),
                                      PointCoordinate(0.06, 0.06),
                                      PointCoordinate(0.08, 0.05),
                                      PointCoordinate(0.07, 0.04),
                                      PointCoordinate(0.05, 0.04),
                                  ]
                              ]
                          ]
                      ),
                      "blueberry_type": "Blueray",
                      "blueray_quality_options": "Plump",
                      "blueberry_quality": 5
                  },
                  {
                      "label_ref": "blueberry_008",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              [
                                  [
                                      PointCoordinate(0.07, 0.02),
                                      PointCoordinate(0.09, 0.03),
                                      PointCoordinate(0.11, 0.02),
                                      PointCoordinate(0.10, 0.01),
                                      PointCoordinate(0.08, 0.01),
                                  ]
                              ]
                          ]
                      ),
                      "blueberry_type": "Other blueberry type",
                      "Specify blueberry type": "Lowbush",
                      "blueberry_quality": 2
                  },
              ],
          },
          "blueberries-is": {
              0: {
                  "label_ref": "blueberry_009",
                  "coordinates": PolygonCoordinates(
                      polygons=[
                          [
                              [
                                  PointCoordinate(0.01, 0.02),
                                  PointCoordinate(0.03, 0.03),
                                  PointCoordinate(0.05, 0.02),
                                  PointCoordinate(0.04, 0.01),
                                  PointCoordinate(0.02, 0.01),
                              ]
                          ]
                      ]
                  ),
                  "blueberry_type": "Bluegold",
                  "bluegold_quality_options": "Plump",
                  "blueberry_quality": 6
              },
              3: [
                  {
                      "label_ref": "blueberry_010",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              [
                                  [
                                      PointCoordinate(0.01, 0.02),
                                      PointCoordinate(0.03, 0.03),
                                      PointCoordinate(0.05, 0.02),
                                      PointCoordinate(0.04, 0.01),
                                      PointCoordinate(0.02, 0.01),
                                  ]
                              ]
                          ]
                      ),
                      "blueberry_type": "Duke",
                      "duke_quality_options": "Plump, Juicy, Large",
                      "blueberry_quality": 9
                  },
                  {
                      "label_ref": "blueberry_011",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              [
                                  [
                                      PointCoordinate(0.04, 0.05),
                                      PointCoordinate(0.06, 0.06),
                                      PointCoordinate(0.08, 0.05),
                                      PointCoordinate(0.07, 0.04),
                                      PointCoordinate(0.05, 0.04),
                                  ]
                              ]
                          ]
                      ),
                      "blueberry_type": "Blueray",
                      "blueray_quality_options": "Plump",
                      "blueberry_quality": 6
                  },
                  {
                      "label_ref": "blueberry_012",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              [
                                  [
                                      PointCoordinate(0.07, 0.02),
                                      PointCoordinate(0.09, 0.03),
                                      PointCoordinate(0.11, 0.02),
                                      PointCoordinate(0.10, 0.01),
                                      PointCoordinate(0.08, 0.01),
                                  ]
                              ]
                          ]
                      ),
                      "blueberry_type": "Other blueberry type",
                      "Specify blueberry type": "Highbush",
                      "blueberry_quality": 7
                  },
              ],
          },
          "blueberries-vid-001.mp4": {
              103: [
                  {
                      "label_ref": "blueberry_013",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              [
                                  [
                                      PointCoordinate(0.01, 0.02),
                                      PointCoordinate(0.03, 0.03),
                                      PointCoordinate(0.05, 0.02),
                                      PointCoordinate(0.04, 0.01),
                                      PointCoordinate(0.02, 0.01),
                                  ]
                              ]
                          ]
                      ),
                      "blueberry_type": "Blueray",
                      "blueray_quality_options": "Plump",
                      "blueberry_quality": 5
                  },
                  {
                      "label_ref": "blueberry_014",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              [
                                  [
                                      PointCoordinate(0.04, 0.05),
                                      PointCoordinate(0.06, 0.06),
                                      PointCoordinate(0.08, 0.05),
                                      PointCoordinate(0.07, 0.04),
                                      PointCoordinate(0.05, 0.04),
                                  ]
                              ]
                          ]
                      ),
                      "blueberry_type": "Bluegold",
                      "bluegold_quality_options": "Plump, Juicy, Large",
                      "blueberry_quality": 9
                  },
                  {
                      "label_ref": "blueberry_015",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              [
                                  [
                                      PointCoordinate(0.07, 0.02),
                                      PointCoordinate(0.09, 0.03),
                                      PointCoordinate(0.11, 0.02),
                                      PointCoordinate(0.10, 0.01),
                                      PointCoordinate(0.08, 0.01),
                                  ]
                              ]
                          ]
                      ),
                      "blueberry_type": "Other blueberry type",
                      "Specify blueberry type": "Lowbush",
                      "blueberry_quality": 8
                  },
              ],
              104: [
                  {
                      "label_ref": "blueberry_016",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              [
                                  [
                                      PointCoordinate(0.01, 0.02),
                                      PointCoordinate(0.03, 0.03),
                                      PointCoordinate(0.05, 0.02),
                                      PointCoordinate(0.04, 0.01),
                                      PointCoordinate(0.02, 0.01),
                                  ]
                              ]
                          ]
                      ),
                      "blueberry_type": "Blueray",
                      "blueray_quality_options": "Plump",
                      "blueberry_quality": 5
                  },
                  {
                      "label_ref": "blueberry_014",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              [
                                  [
                                      PointCoordinate(0.041, 0.052),
                                      PointCoordinate(0.061, 0.062),
                                      PointCoordinate(0.081, 0.052),
                                      PointCoordinate(0.071, 0.042),
                                      PointCoordinate(0.051, 0.042),
                                  ]
                              ]
                          ]
                      ),
                      "blueberry_type": "Bluegold",
                      "bluegold_quality_options": "Plump, Juicy, Large",
                      "blueberry_quality": 9
                  },
                  {
                      "label_ref": "blueberry_017",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              [
                                  [
                                      PointCoordinate(0.07, 0.02),
                                      PointCoordinate(0.09, 0.03),
                                      PointCoordinate(0.11, 0.02),
                                      PointCoordinate(0.10, 0.01),
                                      PointCoordinate(0.08, 0.01),
                                  ]
                              ]
                          ]
                      ),
                      "blueberry_type": "Other blueberry type",
                      "Specify blueberry type": "Highbush",
                      "blueberry_quality": 7
                  },
              ],
              105: [
                  {
                      "label_ref": "blueberry_016",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              [
                                  [
                                      PointCoordinate(0.011, 0.022),
                                      PointCoordinate(0.031, 0.032),
                                      PointCoordinate(0.051, 0.022),
                                      PointCoordinate(0.041, 0.012),
                                      PointCoordinate(0.021, 0.012),
                                  ]
                              ]
                          ]
                      ),
                      "blueberry_type": "Blueray",
                      "blueray_quality_options": "Plump",
                      "blueberry_quality": 5
                  },
                  {
                      "label_ref": "blueberry_014",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              [
                                  [
                                      PointCoordinate(0.043, 0.055),
                                      PointCoordinate(0.063, 0.065),
                                      PointCoordinate(0.083, 0.055),
                                      PointCoordinate(0.073, 0.045),
                                      PointCoordinate(0.053, 0.045),
                                  ]
                              ]
                          ]
                      ),
                      "blueberry_type": "Bluegold",
                      "bluegold_quality_options": "Plump, Juicy, Large",
                      "blueberry_quality": 9
                  },
                  {
                      "label_ref": "blueberry_017",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              [
                                  [
                                      PointCoordinate(0.071, 0.022),
                                      PointCoordinate(0.091, 0.032),
                                      PointCoordinate(0.111, 0.022),
                                      PointCoordinate(0.101, 0.012),
                                      PointCoordinate(0.081, 0.012),
                                  ]
                              ]
                          ]
                      ),
                      "blueberry_type": "Other blueberry type",
                      "Specify blueberry type": "Highbush",
                      "blueberry_quality": 3
                  },
              ],
          },
      }

      # Loop through each data unit (image, video, etc.)
      for data_unit, frame_coordinates in video_frame_labels.items():
          object_instances_by_label_ref = {}

          # Get the label row for the current data unit
          label_rows = project.list_label_rows_v2(data_title_eq=data_unit)
          assert isinstance(label_rows, list), f"Expected list of label rows for '{data_unit}', got {type(label_rows)}"
          assert label_rows, f"No label rows found for data unit: {data_unit}"

          label_row = label_rows[0]
          assert label_row is not None, f"Label row is None for {data_unit}"

          # Initialize label row using bundle
          with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
              label_row.initialise_labels()
              assert label_row.ontology_structure is not None, f"Ontology not initialized for label row: {data_unit}"

              for frame_number, items in frame_coordinates.items():
                  assert isinstance(frame_number, int), f"Frame number must be int, got {type(frame_number)}"

                  if not isinstance(items, list):  # Single or multiple objects in the frame
                      items = [items]

                  for item in items:
                      label_ref = item["label_ref"]
                      coord = item["coordinates"]
                      blueberry_type = item["blueberry_type"]
                      blueberry_quality = item["blueberry_quality"]

                      assert blueberry_type in {
                          "Bluegold",
                          "Duke",
                          "Blueray",
                          "Other blueberry type",
                      }, f"Unexpected blueberry type '{blueberry_type}' in data unit '{data_unit}'"

                      if label_ref not in object_instances_by_label_ref:
                          polygon_object_instance: ObjectInstance = polygon_ontology_object.create_instance()
                          assert polygon_object_instance is not None, f"Failed to create ObjectInstance for {label_ref}"

                          object_instances_by_label_ref[label_ref] = polygon_object_instance
                          checklist_attribute = None

                          # Set blueberry quality attribute 
                          polygon_object_instance.set_answer(attribute=blueberry_quality_number_attribute, answer=blueberry_quality)

                          # Set blueberry type attribute
                          if blueberry_type == "Bluegold":
                              assert bluegold_option is not None, "Missing 'bluegold_option'"
                              polygon_object_instance.set_answer(
                                  attribute=blueberry_type_radio_attribute, answer=bluegold_option
                              )
                              checklist_attribute = bluegold_checklist_attribute
                          elif blueberry_type == "Duke":
                              assert duke_option is not None, "Missing 'duke_option'"
                              polygon_object_instance.set_answer(attribute=blueberry_type_radio_attribute, answer=duke_option)
                              checklist_attribute = duke_checklist_attribute
                          elif blueberry_type == "Blueray":
                              assert blueray_option is not None, "Missing 'blueray_option'"
                              polygon_object_instance.set_answer(
                                  attribute=blueberry_type_radio_attribute, answer=blueray_option
                              )
                              checklist_attribute = blueray_checklist_attribute
                          elif blueberry_type == "Other blueberry type":
                              assert other_blueberry_option is not None, "Missing 'other_blueberry_option'"
                              polygon_object_instance.set_answer(
                                  attribute=blueberry_type_radio_attribute, answer=other_blueberry_option
                              )
                              text_answer = item.get("Specify blueberry type", "")
                              assert isinstance(text_answer, str), "'Specify blueberry type' must be a string"
                              polygon_object_instance.set_answer(
                                  attribute=other_blueberry_option_text_attribute,
                                  answer=text_answer,
                              )

                          # Set checklist attributes
                          checklist_answers = []
                          quality_key = f"{blueberry_type.lower()}_quality_options"
                          quality_options = item.get(quality_key, "").split(", ")

                          for quality in quality_options:
                              option = None
                              if quality == "Plump":
                                  option = (
                                      bluegold_plump_option
                                      if blueberry_type == "Bluegold"
                                      else duke_plump_option
                                      if blueberry_type == "Duke"
                                      else blueray_plump_option
                                      if blueberry_type == "Blueray"
                                      else None
                                  )
                              elif quality == "Juicy":
                                  option = (
                                      bluegold_juicy_option
                                      if blueberry_type == "Bluegold"
                                      else duke_juicy_option
                                      if blueberry_type == "Duke"
                                      else blueray_juicy_option
                                      if blueberry_type == "Blueray"
                                      else None
                                  )
                              elif quality == "Large":
                                  option = (
                                      bluegold_large_option
                                      if blueberry_type == "Bluegold"
                                      else duke_large_option
                                      if blueberry_type == "Duke"
                                      else blueray_large_option
                                      if blueberry_type == "Blueray"
                                      else None
                                  )

                              if option:
                                  checklist_answers.append(option)
                              else:
                                  assert blueberry_type == "Other blueberry type", (
                                      f"Invalid quality '{quality}' for type '{blueberry_type}'"
                                  )

                          if checklist_attribute and checklist_answers:
                              polygon_object_instance.set_answer(
                                  attribute=checklist_attribute, answer=checklist_answers, overwrite=True
                              )

                      else:
                          polygon_object_instance = object_instances_by_label_ref[label_ref]

                      # Assign the object to the frame and track it
                      polygon_object_instance.set_for_frames(coordinates=coord, frames=frame_number)

              # Add object instances to label_row **only if they have frames assigned**
              for polygon_object_instance in object_instances_by_label_ref.values():
                  assert isinstance(polygon_object_instance, ObjectInstance), "Expected ObjectInstance type"
                  if polygon_object_instance.get_annotation_frames():
                      label_row.add_object_instance(polygon_object_instance)

              # Save label row using the bundle
              assert label_row is not None, "Trying to save a None label row"
              label_row.save(bundle=bundle)

      print("Labels with blueberry type radio buttons, checklist attributes, number classifications, and text labels added for all data units.")

      ```
    </CodeGroup>

    <CodeGroup title="Complex Polygons - Donut">
      ```python Donut expandable theme={"dark"}

      from encord import EncordUserClient, Project
      from encord.objects import Object, ObjectInstance
      from encord.objects.coordinates import PointCoordinate, PolygonCoordinates

      # User input
      SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"  # Replace with the file path to your SSH private key
      PROJECT_ID = "00000000-0000-0000-0000-000000000000"  # Replace with the unique Project ID
      BUNDLE_SIZE = 10

      # Data unit titles in your Project
      IMAGE_TITLE = "blueberries-001.jpg"
      IMG_GROUP_TITLE = "blueberries-ig"
      IMG_SEQUENCE_TITLE = "blueberries-is"
      VIDEO_TITLE = "blueberries-vid-001.mp4"

      # Authorize connection to Encord
      user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path=SSH_PATH,
          # For US platform users use domain="https://api.us.encord.com"
          domain="https://api.encord.com",
      )

      project: Project = user_client.get_project(PROJECT_ID)

      # Find the polygon object "Blueberries" in the ontology
      ontology_structure = project.ontology_structure
      polygon_ontology_object: Object = ontology_structure.get_child_by_title(title="Blueberries", type_=Object)
      assert polygon_ontology_object is not None, "Polygon object 'Blueberries' not found in ontology."

      # Initialise label rows
      label_rows = {}
      all_titles = [IMAGE_TITLE, IMG_GROUP_TITLE, IMG_SEQUENCE_TITLE, VIDEO_TITLE]

      with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
          for title in all_titles:
              rows = project.list_label_rows_v2(data_title_eq=title)
              assert isinstance(rows, list), f"Expected list for '{title}', got {type(rows)}"
              if not rows:
                  print(f"Skipping: No label row found for {title}")
                  continue
              lr = rows[0]
              lr.initialise_labels(bundle=bundle)
              assert lr.ontology_structure is not None, f"Ontology not initialized for '{title}'"
              label_rows[title] = lr

      # Donut polygon coordinates
      outer_ring = [
          PointCoordinate(0.30, 0.30),
          PointCoordinate(0.40, 0.28),
          PointCoordinate(0.50, 0.35),
          PointCoordinate(0.52, 0.48),
          PointCoordinate(0.46, 0.60),
          PointCoordinate(0.36, 0.62),
          PointCoordinate(0.26, 0.55),
          PointCoordinate(0.24, 0.42),
      ]

      inner_ring = [  # hole
          PointCoordinate(0.36, 0.42),
          PointCoordinate(0.42, 0.41),
          PointCoordinate(0.45, 0.48),
          PointCoordinate(0.41, 0.53),
          PointCoordinate(0.34, 0.50),
      ]

      poly_donut = PolygonCoordinates(polygons=[[outer_ring, inner_ring]])

      # Create instances and attach to frames
      label_rows_to_save = []

      # 1. One image > annotate frame 0
      image_lr = label_rows.get(IMAGE_TITLE)
      if image_lr is not None:
          inst: ObjectInstance = polygon_ontology_object.create_instance()
          inst.set_for_frames(coordinates=poly_donut, frames=0)
          image_lr.add_object_instance(inst)
          label_rows_to_save.append(image_lr)

      # 2. One image group > annotate frame 0
      img_group_lr = label_rows.get(IMG_GROUP_TITLE)
      if img_group_lr is not None:
          inst: ObjectInstance = polygon_ontology_object.create_instance()
          inst.set_for_frames(coordinates=poly_donut, frames=0)
          img_group_lr.add_object_instance(inst)
          label_rows_to_save.append(img_group_lr)

      # 3. One image sequence > annotate frame 0
      img_sequence_lr = label_rows.get(IMG_SEQUENCE_TITLE)
      if img_sequence_lr is not None:
          inst: ObjectInstance = polygon_ontology_object.create_instance()
          inst.set_for_frames(coordinates=poly_donut, frames=0)
          img_sequence_lr.add_object_instance(inst)
          label_rows_to_save.append(img_sequence_lr)

      # 4. One video > reuse SAME instance across 3 consecutive frames (frames 100, 101, 102)
      video_lr = label_rows.get(VIDEO_TITLE)
      if video_lr is not None:
          inst: ObjectInstance = polygon_ontology_object.create_instance()
          consecutive_frames = [100, 101, 102]
          for f in consecutive_frames:
              inst.set_for_frames(coordinates=poly_donut, frames=f)
          video_lr.add_object_instance(inst)
          label_rows_to_save.append(video_lr)

      # Save label rows
      with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
          for lr in label_rows_to_save:
              lr.save(bundle=bundle)
              print(f"Saved label row for {lr.data_title}")

      print("Done: created one donut polygon on image, image group, image sequence, and 3 video frames.")
      ```

      ```python Donut - Advanced expandable theme={"dark"}

      # Import dependencies
      from pathlib import Path

      from encord import EncordUserClient, Project
      from encord.objects import ChecklistAttribute, Object, ObjectInstance, Option, RadioAttribute, TextAttribute
      from encord.objects.coordinates import PointCoordinate, PolygonCoordinates
      from encord.objects.attributes import NumericAttribute

      SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"
      # SSH_PATH = get_ssh_key() # replace it with access key
      PROJECT_ID = "00000000-0000-0000-0000-000000000000"
      BUNDLE_SIZE = 100

      # Create user client using access key
      user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path=SSH_PATH,
          # For US platform users use "https://api.us.encord.com"
          domain="https://api.encord.com",
      )

      # Get project for which labels are to be added
      project: Project = user_client.get_project(PROJECT_ID)
      assert project is not None, "Project not found — check PROJECT_ID"

      # Get ontology structure
      ontology_structure = project.ontology_structure
      assert ontology_structure is not None, "Ontology structure is missing in the project"

      # Find polygon object for blueberries
      polygon_ontology_object: Object = ontology_structure.get_child_by_title(title="Blueberries", type_=Object)
      assert polygon_ontology_object is not None, "Object 'Blueberries' not found in ontology"

      # Get radio attribute for blueberry type
      blueberry_type_radio_attribute = ontology_structure.get_child_by_title(type_=RadioAttribute, title="Type?")
      assert blueberry_type_radio_attribute is not None, "Radio attribute 'Type?' not found"

      # Get radio options
      bluegold_option = blueberry_type_radio_attribute.get_child_by_title(type_=Option, title="Bluegold")
      assert bluegold_option is not None, "Option 'Bluegold' not found under radio attribute 'Type?'"

      duke_option = blueberry_type_radio_attribute.get_child_by_title(type_=Option, title="Duke")
      assert duke_option is not None, "Option 'Duke' not found under radio attribute 'Type?'"

      blueray_option = blueberry_type_radio_attribute.get_child_by_title(type_=Option, title="Blueray")
      assert blueray_option is not None, "Option 'Blueray' not found under radio attribute 'Type?'"

      other_blueberry_option = blueberry_type_radio_attribute.get_child_by_title(type_=Option, title="Other blueberry type")
      assert other_blueberry_option is not None, "Option 'Other blueberry type' not found under radio attribute 'Type?'"

      # Find number attribute in the ontology
      blueberry_quality_number_attribute = ontology_structure.get_child_by_title(type_=NumericAttribute, title="Overall Quality")
      assert blueberry_quality_number_attribute is not None, "Number attribute 'Overall Quality' not found in ontology."

      # Bluegold Qualities
      bluegold_checklist_attribute = ontology_structure.get_child_by_title(
          type_=ChecklistAttribute, title="Bluegold Qualities?"
      )
      assert bluegold_checklist_attribute is not None, "Checklist attribute 'Bluegold Qualities?' not found"

      bluegold_plump_option = bluegold_checklist_attribute.get_child_by_title(type_=Option, title="Plump")
      assert bluegold_plump_option is not None, "Option 'Plump' not found under 'Bluegold Qualities?'"

      bluegold_juicy_option = bluegold_checklist_attribute.get_child_by_title(type_=Option, title="Juicy")
      assert bluegold_juicy_option is not None, "Option 'Juicy' not found under 'Bluegold Qualities?'"

      bluegold_large_option = bluegold_checklist_attribute.get_child_by_title(type_=Option, title="Large")
      assert bluegold_large_option is not None, "Option 'Large' not found under 'Bluegold Qualities?'"

      # Duke Qualities
      duke_checklist_attribute = ontology_structure.get_child_by_title(type_=ChecklistAttribute, title="Duke Qualities?")
      assert duke_checklist_attribute is not None, "Checklist attribute 'Duke Qualities?' not found"

      duke_plump_option = duke_checklist_attribute.get_child_by_title(type_=Option, title="Plump")
      assert duke_plump_option is not None, "Option 'Plump' not found under 'Duke Qualities?'"

      duke_juicy_option = duke_checklist_attribute.get_child_by_title(type_=Option, title="Juicy")
      assert duke_juicy_option is not None, "Option 'Juicy' not found under 'Duke Qualities?'"

      duke_large_option = duke_checklist_attribute.get_child_by_title(type_=Option, title="Large")
      assert duke_large_option is not None, "Option 'Large' not found under 'Duke Qualities?'"

      # Blueray Qualities
      blueray_checklist_attribute = ontology_structure.get_child_by_title(
          type_=ChecklistAttribute, title="Blueray Qualities?"
      )
      assert blueray_checklist_attribute is not None, "Checklist attribute 'Blueray Qualities?' not found"

      blueray_plump_option = blueray_checklist_attribute.get_child_by_title(type_=Option, title="Plump")
      assert blueray_plump_option is not None, "Option 'Plump' not found under 'Blueray Qualities?'"

      blueray_juicy_option = blueray_checklist_attribute.get_child_by_title(type_=Option, title="Juicy")
      assert blueray_juicy_option is not None, "Option 'Juicy' not found under 'Blueray Qualities?'"

      blueray_large_option = blueray_checklist_attribute.get_child_by_title(type_=Option, title="Large")
      assert blueray_large_option is not None, "Option 'Large' not found under 'Blueray Qualities?'"

      # Other blueberry type — text input
      other_blueberry_option_text_attribute = ontology_structure.get_child_by_title(
          type_=TextAttribute, title="Specify blueberry type"
      )
      assert other_blueberry_option_text_attribute is not None, "Text attribute 'Specify blueberry type' not found"

      # Dictionary of labels per data unit and per frame with blueberry type specified, including quality options
      video_frame_labels = {
          "blueberries-001.jpg": {
              0: {
                  "label_ref": "blueberry_001",
                  "coordinates": PolygonCoordinates(
                      polygons=[
                          [
                              # Outer ring (example: square)
                              [
                                  PointCoordinate(0.1, 0.1),
                                  PointCoordinate(0.9, 0.1),
                                  PointCoordinate(0.9, 0.9),
                                  PointCoordinate(0.1, 0.9),
                                  PointCoordinate(0.1, 0.1),  # Closing the ring
                              ],
                              # Inner ring (example: smaller square hole)
                              [
                                  PointCoordinate(0.4, 0.4),
                                  PointCoordinate(0.6, 0.4),
                                  PointCoordinate(0.6, 0.6),
                                  PointCoordinate(0.4, 0.6),
                                  PointCoordinate(0.4, 0.4),  # Closing the ring
                              ],
                          ]
                      ]
                  ),
                  "blueberry_type": "Bluegold",
                  "bluegold_quality_options": "Plump, Juicy",
                  "blueberry_quality": 7
              }
          },
          "blueberries-010.jpg": {
              0: [
                  {
                      "label_ref": "blueberry_002",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # First donut polygon
                              [
                                  # Outer ring (larger square)
                                  [
                                      PointCoordinate(0.1, 0.1),
                                      PointCoordinate(0.4, 0.1),
                                      PointCoordinate(0.4, 0.4),
                                      PointCoordinate(0.1, 0.4),
                                      PointCoordinate(0.1, 0.1),
                                      # Close the ring
                                  ],
                                  # Inner ring (smaller square hole)
                                  [
                                      PointCoordinate(0.2, 0.2),
                                      PointCoordinate(0.3, 0.2),
                                      PointCoordinate(0.3, 0.3),
                                      PointCoordinate(0.2, 0.3),
                                      PointCoordinate(0.2, 0.2),
                                      # Close the ring
                                  ],
                              ]
                          ]
                      ),
                      "blueberry_type": "Duke",
                      "duke_quality_options": "Plump, Juicy, Large",
                      "blueberry_quality": 7
                  },
                  {
                      "label_ref": "blueberry_003",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Second donut polygon
                              [
                                  # Outer ring (another larger square, elsewhere)
                                  [
                                      PointCoordinate(0.6, 0.6),
                                      PointCoordinate(0.9, 0.6),
                                      PointCoordinate(0.9, 0.9),
                                      PointCoordinate(0.6, 0.9),
                                      PointCoordinate(0.6, 0.6),
                                      # Close the ring
                                  ],
                                  # Inner ring (hole in the middle)
                                  [
                                      PointCoordinate(0.7, 0.7),
                                      PointCoordinate(0.8, 0.7),
                                      PointCoordinate(0.8, 0.8),
                                      PointCoordinate(0.7, 0.8),
                                      PointCoordinate(0.7, 0.7),  # Close the ring
                                  ],
                              ]
                          ]
                      ),
                      "blueberry_type": "Blueray",
                      "blueray_quality_options": "Plump",
                      "blueberry_quality": 4
                  },
                  {
                      "label_ref": "blueberry_004",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Third donut polygon
                              [
                                  # Outer ring
                                  [
                                      PointCoordinate(0.3, 0.6),
                                      PointCoordinate(0.7, 0.6),
                                      PointCoordinate(0.7, 0.9),
                                      PointCoordinate(0.3, 0.9),
                                      PointCoordinate(0.3, 0.6),
                                      # Close the ring
                                  ],
                                  # Inner ring (hole)
                                  [
                                      PointCoordinate(0.4, 0.7),
                                      PointCoordinate(0.6, 0.7),
                                      PointCoordinate(0.6, 0.8),
                                      PointCoordinate(0.4, 0.8),
                                      PointCoordinate(0.4, 0.7),
                                      # Close the ring
                                  ],
                              ]
                          ]
                      ),
                      "blueberry_type": "Other blueberry type",
                      "Specify blueberry type": "Highbush",
                      "blueberry_quality": 6
                  },
              ],
          },
          "blueberries-ig": {
              0: {
                  "label_ref": "blueberry_005",
                  "coordinates": PolygonCoordinates(
                      polygons=[
                          [
                              # Outer ring (example: square)
                              [
                                  PointCoordinate(0.1, 0.1),
                                  PointCoordinate(0.9, 0.1),
                                  PointCoordinate(0.9, 0.9),
                                  PointCoordinate(0.1, 0.9),
                                  PointCoordinate(0.1, 0.1),  # Closing the ring
                              ],
                              # Inner ring (example: smaller square hole)
                              [
                                  PointCoordinate(0.4, 0.4),
                                  PointCoordinate(0.6, 0.4),
                                  PointCoordinate(0.6, 0.6),
                                  PointCoordinate(0.4, 0.6),
                                  PointCoordinate(0.4, 0.4),  # Closing the ring
                              ],
                          ]
                      ]
                  ),
                  "blueberry_type": "Bluegold",
                  "bluegold_quality_options": "Plump, Juicy",
                  "blueberry_quality": 7
              },
              2: [
                  {
                      "label_ref": "blueberry_006",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # First donut polygon
                              [
                                  # Outer ring (larger square)
                                  [
                                      PointCoordinate(0.1, 0.1),
                                      PointCoordinate(0.4, 0.1),
                                      PointCoordinate(0.4, 0.4),
                                      PointCoordinate(0.1, 0.4),
                                      PointCoordinate(0.1, 0.1),
                                      # Close the ring
                                  ],
                                  # Inner ring (smaller square hole)
                                  [
                                      PointCoordinate(0.2, 0.2),
                                      PointCoordinate(0.3, 0.2),
                                      PointCoordinate(0.3, 0.3),
                                      PointCoordinate(0.2, 0.3),
                                      PointCoordinate(0.2, 0.2),
                                      # Close the ring
                                  ],
                              ]
                          ]
                      ),
                      "blueberry_type": "Duke",
                      "duke_quality_options": "Large",
                      "blueberry_quality": 5
                  },
                  {
                      "label_ref": "blueberry_007",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Second donut polygon
                              [
                                  # Outer ring (another larger square, elsewhere)
                                  [
                                      PointCoordinate(0.6, 0.6),
                                      PointCoordinate(0.9, 0.6),
                                      PointCoordinate(0.9, 0.9),
                                      PointCoordinate(0.6, 0.9),
                                      PointCoordinate(0.6, 0.6),
                                      # Close the ring
                                  ],
                                  # Inner ring (hole in the middle)
                                  [
                                      PointCoordinate(0.7, 0.7),
                                      PointCoordinate(0.8, 0.7),
                                      PointCoordinate(0.8, 0.8),
                                      PointCoordinate(0.7, 0.8),
                                      PointCoordinate(0.7, 0.7),  # Close the ring
                                  ],
                              ]
                          ]
                      ),
                      "blueberry_type": "Blueray",
                      "blueray_quality_options": "Plump",
                      "blueberry_quality": 6
                  },
                  {
                      "label_ref": "blueberry_008",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Third donut polygon
                              [
                                  # Outer ring
                                  [
                                      PointCoordinate(0.3, 0.6),
                                      PointCoordinate(0.7, 0.6),
                                      PointCoordinate(0.7, 0.9),
                                      PointCoordinate(0.3, 0.9),
                                      PointCoordinate(0.3, 0.6),
                                      # Close the ring
                                  ],
                                  # Inner ring (hole)
                                  [
                                      PointCoordinate(0.4, 0.7),
                                      PointCoordinate(0.6, 0.7),
                                      PointCoordinate(0.6, 0.8),
                                      PointCoordinate(0.4, 0.8),
                                      PointCoordinate(0.4, 0.7),
                                      # Close the ring
                                  ],
                              ]
                          ]
                      ),
                      "blueberry_type": "Other blueberry type",
                      "Specify blueberry type": "Lowbush",
                      "blueberry_quality": 8
                  },
              ],
          },
          "blueberries-is": {
              0: {
                  "label_ref": "blueberry_009",
                  "coordinates": PolygonCoordinates(
                      polygons=[
                          [
                              # Outer ring (example: square)
                              [
                                  PointCoordinate(0.1, 0.1),
                                  PointCoordinate(0.9, 0.1),
                                  PointCoordinate(0.9, 0.9),
                                  PointCoordinate(0.1, 0.9),
                                  PointCoordinate(0.1, 0.1),  # Closing the ring
                              ],
                              # Inner ring (example: smaller square hole)
                              [
                                  PointCoordinate(0.4, 0.4),
                                  PointCoordinate(0.6, 0.4),
                                  PointCoordinate(0.6, 0.6),
                                  PointCoordinate(0.4, 0.6),
                                  PointCoordinate(0.4, 0.4),  # Closing the ring
                              ],
                          ]
                      ]
                  ),
                  "blueberry_type": "Bluegold",
                  "bluegold_quality_options": "Plump",
                  "blueberry_quality": 8
              },
              3: [
                  {
                      "label_ref": "blueberry_010",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # First donut polygon
                              [
                                  # Outer ring (larger square)
                                  [
                                      PointCoordinate(0.1, 0.1),
                                      PointCoordinate(0.4, 0.1),
                                      PointCoordinate(0.4, 0.4),
                                      PointCoordinate(0.1, 0.4),
                                      PointCoordinate(0.1, 0.1),
                                      # Close the ring
                                  ],
                                  # Inner ring (smaller square hole)
                                  [
                                      PointCoordinate(0.2, 0.2),
                                      PointCoordinate(0.3, 0.2),
                                      PointCoordinate(0.3, 0.3),
                                      PointCoordinate(0.2, 0.3),
                                      PointCoordinate(0.2, 0.2),
                                      # Close the ring
                                  ],
                              ]
                          ]
                      ),
                      "blueberry_type": "Duke",
                      "duke_quality_options": "Plump, Juicy, Large",
                      "blueberry_quality": 9
                  },
                  {
                      "label_ref": "blueberry_011",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Second donut polygon
                              [
                                  # Outer ring (another larger square, elsewhere)
                                  [
                                      PointCoordinate(0.6, 0.6),
                                      PointCoordinate(0.9, 0.6),
                                      PointCoordinate(0.9, 0.9),
                                      PointCoordinate(0.6, 0.9),
                                      PointCoordinate(0.6, 0.6),
                                      # Close the ring
                                  ],
                                  # Inner ring (hole in the middle)
                                  [
                                      PointCoordinate(0.7, 0.7),
                                      PointCoordinate(0.8, 0.7),
                                      PointCoordinate(0.8, 0.8),
                                      PointCoordinate(0.7, 0.8),
                                      PointCoordinate(0.7, 0.7),  # Close the ring
                                  ],
                              ]
                          ]
                      ),
                      "blueberry_type": "Blueray",
                      "blueray_quality_options": "Plump",
                      "blueberry_quality": 5
                  },
                  {
                      "label_ref": "blueberry_012",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Third donut polygon
                              [
                                  # Outer ring
                                  [
                                      PointCoordinate(0.3, 0.6),
                                      PointCoordinate(0.7, 0.6),
                                      PointCoordinate(0.7, 0.9),
                                      PointCoordinate(0.3, 0.9),
                                      PointCoordinate(0.3, 0.6),
                                      # Close the ring
                                  ],
                                  # Inner ring (hole)
                                  [
                                      PointCoordinate(0.4, 0.7),
                                      PointCoordinate(0.6, 0.7),
                                      PointCoordinate(0.6, 0.8),
                                      PointCoordinate(0.4, 0.8),
                                      PointCoordinate(0.4, 0.7),
                                      # Close the ring
                                  ],
                              ]
                          ]
                      ),
                      "blueberry_type": "Other blueberry type",
                      "Specify blueberry type": "Highbush",
                      "blueberry_quality": 8
                  },
              ],
          },
          "blueberries-vid-001.mp4": {
              103: [
                  {
                      "label_ref": "blueberry_013",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # First donut polygon
                              [
                                  # Outer ring
                                  [
                                      PointCoordinate(0.05, 0.55),
                                      PointCoordinate(0.25, 0.55),
                                      PointCoordinate(0.25, 0.75),
                                      PointCoordinate(0.05, 0.75),
                                      PointCoordinate(0.05, 0.55),
                                      # Close the ring
                                  ],
                                  # Inner ring (hole)
                                  [
                                      PointCoordinate(0.10, 0.60),
                                      PointCoordinate(0.20, 0.60),
                                      PointCoordinate(0.20, 0.70),
                                      PointCoordinate(0.10, 0.70),
                                      PointCoordinate(0.10, 0.60),
                                      # Close the ring
                                  ],
                              ],
                          ]
                      ),
                      "blueberry_type": "Blueray",
                      "blueray_quality_options": "Plump",
                      "blueberry_quality": 6
                  },
                  {
                      "label_ref": "blueberry_014",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Second donut polygon
                              [
                                  # Outer ring (larger square)
                                  [
                                      PointCoordinate(0.1, 0.1),
                                      PointCoordinate(0.4, 0.1),
                                      PointCoordinate(0.4, 0.4),
                                      PointCoordinate(0.1, 0.4),
                                      PointCoordinate(0.1, 0.1),
                                      # Close the ring
                                  ],
                                  # Inner ring (smaller square hole)
                                  [
                                      PointCoordinate(0.2, 0.2),
                                      PointCoordinate(0.3, 0.2),
                                      PointCoordinate(0.3, 0.3),
                                      PointCoordinate(0.2, 0.3),
                                      PointCoordinate(0.2, 0.2),
                                      # Close the ring
                                  ],
                              ]
                          ]
                      ),
                      "blueberry_type": "Bluegold",
                      "bluegold_quality_options": "Plump, Juicy, Large",
                  },
                  {
                      "label_ref": "blueberry_015",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Third donut polygon
                              [
                                  # Outer ring
                                  [
                                      PointCoordinate(0.75, 0.75),
                                      PointCoordinate(0.95, 0.75),
                                      PointCoordinate(0.95, 0.95),
                                      PointCoordinate(0.75, 0.95),
                                      PointCoordinate(0.75, 0.75),  # Close the ring
                                  ],
                                  # Inner ring (hole)
                                  [
                                      PointCoordinate(0.80, 0.80),
                                      PointCoordinate(0.90, 0.80),
                                      PointCoordinate(0.90, 0.90),
                                      PointCoordinate(0.80, 0.90),
                                      PointCoordinate(0.80, 0.80),
                                      # Close the ring
                                  ],
                              ]
                          ]
                      ),
                      "blueberry_type": "Other blueberry type",
                      "Specify blueberry type": "Lowbush",
                      "blueberry_quality": 4
                  },
              ],
              104: [
                  {
                      "label_ref": "blueberry_016",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Fourth donut polygon
                              [
                                  # Outer ring
                                  [
                                      PointCoordinate(0.6, 0.1),
                                      PointCoordinate(0.9, 0.1),
                                      PointCoordinate(0.9, 0.4),
                                      PointCoordinate(0.6, 0.4),
                                      PointCoordinate(0.6, 0.1),
                                      # Close the ring
                                  ],
                                  # Inner ring (hole)
                                  [
                                      PointCoordinate(0.7, 0.2),
                                      PointCoordinate(0.8, 0.2),
                                      PointCoordinate(0.8, 0.3),
                                      PointCoordinate(0.7, 0.3),
                                      PointCoordinate(0.7, 0.2),
                                      # Close the ring
                                  ],
                              ]
                          ]
                      ),
                      "blueberry_type": "Blueray",
                      "blueray_quality_options": "Plump",
                      "blueberry_quality": 5
                  },
                  {
                      "label_ref": "blueberry_014",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Second donut polygon
                              [
                                  # Outer ring (larger square)
                                  [
                                      PointCoordinate(0.13, 0.13),
                                      PointCoordinate(0.43, 0.13),
                                      PointCoordinate(0.43, 0.43),
                                      PointCoordinate(0.13, 0.43),
                                      PointCoordinate(0.13, 0.13),
                                      # Close the ring
                                  ],
                                  # Inner ring (smaller square hole)
                                  [
                                      PointCoordinate(0.18, 0.18),
                                      PointCoordinate(0.28, 0.18),
                                      PointCoordinate(0.28, 0.28),
                                      PointCoordinate(0.17, 0.27),
                                      PointCoordinate(0.18, 0.18),
                                      # Close the ring
                                  ],
                              ]
                          ]
                      ),
                      "blueberry_type": "Bluegold",
                      "bluegold_quality_options": "Plump, Juicy, Large",
                      "blueberry_quality": 9
                  },
                  {
                      "label_ref": "blueberry_017",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Fifth donut polygon
                              [
                                  # Outer ring (larger square)
                                  [
                                      PointCoordinate(0.32, 0.62),
                                      PointCoordinate(0.72, 0.61),
                                      PointCoordinate(0.71, 0.92),
                                      PointCoordinate(0.31, 0.91),
                                      PointCoordinate(0.32, 0.62),
                                      # Close the ring
                                  ],
                                  # Inner ring (smaller square hole)
                                  [
                                      PointCoordinate(0.42, 0.72),
                                      PointCoordinate(0.61, 0.71),
                                      PointCoordinate(0.59, 0.82),
                                      PointCoordinate(0.41, 0.81),
                                      PointCoordinate(0.42, 0.72),
                                      # Close the ring
                                  ],
                              ]
                          ]
                      ),
                      "blueberry_type": "Other blueberry type",
                      "Specify blueberry type": "Highbush",
                      "blueberry_quality": 7
                  },
              ],
              105: [
                  {
                      "label_ref": "blueberry_016",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Fourth donut polygon
                              [
                                  # Outer ring
                                  [
                                      PointCoordinate(0.62, 0.12),
                                      PointCoordinate(0.91, 0.13),
                                      PointCoordinate(0.89, 0.42),
                                      PointCoordinate(0.61, 0.40),
                                      PointCoordinate(0.62, 0.12),
                                      # Close the ring
                                  ],
                                  # Inner ring (hole)
                                  [
                                      PointCoordinate(0.72, 0.22),
                                      PointCoordinate(0.82, 0.23),
                                      PointCoordinate(0.81, 0.33),
                                      PointCoordinate(0.71, 0.32),
                                      PointCoordinate(0.72, 0.22),
                                      # Close the ring
                                  ],
                              ]
                          ]
                      ),
                      "blueberry_type": "Blueray",
                      "blueray_quality_options": "Plump",
                      "blueberry_quality": 6
                  },
                  {
                      "label_ref": "blueberry_014",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Second donut polygon
                              [
                                  # Outer ring (larger square)
                                  [
                                      PointCoordinate(0.11, 0.14),
                                      PointCoordinate(0.41, 0.13),
                                      PointCoordinate(0.40, 0.44),
                                      PointCoordinate(0.10, 0.42),
                                      PointCoordinate(0.11, 0.14),
                                      # Close the ring
                                  ],
                                  # Inner ring (smaller square hole)
                                  [
                                      PointCoordinate(0.21, 0.24),
                                      PointCoordinate(0.30, 0.23),
                                      PointCoordinate(0.28, 0.34),
                                      PointCoordinate(0.19, 0.32),
                                      PointCoordinate(0.21, 0.24),
                                      # Close the ring
                                  ],
                              ]
                          ]
                      ),
                      "blueberry_type": "Bluegold",
                      "bluegold_quality_options": "Plump, Juicy, Large",
                      "blueberry_quality": 9
                  },
                  {
                      "label_ref": "blueberry_017",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Fifth donut polygon
                              [
                                  # Outer ring (larger square)
                                  [
                                      PointCoordinate(0.33, 0.60),
                                      PointCoordinate(0.73, 0.59),
                                      PointCoordinate(0.72, 0.88),
                                      PointCoordinate(0.32, 0.89),
                                      PointCoordinate(0.33, 0.60),
                                      # Close the ring
                                  ],
                                  # Inner ring (smaller square hole)
                                  [
                                      PointCoordinate(0.43, 0.70),
                                      PointCoordinate(0.62, 0.69),
                                      PointCoordinate(0.60, 0.80),
                                      PointCoordinate(0.42, 0.79),
                                      PointCoordinate(0.43, 0.70),
                                      # Close the ring
                                  ],
                              ]
                          ]
                      ),
                      "blueberry_type": "Other blueberry type",
                      "Specify blueberry type": "Highbush",
                      "blueberry_quality": 3
                  },
              ],
          },
      }

      # Loop through each data unit (image, video, etc.)
      for data_unit, frame_coordinates in video_frame_labels.items():
          object_instances_by_label_ref = {}

          # Get the label row for the current data unit
          label_rows = project.list_label_rows_v2(data_title_eq=data_unit)
          assert isinstance(label_rows, list), f"Expected list of label rows for '{data_unit}', got {type(label_rows)}"
          assert label_rows, f"No label rows found for data unit: {data_unit}"

          label_row = label_rows[0]
          assert label_row is not None, f"Label row is None for {data_unit}"

          # Initialize label row using bundle
          with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
              label_row.initialise_labels()
              assert label_row.ontology_structure is not None, f"Ontology not initialized for label row: {data_unit}"

              for frame_number, items in frame_coordinates.items():
                  assert isinstance(frame_number, int), f"Frame number must be int, got {type(frame_number)}"

                  if not isinstance(items, list):  # Single or multiple objects in the frame
                      items = [items]

                  for item in items:
                      label_ref = item["label_ref"]
                      coord = item["coordinates"]
                      blueberry_type = item["blueberry_type"]
                      blueberry_quality = item["blueberry_quality"]

                      assert blueberry_type in {
                          "Bluegold",
                          "Duke",
                          "Blueray",
                          "Other blueberry type",
                      }, f"Unexpected blueberry type '{blueberry_type}' in data unit '{data_unit}'"

                      if label_ref not in object_instances_by_label_ref:
                          polygon_object_instance: ObjectInstance = polygon_ontology_object.create_instance()
                          assert polygon_object_instance is not None, f"Failed to create ObjectInstance for {label_ref}"

                          object_instances_by_label_ref[label_ref] = polygon_object_instance
                          checklist_attribute = None

                          # Set blueberry quality attribute 
                          polygon_object_instance.set_answer(attribute=blueberry_quality_number_attribute, answer=blueberry_quality)

                          # Set blueberry type attribute
                          if blueberry_type == "Bluegold":
                              assert bluegold_option is not None, "Missing 'bluegold_option'"
                              polygon_object_instance.set_answer(
                                  attribute=blueberry_type_radio_attribute, answer=bluegold_option
                              )
                              checklist_attribute = bluegold_checklist_attribute
                          elif blueberry_type == "Duke":
                              assert duke_option is not None, "Missing 'duke_option'"
                              polygon_object_instance.set_answer(attribute=blueberry_type_radio_attribute, answer=duke_option)
                              checklist_attribute = duke_checklist_attribute
                          elif blueberry_type == "Blueray":
                              assert blueray_option is not None, "Missing 'blueray_option'"
                              polygon_object_instance.set_answer(
                                  attribute=blueberry_type_radio_attribute, answer=blueray_option
                              )
                              checklist_attribute = blueray_checklist_attribute
                          elif blueberry_type == "Other blueberry type":
                              assert other_blueberry_option is not None, "Missing 'other_blueberry_option'"
                              polygon_object_instance.set_answer(
                                  attribute=blueberry_type_radio_attribute, answer=other_blueberry_option
                              )
                              text_answer = item.get("Specify blueberry type", "")
                              assert isinstance(text_answer, str), "'Specify blueberry type' must be a string"
                              polygon_object_instance.set_answer(
                                  attribute=other_blueberry_option_text_attribute,
                                  answer=text_answer,
                              )

                          # Set checklist attributes
                          checklist_answers = []
                          quality_key = f"{blueberry_type.lower()}_quality_options"
                          quality_options = item.get(quality_key, "").split(", ")

                          for quality in quality_options:
                              option = None
                              if quality == "Plump":
                                  option = (
                                      bluegold_plump_option
                                      if blueberry_type == "Bluegold"
                                      else duke_plump_option
                                      if blueberry_type == "Duke"
                                      else blueray_plump_option
                                      if blueberry_type == "Blueray"
                                      else None
                                  )
                              elif quality == "Juicy":
                                  option = (
                                      bluegold_juicy_option
                                      if blueberry_type == "Bluegold"
                                      else duke_juicy_option
                                      if blueberry_type == "Duke"
                                      else blueray_juicy_option
                                      if blueberry_type == "Blueray"
                                      else None
                                  )
                              elif quality == "Large":
                                  option = (
                                      bluegold_large_option
                                      if blueberry_type == "Bluegold"
                                      else duke_large_option
                                      if blueberry_type == "Duke"
                                      else blueray_large_option
                                      if blueberry_type == "Blueray"
                                      else None
                                  )

                              if option:
                                  checklist_answers.append(option)
                              else:
                                  assert blueberry_type == "Other blueberry type", (
                                      f"Invalid quality '{quality}' for type '{blueberry_type}'"
                                  )

                          if checklist_attribute and checklist_answers:
                              polygon_object_instance.set_answer(
                                  attribute=checklist_attribute, answer=checklist_answers, overwrite=True
                              )

                      else:
                          polygon_object_instance = object_instances_by_label_ref[label_ref]

                      # Assign the object to the frame and track it
                      polygon_object_instance.set_for_frames(coordinates=coord, frames=frame_number)

              # Add object instances to label_row **only if they have frames assigned**
              for polygon_object_instance in object_instances_by_label_ref.values():
                  assert isinstance(polygon_object_instance, ObjectInstance), "Expected ObjectInstance type"
                  if polygon_object_instance.get_annotation_frames():
                      label_row.add_object_instance(polygon_object_instance)

              # Save label row using the bundle
              assert label_row is not None, "Trying to save a None label row"
              label_row.save(bundle=bundle)

      print("Labels with blueberry type radio buttons, checklist attributes, number attributes, and text labels added for all data units.")

      ```
    </CodeGroup>

    <CodeGroup title="Complex Polygons - Multiple">
      ```python Multiple - Basic expandable theme={"dark"}

      from encord import EncordUserClient, Project
      from encord.objects import Object, ObjectInstance
      from encord.objects.coordinates import PointCoordinate, PolygonCoordinates

      # User input
      SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"  # Replace with the file path to your SSH private key
      PROJECT_ID = "00000000-0000-0000-0000-000000000000"  # Replace with the unique Project ID
      BUNDLE_SIZE = 10

      # Data unit titles in your Project
      IMAGE_TITLE = "blueberries-001.jpg"
      IMG_GROUP_TITLE = "blueberries-ig"
      IMG_SEQUENCE_TITLE = "blueberries-is"
      VIDEO_TITLE = "blueberries-vid-001.mp4"

      # Authorize connection to Encord
      user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path=SSH_PATH,
          # For US platform users use domain="https://api.us.encord.com"
          domain="https://api.encord.com",
      )

      project: Project = user_client.get_project(PROJECT_ID)

      # Find the polygon object "Blueberries" in the ontology
      ontology_structure = project.ontology_structure
      polygon_ontology_object: Object = ontology_structure.get_child_by_title(title="Blueberries", type_=Object)
      assert polygon_ontology_object is not None, "Polygon object 'Blueberries' not found in ontology."

      # Initialise label rows
      label_rows = {}
      all_titles = [IMAGE_TITLE, IMG_GROUP_TITLE, IMG_SEQUENCE_TITLE, VIDEO_TITLE]

      with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
          for title in all_titles:
              rows = project.list_label_rows_v2(data_title_eq=title)
              assert isinstance(rows, list), f"Expected list for '{title}', got {type(rows)}"
              if not rows:
                  print(f"Skipping: No label row found for {title}")
                  continue
              lr = rows[0]
              lr.initialise_labels(bundle=bundle)
              assert lr.ontology_structure is not None, f"Ontology not initialized for '{title}'"
              label_rows[title] = lr

      # Multi-polygon coordinates: Two separate simple polygons
      ring_a = [
          PointCoordinate(0.15, 0.15),
          PointCoordinate(0.22, 0.18),
          PointCoordinate(0.24, 0.25),
          PointCoordinate(0.18, 0.28),
          PointCoordinate(0.12, 0.22),
      ]

      ring_b = [
          PointCoordinate(0.55, 0.35),
          PointCoordinate(0.62, 0.38),
          PointCoordinate(0.66, 0.45),
          PointCoordinate(0.60, 0.50),
          PointCoordinate(0.53, 0.43),
      ]

      poly_multi = PolygonCoordinates(polygons=[[ring_a], [ring_b]])

      # Create instances and attach to frames
      label_rows_to_save = []

      # 1. One image > annotate frame 0
      image_lr = label_rows.get(IMAGE_TITLE)
      if image_lr is not None:
          inst: ObjectInstance = polygon_ontology_object.create_instance()
          inst.set_for_frames(coordinates=poly_multi, frames=0)
          image_lr.add_object_instance(inst)
          label_rows_to_save.append(image_lr)

      # 2. One image group > annotate frame 0
      img_group_lr = label_rows.get(IMG_GROUP_TITLE)
      if img_group_lr is not None:
          inst: ObjectInstance = polygon_ontology_object.create_instance()
          inst.set_for_frames(coordinates=poly_multi, frames=0)
          img_group_lr.add_object_instance(inst)
          label_rows_to_save.append(img_group_lr)

      # 3. One image sequence > annotate frame 0
      img_sequence_lr = label_rows.get(IMG_SEQUENCE_TITLE)
      if img_sequence_lr is not None:
          inst: ObjectInstance = polygon_ontology_object.create_instance()
          inst.set_for_frames(coordinates=poly_multi, frames=0)
          img_sequence_lr.add_object_instance(inst)
          label_rows_to_save.append(img_sequence_lr)

      # 4. One video > reuse SAME instance across 3 consecutive frames (frames 100, 101, 102)
      video_lr = label_rows.get(VIDEO_TITLE)
      if video_lr is not None:
          inst: ObjectInstance = polygon_ontology_object.create_instance()
          consecutive_frames = [100, 101, 102]
          for f in consecutive_frames:
              inst.set_for_frames(coordinates=poly_multi, frames=f)
          video_lr.add_object_instance(inst)
          label_rows_to_save.append(video_lr)

      # Save label rows
      with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
          for lr in label_rows_to_save:
              lr.save(bundle=bundle)
              print(f"Saved label row for {lr.data_title}")

      print("Done: created one multi-polygon (two separate rings) on image, image group, image sequence, and 3 video frames.")
      ```

      ```python Multiple - Basic expandable theme={"dark"}

      # Import dependencies
      from pathlib import Path

      from encord import EncordUserClient, Project
      from encord.objects import ChecklistAttribute, Object, ObjectInstance, Option, RadioAttribute, TextAttribute
      from encord.objects.coordinates import PointCoordinate, PolygonCoordinates
      from encord.objects.attributes import NumericAttribute


      SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"
      # SSH_PATH = get_ssh_key() # replace it with access key
      PROJECT_ID = "00000000-0000-0000-0000-000000000000"
      BUNDLE_SIZE = 100

      # Create user client using access key
      user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path=SSH_PATH,
          # For US platform users use "https://api.us.encord.com"
          domain="https://api.encord.com",
      )

      # Get project for which labels are to be added
      project: Project = user_client.get_project(PROJECT_ID)
      assert project is not None, "Project not found — check PROJECT_ID"

      # Get ontology structure
      ontology_structure = project.ontology_structure
      assert ontology_structure is not None, "Ontology structure is missing in the project"

      # Find polygon object for blueberries
      polygon_ontology_object: Object = ontology_structure.get_child_by_title(title="Blueberries", type_=Object)
      assert polygon_ontology_object is not None, "Object 'Blueberries' not found in ontology"

      # Get radio attribute for blueberry type
      blueberry_type_radio_attribute = ontology_structure.get_child_by_title(type_=RadioAttribute, title="Type?")
      assert blueberry_type_radio_attribute is not None, "Radio attribute 'Type?' not found"

      # Get radio options
      bluegold_option = blueberry_type_radio_attribute.get_child_by_title(type_=Option, title="Bluegold")
      assert bluegold_option is not None, "Option 'Bluegold' not found under radio attribute 'Type?'"

      duke_option = blueberry_type_radio_attribute.get_child_by_title(type_=Option, title="Duke")
      assert duke_option is not None, "Option 'Duke' not found under radio attribute 'Type?'"

      blueray_option = blueberry_type_radio_attribute.get_child_by_title(type_=Option, title="Blueray")
      assert blueray_option is not None, "Option 'Blueray' not found under radio attribute 'Type?'"

      other_blueberry_option = blueberry_type_radio_attribute.get_child_by_title(type_=Option, title="Other blueberry type")
      assert other_blueberry_option is not None, "Option 'Other blueberry type' not found under radio attribute 'Type?'"

      # Find number attribute in the ontology
      blueberry_quality_number_attribute = ontology_structure.get_child_by_title(type_=NumericAttribute, title="Overall Quality")
      assert blueberry_quality_number_attribute is not None, "Number attribute 'Overall Quality' not found in ontology."

      # Bluegold Qualities
      bluegold_checklist_attribute = ontology_structure.get_child_by_title(
          type_=ChecklistAttribute, title="Bluegold Qualities?"
      )
      assert bluegold_checklist_attribute is not None, "Checklist attribute 'Bluegold Qualities?' not found"

      bluegold_plump_option = bluegold_checklist_attribute.get_child_by_title(type_=Option, title="Plump")
      assert bluegold_plump_option is not None, "Option 'Plump' not found under 'Bluegold Qualities?'"

      bluegold_juicy_option = bluegold_checklist_attribute.get_child_by_title(type_=Option, title="Juicy")
      assert bluegold_juicy_option is not None, "Option 'Juicy' not found under 'Bluegold Qualities?'"

      bluegold_large_option = bluegold_checklist_attribute.get_child_by_title(type_=Option, title="Large")
      assert bluegold_large_option is not None, "Option 'Large' not found under 'Bluegold Qualities?'"

      # Duke Qualities
      duke_checklist_attribute = ontology_structure.get_child_by_title(type_=ChecklistAttribute, title="Duke Qualities?")
      assert duke_checklist_attribute is not None, "Checklist attribute 'Duke Qualities?' not found"

      duke_plump_option = duke_checklist_attribute.get_child_by_title(type_=Option, title="Plump")
      assert duke_plump_option is not None, "Option 'Plump' not found under 'Duke Qualities?'"

      duke_juicy_option = duke_checklist_attribute.get_child_by_title(type_=Option, title="Juicy")
      assert duke_juicy_option is not None, "Option 'Juicy' not found under 'Duke Qualities?'"

      duke_large_option = duke_checklist_attribute.get_child_by_title(type_=Option, title="Large")
      assert duke_large_option is not None, "Option 'Large' not found under 'Duke Qualities?'"

      # Blueray Qualities
      blueray_checklist_attribute = ontology_structure.get_child_by_title(
          type_=ChecklistAttribute, title="Blueray Qualities?"
      )
      assert blueray_checklist_attribute is not None, "Checklist attribute 'Blueray Qualities?' not found"

      blueray_plump_option = blueray_checklist_attribute.get_child_by_title(type_=Option, title="Plump")
      assert blueray_plump_option is not None, "Option 'Plump' not found under 'Blueray Qualities?'"

      blueray_juicy_option = blueray_checklist_attribute.get_child_by_title(type_=Option, title="Juicy")
      assert blueray_juicy_option is not None, "Option 'Juicy' not found under 'Blueray Qualities?'"

      blueray_large_option = blueray_checklist_attribute.get_child_by_title(type_=Option, title="Large")
      assert blueray_large_option is not None, "Option 'Large' not found under 'Blueray Qualities?'"

      # Other blueberry type — text input
      other_blueberry_option_text_attribute = ontology_structure.get_child_by_title(
          type_=TextAttribute, title="Specify blueberry type"
      )
      assert other_blueberry_option_text_attribute is not None, "Text attribute 'Specify blueberry type' not found"

      # Dictionary of labels per data unit and per frame with blueberry type specified, including quality options
      video_frame_labels = {
          "blueberries-001.jpg": {
              0: {
                  "label_ref": "blueberry_001",
                  "coordinates": PolygonCoordinates(
                      polygons=[
                          [
                              # Polygon
                              # First part (triangle)
                              [
                                  PointCoordinate(0.1, 0.1),
                                  PointCoordinate(0.3, 0.1),
                                  PointCoordinate(0.2, 0.3),
                                  PointCoordinate(0.1, 0.1),
                                  # Close the polygon
                              ]
                          ],
                          [
                              # Second part (pentagon)
                              [
                                  PointCoordinate(0.6, 0.2),
                                  PointCoordinate(0.7, 0.25),
                                  PointCoordinate(0.75, 0.35),
                                  PointCoordinate(0.65, 0.45),
                                  PointCoordinate(0.55, 0.35),
                                  PointCoordinate(0.6, 0.2),
                                  # Close the polygon
                              ]
                          ],
                      ]
                  ),
                  "blueberry_type": "Bluegold",
                  "bluegold_quality_options": "Plump, Juicy",
                  "blueberry_quality": 8
              }
          },
          "blueberries-010.jpg": {
              0: [
                  {
                      "label_ref": "blueberry_002",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Polygon 1
                              [
                                  # First part
                                  [
                                      PointCoordinate(0.1, 0.1),
                                      PointCoordinate(0.3, 0.1),
                                      PointCoordinate(0.2, 0.3),
                                      PointCoordinate(0.1, 0.1),
                                      # Close the polygon
                                  ]
                              ],
                              # Second part
                              [
                                  [
                                      PointCoordinate(0.5, 0.5),
                                      PointCoordinate(0.7, 0.5),
                                      PointCoordinate(0.6, 0.7),
                                      PointCoordinate(0.5, 0.5),
                                      # Close the polygon
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Duke",
                      "duke_quality_options": "Plump, Juicy, Large",
                      "blueberry_quality": 9
                  },
                  {
                      "label_ref": "blueberry_003",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Polygon 2
                              [
                                  # First part
                                  [
                                      PointCoordinate(0.15, 0.6),
                                      PointCoordinate(0.35, 0.6),
                                      PointCoordinate(0.35, 0.8),
                                      PointCoordinate(0.15, 0.8),
                                      PointCoordinate(0.15, 0.6),
                                      # Close the polygon
                                  ]
                              ],
                              # Second part
                              [
                                  [
                                      PointCoordinate(0.55, 0.15),
                                      PointCoordinate(0.75, 0.15),
                                      PointCoordinate(0.75, 0.35),
                                      PointCoordinate(0.55, 0.35),
                                      PointCoordinate(0.55, 0.15),
                                      # Close the polygon
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Blueray",
                      "blueray_quality_options": "Plump",
                      "blueberry_quality": 6
                  },
                  {
                      "label_ref": "blueberry_004",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Third polygon
                              [
                                  # First part
                                  [
                                      PointCoordinate(0.25, 0.25),
                                      PointCoordinate(0.4, 0.3),
                                      PointCoordinate(0.35, 0.45),
                                      PointCoordinate(0.2, 0.4),
                                      PointCoordinate(0.25, 0.25),
                                      # Close the polygon
                                  ]
                              ],
                              # Second part
                              [
                                  [
                                      PointCoordinate(0.65, 0.6),
                                      PointCoordinate(0.8, 0.65),
                                      PointCoordinate(0.75, 0.8),
                                      PointCoordinate(0.6, 0.75),
                                      PointCoordinate(0.65, 0.6),
                                      # Close the polygon
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Other blueberry type",
                      "Specify blueberry type": "Highbush",
                      "blueberry_quality": 4
                  },
              ],
          },
          "blueberries-ig": {
              0: {
                  "label_ref": "blueberry_005",
                  "coordinates": PolygonCoordinates(
                      polygons=[
                          [
                              # Polygon
                              # First part (triangle)
                              [
                                  PointCoordinate(0.1, 0.1),
                                  PointCoordinate(0.3, 0.1),
                                  PointCoordinate(0.2, 0.3),
                                  PointCoordinate(0.1, 0.1),
                                  # Close the ring
                              ]
                          ],
                          [
                              # Second part (pentagon)
                              [
                                  PointCoordinate(0.6, 0.2),
                                  PointCoordinate(0.7, 0.25),
                                  PointCoordinate(0.75, 0.35),
                                  PointCoordinate(0.65, 0.45),
                                  PointCoordinate(0.55, 0.35),
                                  PointCoordinate(0.6, 0.2),
                                  # Close the ring
                              ]
                          ],
                      ]
                  ),
                  "blueberry_type": "Bluegold",
                  "bluegold_quality_options": "Plump, Juicy",
                  "blueberry_quality": 7
              },
              2: [
                  {
                      "label_ref": "blueberry_006",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # First polygon
                              [
                                  # First part
                                  [
                                      PointCoordinate(0.05, 0.15),
                                      PointCoordinate(0.20, 0.10),
                                      PointCoordinate(0.25, 0.25),
                                      PointCoordinate(0.10, 0.30),
                                      PointCoordinate(0.05, 0.15),
                                      # Close the polygon
                                  ]
                              ],
                              # Second part
                              [
                                  [
                                      PointCoordinate(0.50, 0.20),
                                      PointCoordinate(0.65, 0.25),
                                      PointCoordinate(0.60, 0.40),
                                      PointCoordinate(0.45, 0.35),
                                      PointCoordinate(0.50, 0.20),
                                      # Close the polygon
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Duke",
                      "duke_quality_options": "Large",
                      "blueberry_quality": 5
                  },
                  {
                      "label_ref": "blueberry_007",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Second polygon
                              [
                                  # First part
                                  [
                                      PointCoordinate(0.30, 0.60),
                                      PointCoordinate(0.50, 0.60),
                                      PointCoordinate(0.50, 0.75),
                                      PointCoordinate(0.30, 0.75),
                                      PointCoordinate(0.30, 0.60),
                                      # Close the polygon
                                  ]
                              ],
                              # Second part
                              [
                                  [
                                      PointCoordinate(0.65, 0.55),
                                      PointCoordinate(0.85, 0.55),
                                      PointCoordinate(0.85, 0.70),
                                      PointCoordinate(0.65, 0.70),
                                      PointCoordinate(0.65, 0.55),
                                      # Close the polygon
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Blueray",
                      "blueray_quality_options": "Plump",
                      "blueberry_quality": 5
                  },
                  {
                      "label_ref": "blueberry_008",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Third polygon
                              [
                                  # First part
                                  [
                                      PointCoordinate(0.10, 0.80),
                                      PointCoordinate(0.25, 0.85),
                                      PointCoordinate(0.20, 0.95),
                                      PointCoordinate(0.05, 0.90),
                                      PointCoordinate(0.10, 0.80),
                                      # Close the polygon
                                  ]
                              ],
                              # Second part
                              [
                                  [
                                      PointCoordinate(0.55, 0.75),
                                      PointCoordinate(0.70, 0.80),
                                      PointCoordinate(0.65, 0.95),
                                      PointCoordinate(0.50, 0.90),
                                      PointCoordinate(0.55, 0.75),
                                      # Close the polygon
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Other blueberry type",
                      "Specify blueberry type": "Lowbush",
                      "blueberry_quality": 7
                  },
              ],
          },
          "blueberries-is": {
              0: {
                  "label_ref": "blueberry_009",
                  "coordinates": PolygonCoordinates(
                      polygons=[
                          [
                              # Polygon
                              # First part (triangle)
                              [
                                  PointCoordinate(0.1, 0.1),
                                  PointCoordinate(0.3, 0.1),
                                  PointCoordinate(0.2, 0.3),
                                  PointCoordinate(0.1, 0.1),
                                  # Close the ring
                              ]
                          ],
                          [
                              # Second part (pentagon)
                              [
                                  PointCoordinate(0.6, 0.2),
                                  PointCoordinate(0.7, 0.25),
                                  PointCoordinate(0.75, 0.35),
                                  PointCoordinate(0.65, 0.45),
                                  PointCoordinate(0.55, 0.35),
                                  PointCoordinate(0.6, 0.2),
                                  # Close the ring
                              ]
                          ],
                      ]
                  ),
                  "blueberry_type": "Bluegold",
                  "bluegold_quality_options": "Plump",
                  "blueberry_quality": 5
              },
              3: [
                  {
                      "label_ref": "blueberry_010",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # First polygon
                              [
                                  # First part
                                  [
                                      PointCoordinate(0.05, 0.15),
                                      PointCoordinate(0.20, 0.10),
                                      PointCoordinate(0.25, 0.25),
                                      PointCoordinate(0.10, 0.30),
                                      PointCoordinate(0.05, 0.15),
                                      # Close the polygon
                                  ]
                              ],
                              # Second part
                              [
                                  [
                                      PointCoordinate(0.50, 0.20),
                                      PointCoordinate(0.65, 0.25),
                                      PointCoordinate(0.60, 0.40),
                                      PointCoordinate(0.45, 0.35),
                                      PointCoordinate(0.50, 0.20),
                                      # Close the polygon
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Duke",
                      "duke_quality_options": "Plump, Juicy, Large",
                      "blueberry_quality": 9
                  },
                  {
                      "label_ref": "blueberry_011",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Second polygon
                              [
                                  # First part
                                  [
                                      PointCoordinate(0.30, 0.60),
                                      PointCoordinate(0.50, 0.60),
                                      PointCoordinate(0.50, 0.75),
                                      PointCoordinate(0.30, 0.75),
                                      PointCoordinate(0.30, 0.60),
                                      # Close the polygon
                                  ]
                              ],
                              # Second part
                              [
                                  [
                                      PointCoordinate(0.65, 0.55),
                                      PointCoordinate(0.85, 0.55),
                                      PointCoordinate(0.85, 0.70),
                                      PointCoordinate(0.65, 0.70),
                                      PointCoordinate(0.65, 0.55),
                                      # Close the polygon
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Blueray",
                      "blueray_quality_options": "Plump",
                      "blueberry_quality": 4
                  },
                  {
                      "label_ref": "blueberry_012",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Third polygon
                              [
                                  # First part
                                  [
                                      PointCoordinate(0.10, 0.80),
                                      PointCoordinate(0.25, 0.85),
                                      PointCoordinate(0.20, 0.95),
                                      PointCoordinate(0.05, 0.90),
                                      PointCoordinate(0.10, 0.80),
                                      # Close the polygon
                                  ]
                              ],
                              # Second part
                              [
                                  [
                                      PointCoordinate(0.55, 0.75),
                                      PointCoordinate(0.70, 0.80),
                                      PointCoordinate(0.65, 0.95),
                                      PointCoordinate(0.50, 0.90),
                                      PointCoordinate(0.55, 0.75),
                                      # Close the polygon
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Other blueberry type",
                      "Specify blueberry type": "Highbush",
                      "blueberry_quality": 1
                  },
              ],
          },
          "blueberries-vid-001.mp4": {
              103: [
                  {
                      "label_ref": "blueberry_013",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # First polygon
                              [
                                  # First part
                                  [
                                      PointCoordinate(0.05, 0.35),
                                      PointCoordinate(0.15, 0.33),
                                      PointCoordinate(0.17, 0.43),
                                      PointCoordinate(0.07, 0.45),
                                      PointCoordinate(0.05, 0.35),
                                      # Close the polygon
                                  ]
                              ],
                              # Second part
                              [
                                  [
                                      PointCoordinate(0.80, 0.40),
                                      PointCoordinate(0.90, 0.42),
                                      PointCoordinate(0.88, 0.52),
                                      PointCoordinate(0.78, 0.50),
                                      PointCoordinate(0.80, 0.40),
                                      # Close the polygon
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Blueray",
                      "blueray_quality_options": "Plump",
                      "blueberry_quality": 6
                  },
                  {
                      "label_ref": "blueberry_014",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Second polygon
                              [
                                  # First part
                                  [
                                      PointCoordinate(0.05, 0.05),
                                      PointCoordinate(0.15, 0.05),
                                      PointCoordinate(0.15, 0.10),
                                      PointCoordinate(0.05, 0.10),
                                      PointCoordinate(0.05, 0.05),
                                      # Close the polygon
                                  ]
                              ],
                              # Second part
                              [
                                  [
                                      PointCoordinate(0.80, 0.05),
                                      PointCoordinate(0.95, 0.05),
                                      PointCoordinate(0.95, 0.10),
                                      PointCoordinate(0.80, 0.10),
                                      PointCoordinate(0.80, 0.05),
                                      # Close the polygon
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Bluegold",
                      "bluegold_quality_options": "Plump, Juicy, Large",
                      "blueberry_quality": 9
                  },
                  {
                      "label_ref": "blueberry_015",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Third polygon
                              [
                                  # First part
                                  [
                                      PointCoordinate(0.15, 0.40),
                                      PointCoordinate(0.25, 0.38),
                                      PointCoordinate(0.27, 0.48),
                                      PointCoordinate(0.17, 0.50),
                                      PointCoordinate(0.15, 0.40),
                                      # Close the polygon
                                  ]
                              ],
                              # Second part
                              [
                                  [
                                      PointCoordinate(0.65, 0.65),
                                      PointCoordinate(0.75, 0.63),
                                      PointCoordinate(0.77, 0.73),
                                      PointCoordinate(0.67, 0.75),
                                      PointCoordinate(0.65, 0.65),
                                      # Close the polygon
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Other blueberry type",
                      "Specify blueberry type": "Lowbush",
                      "blueberry_quality": 7
                  },
              ],
              104: [
                  {
                      "label_ref": "blueberry_016",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Fourth polygon
                              [
                                  # First part
                                  [
                                      PointCoordinate(0.20, 0.20),
                                      PointCoordinate(0.30, 0.18),
                                      PointCoordinate(0.32, 0.28),
                                      PointCoordinate(0.22, 0.30),
                                      PointCoordinate(0.20, 0.20),
                                      # Close the polygon
                                  ]
                              ],
                              # Second part
                              [
                                  [
                                      PointCoordinate(0.65, 0.20),
                                      PointCoordinate(0.75, 0.22),
                                      PointCoordinate(0.73, 0.32),
                                      PointCoordinate(0.63, 0.30),
                                      PointCoordinate(0.65, 0.20),
                                      # Close the polygon
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Blueray",
                      "blueray_quality_options": "Plump",
                      "blueberry_quality": 6
                  },
                  {
                      "label_ref": "blueberry_014",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Second polygon
                              [
                                  # First part
                                  [
                                      PointCoordinate(0.30, 0.60),
                                      PointCoordinate(0.50, 0.60),
                                      PointCoordinate(0.50, 0.75),
                                      PointCoordinate(0.30, 0.75),
                                      PointCoordinate(0.30, 0.60),
                                      # Close the polygon
                                  ]
                              ],
                              # Second part
                              [
                                  [
                                      PointCoordinate(0.65, 0.55),
                                      PointCoordinate(0.85, 0.55),
                                      PointCoordinate(0.85, 0.70),
                                      PointCoordinate(0.65, 0.70),
                                      PointCoordinate(0.65, 0.55),
                                      # Close the polygon
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Bluegold",
                      "bluegold_quality_options": "Plump, Juicy, Large",
                      "blueberry_quality": 9
                  },
                  {
                      "label_ref": "blueberry_017",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Fifth polygon
                              [
                                  # First part
                                  [
                                      PointCoordinate(0.05, 0.05),
                                      PointCoordinate(0.15, 0.05),
                                      PointCoordinate(0.15, 0.10),
                                      PointCoordinate(0.05, 0.10),
                                      PointCoordinate(0.05, 0.05),
                                      # Close the polygon
                                  ]
                              ],
                              [
                                  # Second part
                                  [
                                      PointCoordinate(0.80, 0.05),
                                      PointCoordinate(0.95, 0.05),
                                      PointCoordinate(0.95, 0.10),
                                      PointCoordinate(0.80, 0.10),
                                      PointCoordinate(0.80, 0.05),
                                      # Close the polygon
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Other blueberry type",
                      "Specify blueberry type": "Highbush",
                      "blueberry_quality": 8
                  },
              ],
              105: [
                  {
                      "label_ref": "blueberry_016",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Fourth polygon
                              [
                                  # First part
                                  [
                                      PointCoordinate(0.40, 0.40),
                                      PointCoordinate(0.50, 0.40),
                                      PointCoordinate(0.50, 0.50),
                                      PointCoordinate(0.40, 0.50),
                                      PointCoordinate(0.40, 0.40),
                                      # Close the polygon
                                  ]
                              ],
                              # Second part
                              [
                                  [
                                      PointCoordinate(0.55, 0.55),
                                      PointCoordinate(0.65, 0.55),
                                      PointCoordinate(0.65, 0.65),
                                      PointCoordinate(0.55, 0.65),
                                      PointCoordinate(0.55, 0.55),
                                      # Close the polygon
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Blueray",
                      "blueray_quality_options": "Plump",
                      "blueberry_quality": 6
                  },
                  {
                      "label_ref": "blueberry_014",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Second polygon
                              [
                                  # First part
                                  [
                                      PointCoordinate(0.10, 0.80),
                                      PointCoordinate(0.25, 0.85),
                                      PointCoordinate(0.20, 0.95),
                                      PointCoordinate(0.05, 0.90),
                                      PointCoordinate(0.10, 0.80),
                                      # Close the polygon
                                  ]
                              ],
                              # Second part
                              [
                                  [
                                      PointCoordinate(0.55, 0.75),
                                      PointCoordinate(0.70, 0.80),
                                      PointCoordinate(0.65, 0.95),
                                      PointCoordinate(0.50, 0.90),
                                      PointCoordinate(0.55, 0.75),
                                      # Close the polygon
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Bluegold",
                      "bluegold_quality_options": "Plump, Juicy, Large",
                      "blueberry_quality": 8
                  },
                  {
                      "label_ref": "blueberry_017",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Fifth polygon
                              [
                                  # First part
                                  [
                                      PointCoordinate(0.35, 0.05),
                                      PointCoordinate(0.45, 0.05),
                                      PointCoordinate(0.45, 0.15),
                                      PointCoordinate(0.35, 0.15),
                                      PointCoordinate(0.35, 0.05),
                                      # Close the polygon
                                  ]
                              ],
                              [
                                  # Second part
                                  [
                                      PointCoordinate(0.55, 0.05),
                                      PointCoordinate(0.65, 0.05),
                                      PointCoordinate(0.65, 0.15),
                                      PointCoordinate(0.55, 0.15),
                                      PointCoordinate(0.55, 0.05),
                                      # Close the polygon
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Other blueberry type",
                      "Specify blueberry type": "Highbush",
                      "blueberry_quality": 9
                  },
              ],
          },
      }

      # Loop through each data unit (image, video, etc.)
      for data_unit, frame_coordinates in video_frame_labels.items():
          object_instances_by_label_ref = {}

          # Get the label row for the current data unit
          label_rows = project.list_label_rows_v2(data_title_eq=data_unit)
          assert isinstance(label_rows, list), f"Expected list of label rows for '{data_unit}', got {type(label_rows)}"
          assert label_rows, f"No label rows found for data unit: {data_unit}"

          label_row = label_rows[0]
          assert label_row is not None, f"Label row is None for {data_unit}"

          # Initialize label row using bundle
          with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
              label_row.initialise_labels()
              assert label_row.ontology_structure is not None, f"Ontology not initialized for label row: {data_unit}"

              for frame_number, items in frame_coordinates.items():
                  assert isinstance(frame_number, int), f"Frame number must be int, got {type(frame_number)}"

                  if not isinstance(items, list):  # Single or multiple objects in the frame
                      items = [items]

                  for item in items:
                      label_ref = item["label_ref"]
                      coord = item["coordinates"]
                      blueberry_type = item["blueberry_type"]
                      blueberry_quality = item["blueberry_quality"]

                      assert blueberry_type in {
                          "Bluegold",
                          "Duke",
                          "Blueray",
                          "Other blueberry type",
                      }, f"Unexpected blueberry type '{blueberry_type}' in data unit '{data_unit}'"

                      if label_ref not in object_instances_by_label_ref:
                          polygon_object_instance: ObjectInstance = polygon_ontology_object.create_instance()
                          assert polygon_object_instance is not None, f"Failed to create ObjectInstance for {label_ref}"

                          object_instances_by_label_ref[label_ref] = polygon_object_instance
                          checklist_attribute = None

                          # Set blueberry quality attribute 
                          polygon_object_instance.set_answer(attribute=blueberry_quality_number_attribute, answer=blueberry_quality)

                          # Set blueberry type attribute
                          if blueberry_type == "Bluegold":
                              assert bluegold_option is not None, "Missing 'bluegold_option'"
                              polygon_object_instance.set_answer(
                                  attribute=blueberry_type_radio_attribute, answer=bluegold_option
                              )
                              checklist_attribute = bluegold_checklist_attribute
                          elif blueberry_type == "Duke":
                              assert duke_option is not None, "Missing 'duke_option'"
                              polygon_object_instance.set_answer(attribute=blueberry_type_radio_attribute, answer=duke_option)
                              checklist_attribute = duke_checklist_attribute
                          elif blueberry_type == "Blueray":
                              assert blueray_option is not None, "Missing 'blueray_option'"
                              polygon_object_instance.set_answer(
                                  attribute=blueberry_type_radio_attribute, answer=blueray_option
                              )
                              checklist_attribute = blueray_checklist_attribute
                          elif blueberry_type == "Other blueberry type":
                              assert other_blueberry_option is not None, "Missing 'other_blueberry_option'"
                              polygon_object_instance.set_answer(
                                  attribute=blueberry_type_radio_attribute, answer=other_blueberry_option
                              )
                              text_answer = item.get("Specify blueberry type", "")
                              assert isinstance(text_answer, str), "'Specify blueberry type' must be a string"
                              polygon_object_instance.set_answer(
                                  attribute=other_blueberry_option_text_attribute,
                                  answer=text_answer,
                              )

                          # Set checklist attributes
                          checklist_answers = []
                          quality_key = f"{blueberry_type.lower()}_quality_options"
                          quality_options = item.get(quality_key, "").split(", ")

                          for quality in quality_options:
                              option = None
                              if quality == "Plump":
                                  option = (
                                      bluegold_plump_option
                                      if blueberry_type == "Bluegold"
                                      else duke_plump_option
                                      if blueberry_type == "Duke"
                                      else blueray_plump_option
                                      if blueberry_type == "Blueray"
                                      else None
                                  )
                              elif quality == "Juicy":
                                  option = (
                                      bluegold_juicy_option
                                      if blueberry_type == "Bluegold"
                                      else duke_juicy_option
                                      if blueberry_type == "Duke"
                                      else blueray_juicy_option
                                      if blueberry_type == "Blueray"
                                      else None
                                  )
                              elif quality == "Large":
                                  option = (
                                      bluegold_large_option
                                      if blueberry_type == "Bluegold"
                                      else duke_large_option
                                      if blueberry_type == "Duke"
                                      else blueray_large_option
                                      if blueberry_type == "Blueray"
                                      else None
                                  )

                              if option:
                                  checklist_answers.append(option)
                              else:
                                  assert blueberry_type == "Other blueberry type", (
                                      f"Invalid quality '{quality}' for type '{blueberry_type}'"
                                  )

                          if checklist_attribute and checklist_answers:
                              polygon_object_instance.set_answer(
                                  attribute=checklist_attribute, answer=checklist_answers, overwrite=True
                              )

                      else:
                          polygon_object_instance = object_instances_by_label_ref[label_ref]

                      # Assign the object to the frame and track it
                      polygon_object_instance.set_for_frames(coordinates=coord, frames=frame_number)

              # Add object instances to label_row **only if they have frames assigned**
              for polygon_object_instance in object_instances_by_label_ref.values():
                  assert isinstance(polygon_object_instance, ObjectInstance), "Expected ObjectInstance type"
                  if polygon_object_instance.get_annotation_frames():
                      label_row.add_object_instance(polygon_object_instance)

              # Save label row using the bundle
              assert label_row is not None, "Trying to save a None label row"
              label_row.save(bundle=bundle)

      print("Labels with blueberry type radio buttons, checklist attributes, number classifications and text labels added for all data units.")

      ```
    </CodeGroup>

    <CodeGroup title="Complex Polygons - Donut plus Object">
      <LabelPolygonsImagesVideosExampleBasicDonutPlusObject />

      ```python Donut with Object - Advanced expandable theme={"dark"}

      # Import dependencies
      from pathlib import Path

      from encord import EncordUserClient, Project
      from encord.objects import ChecklistAttribute, Object, ObjectInstance, Option, RadioAttribute, TextAttribute
      from encord.objects.coordinates import PointCoordinate, PolygonCoordinates
      from encord.objects.attributes import NumericAttribute

      SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"
      # SSH_PATH = get_ssh_key() # replace it with access key
      PROJECT_ID = "00000000-0000-0000-0000-000000000000"
      BUNDLE_SIZE = 100

      # Create user client using access key
      user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path=SSH_PATH,
          # For US platform users use "https://api.us.encord.com"
          domain="https://api.encord.com",
      )

      # Get project for which labels are to be added
      project: Project = user_client.get_project(PROJECT_ID)
      assert project is not None, "Project not found — check PROJECT_ID"

      # Get ontology structure
      ontology_structure = project.ontology_structure
      assert ontology_structure is not None, "Ontology structure is missing in the project"

      # Find polygon object for blueberries
      polygon_ontology_object: Object = ontology_structure.get_child_by_title(title="Blueberries", type_=Object)
      assert polygon_ontology_object is not None, "Object 'Blueberries' not found in ontology"

      # Get radio attribute for blueberry type
      blueberry_type_radio_attribute = ontology_structure.get_child_by_title(type_=RadioAttribute, title="Type?")
      assert blueberry_type_radio_attribute is not None, "Radio attribute 'Type?' not found"

      # Find number attribute in the ontology
      blueberry_quality_number_attribute = ontology_structure.get_child_by_title(type_=NumericAttribute, title="Overall Quality")
      assert blueberry_quality_number_attribute is not None, "Number attribute 'Overall Quality' not found in ontology."

      # Get radio options
      bluegold_option = blueberry_type_radio_attribute.get_child_by_title(type_=Option, title="Bluegold")
      assert bluegold_option is not None, "Option 'Bluegold' not found under radio attribute 'Type?'"

      duke_option = blueberry_type_radio_attribute.get_child_by_title(type_=Option, title="Duke")
      assert duke_option is not None, "Option 'Duke' not found under radio attribute 'Type?'"

      blueray_option = blueberry_type_radio_attribute.get_child_by_title(type_=Option, title="Blueray")
      assert blueray_option is not None, "Option 'Blueray' not found under radio attribute 'Type?'"

      other_blueberry_option = blueberry_type_radio_attribute.get_child_by_title(type_=Option, title="Other blueberry type")
      assert other_blueberry_option is not None, "Option 'Other blueberry type' not found under radio attribute 'Type?'"

      # Bluegold Qualities
      bluegold_checklist_attribute = ontology_structure.get_child_by_title(
          type_=ChecklistAttribute, title="Bluegold Qualities?"
      )
      assert bluegold_checklist_attribute is not None, "Checklist attribute 'Bluegold Qualities?' not found"

      bluegold_plump_option = bluegold_checklist_attribute.get_child_by_title(type_=Option, title="Plump")
      assert bluegold_plump_option is not None, "Option 'Plump' not found under 'Bluegold Qualities?'"

      bluegold_juicy_option = bluegold_checklist_attribute.get_child_by_title(type_=Option, title="Juicy")
      assert bluegold_juicy_option is not None, "Option 'Juicy' not found under 'Bluegold Qualities?'"

      bluegold_large_option = bluegold_checklist_attribute.get_child_by_title(type_=Option, title="Large")
      assert bluegold_large_option is not None, "Option 'Large' not found under 'Bluegold Qualities?'"

      # Duke Qualities
      duke_checklist_attribute = ontology_structure.get_child_by_title(type_=ChecklistAttribute, title="Duke Qualities?")
      assert duke_checklist_attribute is not None, "Checklist attribute 'Duke Qualities?' not found"

      duke_plump_option = duke_checklist_attribute.get_child_by_title(type_=Option, title="Plump")
      assert duke_plump_option is not None, "Option 'Plump' not found under 'Duke Qualities?'"

      duke_juicy_option = duke_checklist_attribute.get_child_by_title(type_=Option, title="Juicy")
      assert duke_juicy_option is not None, "Option 'Juicy' not found under 'Duke Qualities?'"

      duke_large_option = duke_checklist_attribute.get_child_by_title(type_=Option, title="Large")
      assert duke_large_option is not None, "Option 'Large' not found under 'Duke Qualities?'"

      # Blueray Qualities
      blueray_checklist_attribute = ontology_structure.get_child_by_title(
          type_=ChecklistAttribute, title="Blueray Qualities?"
      )
      assert blueray_checklist_attribute is not None, "Checklist attribute 'Blueray Qualities?' not found"

      blueray_plump_option = blueray_checklist_attribute.get_child_by_title(type_=Option, title="Plump")
      assert blueray_plump_option is not None, "Option 'Plump' not found under 'Blueray Qualities?'"

      blueray_juicy_option = blueray_checklist_attribute.get_child_by_title(type_=Option, title="Juicy")
      assert blueray_juicy_option is not None, "Option 'Juicy' not found under 'Blueray Qualities?'"

      blueray_large_option = blueray_checklist_attribute.get_child_by_title(type_=Option, title="Large")
      assert blueray_large_option is not None, "Option 'Large' not found under 'Blueray Qualities?'"

      # Other blueberry type — text input
      other_blueberry_option_text_attribute = ontology_structure.get_child_by_title(
          type_=TextAttribute, title="Specify blueberry type"
      )
      assert other_blueberry_option_text_attribute is not None, "Text attribute 'Specify blueberry type' not found"

      # Dictionary of labels per data unit and per frame with blueberry type specified, including quality options
      video_frame_labels = {
          "blueberries-001.jpg": {
              0: {
                  "label_ref": "blueberry_001",
                  "coordinates": PolygonCoordinates(
                      polygons=[
                          # Donut + inner polygon
                          [
                              # Outer ring
                              [
                                  PointCoordinate(0.10, 0.10),
                                  PointCoordinate(0.22, 0.09),
                                  PointCoordinate(0.21, 0.22),
                                  PointCoordinate(0.09, 0.21),
                                  PointCoordinate(0.10, 0.10),
                              ],
                              # Inner ring
                              [
                                  PointCoordinate(0.13, 0.13),
                                  PointCoordinate(0.13, 0.18),
                                  PointCoordinate(0.18, 0.18),
                                  PointCoordinate(0.18, 0.13),
                                  PointCoordinate(0.13, 0.13),
                              ],
                          ],
                          # Shape inside the hole
                          [
                              [
                                  PointCoordinate(0.145, 0.145),
                                  PointCoordinate(0.165, 0.150),
                                  PointCoordinate(0.160, 0.165),
                                  PointCoordinate(0.145, 0.145),
                              ]
                          ],
                      ]
                  ),
                  "blueberry_type": "Bluegold",
                  "bluegold_quality_options": "Plump, Juicy",
                   "blueberry_quality": 7
              }
          },
          "blueberries-010.jpg": {
              0: [
                  {
                      "label_ref": "blueberry_002",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # First donut + inner polygon
                              [
                                  # Outer ring
                                  [
                                      PointCoordinate(0.10, 0.10),
                                      PointCoordinate(0.22, 0.09),
                                      PointCoordinate(0.21, 0.22),
                                      PointCoordinate(0.09, 0.21),
                                      PointCoordinate(0.10, 0.10),
                                  ],
                                  # Inner ring
                                  [
                                      PointCoordinate(0.13, 0.13),
                                      PointCoordinate(0.13, 0.18),
                                      PointCoordinate(0.18, 0.18),
                                      PointCoordinate(0.18, 0.13),
                                      PointCoordinate(0.13, 0.13),
                                  ],
                              ],
                              # Shape inside the hole
                              [
                                  [
                                      PointCoordinate(0.145, 0.145),
                                      PointCoordinate(0.165, 0.150),
                                      PointCoordinate(0.160, 0.165),
                                      PointCoordinate(0.145, 0.145),
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Duke",
                      "duke_quality_options": "Plump, Juicy, Large",
                       "blueberry_quality": 9
                  },
                  {
                      "label_ref": "blueberry_003",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Second donut + inner polygon
                              [
                                  # Outer ring
                                  [
                                      PointCoordinate(0.30, 0.10),
                                      PointCoordinate(0.42, 0.11),
                                      PointCoordinate(0.41, 0.22),
                                      PointCoordinate(0.29, 0.21),
                                      PointCoordinate(0.30, 0.10),
                                  ],
                                  # Inner ring
                                  [
                                      PointCoordinate(0.33, 0.13),
                                      PointCoordinate(0.33, 0.18),
                                      PointCoordinate(0.38, 0.18),
                                      PointCoordinate(0.38, 0.13),
                                      PointCoordinate(0.33, 0.13),
                                  ],
                              ],
                              # Shape inside the hole
                              [
                                  [
                                      PointCoordinate(0.345, 0.145),
                                      PointCoordinate(0.355, 0.155),
                                      PointCoordinate(0.350, 0.165),
                                      PointCoordinate(0.340, 0.160),
                                      PointCoordinate(0.345, 0.145),
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Blueray",
                      "blueray_quality_options": "Plump",
                       "blueberry_quality": 6
                  },
                  {
                      "label_ref": "blueberry_004",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Third donut + inner polygon
                              [
                                  # Outer ring
                                  [
                                      PointCoordinate(0.10, 0.30),
                                      PointCoordinate(0.22, 0.29),
                                      PointCoordinate(0.21, 0.42),
                                      PointCoordinate(0.09, 0.41),
                                      PointCoordinate(0.10, 0.30),
                                  ],
                                  # Inner ring
                                  [
                                      PointCoordinate(0.13, 0.33),
                                      PointCoordinate(0.13, 0.38),
                                      PointCoordinate(0.18, 0.38),
                                      PointCoordinate(0.18, 0.33),
                                      PointCoordinate(0.13, 0.33),
                                  ],
                              ],
                              # Shape inside the hole
                              [
                                  [
                                      PointCoordinate(0.145, 0.345),
                                      PointCoordinate(0.155, 0.355),
                                      PointCoordinate(0.150, 0.370),
                                      PointCoordinate(0.140, 0.360),
                                      PointCoordinate(0.145, 0.345),
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Other blueberry type",
                      "Specify blueberry type": "Highbush",
                       "blueberry_quality": 3
                  },
              ],
          },
          "blueberries-ig": {
              0: {
                  "label_ref": "blueberry_005",
                  "coordinates": PolygonCoordinates(
                      polygons=[
                          # Donut + inner polygon
                          [
                              # Outer ring
                              [
                                  PointCoordinate(0.10, 0.10),
                                  PointCoordinate(0.22, 0.09),
                                  PointCoordinate(0.21, 0.22),
                                  PointCoordinate(0.09, 0.21),
                                  PointCoordinate(0.10, 0.10),
                              ],
                              # Inner ring
                              [
                                  PointCoordinate(0.13, 0.13),
                                  PointCoordinate(0.13, 0.18),
                                  PointCoordinate(0.18, 0.18),
                                  PointCoordinate(0.18, 0.13),
                                  PointCoordinate(0.13, 0.13),
                              ],
                          ],
                          # Shape inside the hole
                          [
                              [
                                  PointCoordinate(0.145, 0.145),
                                  PointCoordinate(0.165, 0.150),
                                  PointCoordinate(0.160, 0.165),
                                  PointCoordinate(0.145, 0.145),
                              ]
                          ],
                      ]
                  ),
                  "blueberry_type": "Bluegold",
                  "bluegold_quality_options": "Plump, Juicy",
                   "blueberry_quality": 7
              },
              2: [
                  {
                      "label_ref": "blueberry_006",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # First donut + inner polygon
                              [
                                  # Outer ring
                                  [
                                      PointCoordinate(0.10, 0.10),
                                      PointCoordinate(0.22, 0.09),
                                      PointCoordinate(0.21, 0.22),
                                      PointCoordinate(0.09, 0.21),
                                      PointCoordinate(0.10, 0.10),
                                  ],
                                  # Inner ring
                                  [
                                      PointCoordinate(0.13, 0.13),
                                      PointCoordinate(0.13, 0.18),
                                      PointCoordinate(0.18, 0.18),
                                      PointCoordinate(0.18, 0.13),
                                      PointCoordinate(0.13, 0.13),
                                  ],
                              ],
                              # Shape inside the hole
                              [
                                  [
                                      PointCoordinate(0.145, 0.145),
                                      PointCoordinate(0.165, 0.150),
                                      PointCoordinate(0.160, 0.165),
                                      PointCoordinate(0.145, 0.145),
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Duke",
                      "duke_quality_options": "Large",
                       "blueberry_quality": 5
                  },
                  {
                      "label_ref": "blueberry_007",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Second donut + inner polygon
                              [
                                  # Outer ring
                                  [
                                      PointCoordinate(0.30, 0.10),
                                      PointCoordinate(0.42, 0.11),
                                      PointCoordinate(0.41, 0.22),
                                      PointCoordinate(0.29, 0.21),
                                      PointCoordinate(0.30, 0.10),
                                  ],
                                  # Inner ring
                                  [
                                      PointCoordinate(0.33, 0.13),
                                      PointCoordinate(0.33, 0.18),
                                      PointCoordinate(0.38, 0.18),
                                      PointCoordinate(0.38, 0.13),
                                      PointCoordinate(0.33, 0.13),
                                  ],
                              ],
                              # Shape inside the hole
                              [
                                  [
                                      PointCoordinate(0.345, 0.145),
                                      PointCoordinate(0.355, 0.155),
                                      PointCoordinate(0.350, 0.165),
                                      PointCoordinate(0.340, 0.160),
                                      PointCoordinate(0.345, 0.145),
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Blueray",
                      "blueray_quality_options": "Plump",
                       "blueberry_quality": 5
                  },
                  {
                      "label_ref": "blueberry_008",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Third donut + inner polygon
                              [
                                  # Outer ring
                                  [
                                      PointCoordinate(0.10, 0.30),
                                      PointCoordinate(0.22, 0.29),
                                      PointCoordinate(0.21, 0.42),
                                      PointCoordinate(0.09, 0.41),
                                      PointCoordinate(0.10, 0.30),
                                  ],
                                  # Inner ring
                                  [
                                      PointCoordinate(0.13, 0.33),
                                      PointCoordinate(0.13, 0.38),
                                      PointCoordinate(0.18, 0.38),
                                      PointCoordinate(0.18, 0.33),
                                      PointCoordinate(0.13, 0.33),
                                  ],
                              ],
                              # Shape inside the hole
                              [
                                  [
                                      PointCoordinate(0.145, 0.345),
                                      PointCoordinate(0.155, 0.355),
                                      PointCoordinate(0.150, 0.370),
                                      PointCoordinate(0.140, 0.360),
                                      PointCoordinate(0.145, 0.345),
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Other blueberry type",
                      "Specify blueberry type": "Lowbush",
                       "blueberry_quality": 3
                  },
              ],
          },
          "blueberries-is": {
              0: {
                  "label_ref": "blueberry_009",
                  "coordinates": PolygonCoordinates(
                      polygons=[
                          # Donut + inner polygon
                          [
                              # Outer ring
                              [
                                  PointCoordinate(0.10, 0.10),
                                  PointCoordinate(0.22, 0.09),
                                  PointCoordinate(0.21, 0.22),
                                  PointCoordinate(0.09, 0.21),
                                  PointCoordinate(0.10, 0.10),
                              ],
                              # Inner ring
                              [
                                  PointCoordinate(0.13, 0.13),
                                  PointCoordinate(0.13, 0.18),
                                  PointCoordinate(0.18, 0.18),
                                  PointCoordinate(0.18, 0.13),
                                  PointCoordinate(0.13, 0.13),
                              ],
                          ],
                          # Shape inside the hole
                          [
                              [
                                  PointCoordinate(0.145, 0.145),
                                  PointCoordinate(0.165, 0.150),
                                  PointCoordinate(0.160, 0.165),
                                  PointCoordinate(0.145, 0.145),
                              ]
                          ],
                      ]
                  ),
                  "blueberry_type": "Bluegold",
                  "bluegold_quality_options": "Plump",
                   "blueberry_quality": 4
              },
              3: [
                  {
                      "label_ref": "blueberry_010",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # First donut + inner polygon
                              [
                                  # Outer ring
                                  [
                                      PointCoordinate(0.10, 0.10),
                                      PointCoordinate(0.22, 0.09),
                                      PointCoordinate(0.21, 0.22),
                                      PointCoordinate(0.09, 0.21),
                                      PointCoordinate(0.10, 0.10),
                                  ],
                                  # Inner ring
                                  [
                                      PointCoordinate(0.13, 0.13),
                                      PointCoordinate(0.13, 0.18),
                                      PointCoordinate(0.18, 0.18),
                                      PointCoordinate(0.18, 0.13),
                                      PointCoordinate(0.13, 0.13),
                                  ],
                              ],
                              # Shape inside the hole
                              [
                                  [
                                      PointCoordinate(0.145, 0.145),
                                      PointCoordinate(0.165, 0.150),
                                      PointCoordinate(0.160, 0.165),
                                      PointCoordinate(0.145, 0.145),
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Duke",
                      "duke_quality_options": "Plump, Juicy, Large",
                       "blueberry_quality": 9
                  },
                  {
                      "label_ref": "blueberry_011",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Second donut + inner polygon
                              [
                                  # Outer ring
                                  [
                                      PointCoordinate(0.30, 0.10),
                                      PointCoordinate(0.42, 0.11),
                                      PointCoordinate(0.41, 0.22),
                                      PointCoordinate(0.29, 0.21),
                                      PointCoordinate(0.30, 0.10),
                                  ],
                                  # Inner ring
                                  [
                                      PointCoordinate(0.33, 0.13),
                                      PointCoordinate(0.33, 0.18),
                                      PointCoordinate(0.38, 0.18),
                                      PointCoordinate(0.38, 0.13),
                                      PointCoordinate(0.33, 0.13),
                                  ],
                              ],
                              # Shape inside the hole
                              [
                                  [
                                      PointCoordinate(0.345, 0.145),
                                      PointCoordinate(0.355, 0.155),
                                      PointCoordinate(0.350, 0.165),
                                      PointCoordinate(0.340, 0.160),
                                      PointCoordinate(0.345, 0.145),
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Blueray",
                      "blueray_quality_options": "Plump",
                       "blueberry_quality": 6
                  },
                  {
                      "label_ref": "blueberry_012",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Third donut + inner polygon
                              [
                                  # Outer ring
                                  [
                                      PointCoordinate(0.10, 0.30),
                                      PointCoordinate(0.22, 0.29),
                                      PointCoordinate(0.21, 0.42),
                                      PointCoordinate(0.09, 0.41),
                                      PointCoordinate(0.10, 0.30),
                                  ],
                                  # Inner ring
                                  [
                                      PointCoordinate(0.13, 0.33),
                                      PointCoordinate(0.13, 0.38),
                                      PointCoordinate(0.18, 0.38),
                                      PointCoordinate(0.18, 0.33),
                                      PointCoordinate(0.13, 0.33),
                                  ],
                              ],
                              # Shape inside the hole
                              [
                                  [
                                      PointCoordinate(0.145, 0.345),
                                      PointCoordinate(0.155, 0.355),
                                      PointCoordinate(0.150, 0.370),
                                      PointCoordinate(0.140, 0.360),
                                      PointCoordinate(0.145, 0.345),
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Other blueberry type",
                      "Specify blueberry type": "Highbush",
                       "blueberry_quality": 5
                  },
              ],
          },
          "blueberries-vid-001.mp4": {
              103: [
                  {
                      "label_ref": "blueberry_013",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # First donut + inner polygon
                              [
                                  # Outer ring
                                  [
                                      PointCoordinate(0.10, 0.10),
                                      PointCoordinate(0.22, 0.09),
                                      PointCoordinate(0.21, 0.22),
                                      PointCoordinate(0.09, 0.21),
                                      PointCoordinate(0.10, 0.10),
                                  ],
                                  # Inner ring
                                  [
                                      PointCoordinate(0.13, 0.13),
                                      PointCoordinate(0.13, 0.18),
                                      PointCoordinate(0.18, 0.18),
                                      PointCoordinate(0.18, 0.13),
                                      PointCoordinate(0.13, 0.13),
                                  ],
                              ],
                              # Shape inside the hole
                              [
                                  [
                                      PointCoordinate(0.145, 0.145),
                                      PointCoordinate(0.165, 0.150),
                                      PointCoordinate(0.160, 0.165),
                                      PointCoordinate(0.145, 0.145),
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Blueray",
                      "blueray_quality_options": "Plump",
                       "blueberry_quality": 4
                  },
                  {
                      "label_ref": "blueberry_014",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Second donut + inner polygon
                              [
                                  # Outer ring
                                  [
                                      PointCoordinate(0.30, 0.10),
                                      PointCoordinate(0.42, 0.11),
                                      PointCoordinate(0.41, 0.22),
                                      PointCoordinate(0.29, 0.21),
                                      PointCoordinate(0.30, 0.10),
                                  ],
                                  # Inner ring
                                  [
                                      PointCoordinate(0.33, 0.13),
                                      PointCoordinate(0.33, 0.18),
                                      PointCoordinate(0.38, 0.18),
                                      PointCoordinate(0.38, 0.13),
                                      PointCoordinate(0.33, 0.13),
                                  ],
                              ],
                              # Shape inside the hole
                              [
                                  [
                                      PointCoordinate(0.345, 0.145),
                                      PointCoordinate(0.355, 0.155),
                                      PointCoordinate(0.350, 0.165),
                                      PointCoordinate(0.340, 0.160),
                                      PointCoordinate(0.345, 0.145),
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Bluegold",
                      "bluegold_quality_options": "Plump, Juicy, Large",
                       "blueberry_quality": 9
                  },
                  {
                      "label_ref": "blueberry_015",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Third donut + inner polygon
                              [
                                  # Outer ring
                                  [
                                      PointCoordinate(0.10, 0.30),
                                      PointCoordinate(0.22, 0.29),
                                      PointCoordinate(0.21, 0.42),
                                      PointCoordinate(0.09, 0.41),
                                      PointCoordinate(0.10, 0.30),
                                  ],
                                  # Inner ring
                                  [
                                      PointCoordinate(0.13, 0.33),
                                      PointCoordinate(0.13, 0.38),
                                      PointCoordinate(0.18, 0.38),
                                      PointCoordinate(0.18, 0.33),
                                      PointCoordinate(0.13, 0.33),
                                  ],
                              ],
                              # Shape inside the hole
                              [
                                  [
                                      PointCoordinate(0.145, 0.345),
                                      PointCoordinate(0.155, 0.355),
                                      PointCoordinate(0.150, 0.370),
                                      PointCoordinate(0.140, 0.360),
                                      PointCoordinate(0.145, 0.345),
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Other blueberry type",
                      "Specify blueberry type": "Lowbush",
                      "blueberry_quality": 8
                  },
              ],
              104: [
                  {
                      "label_ref": "blueberry_016",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Fourth donut + inner polygon
                              [
                                  # Outer ring
                                  [
                                      PointCoordinate(0.30, 0.30),
                                      PointCoordinate(0.42, 0.31),
                                      PointCoordinate(0.41, 0.42),
                                      PointCoordinate(0.29, 0.41),
                                      PointCoordinate(0.30, 0.30),
                                  ],
                                  # Inner ring
                                  [
                                      PointCoordinate(0.33, 0.33),
                                      PointCoordinate(0.33, 0.38),
                                      PointCoordinate(0.38, 0.38),
                                      PointCoordinate(0.38, 0.33),
                                      PointCoordinate(0.33, 0.33),
                                  ],
                              ],
                              # Shape inside the hole
                              [
                                  [
                                      PointCoordinate(0.345, 0.345),
                                      PointCoordinate(0.360, 0.350),
                                      PointCoordinate(0.355, 0.365),
                                      PointCoordinate(0.345, 0.345),
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Blueray",
                      "blueray_quality_options": "Plump",
                       "blueberry_quality": 7
                  },
                  {
                      "label_ref": "blueberry_014",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Second donut + inner polygon
                              [
                                  # Outer ring
                                  [
                                      PointCoordinate(0.31, 0.10),
                                      PointCoordinate(0.45, 0.12),
                                      PointCoordinate(0.43, 0.25),
                                      PointCoordinate(0.30, 0.22),
                                      PointCoordinate(0.31, 0.10),
                                  ],
                                  # Inner ring
                                  [
                                      PointCoordinate(0.34, 0.14),
                                      PointCoordinate(0.34, 0.19),
                                      PointCoordinate(0.39, 0.20),
                                      PointCoordinate(0.40, 0.15),
                                      PointCoordinate(0.34, 0.14),
                                  ],
                              ],
                              # Shape inside the hole
                              [
                                  [
                                      PointCoordinate(0.355, 0.155),
                                      PointCoordinate(0.370, 0.160),
                                      PointCoordinate(0.365, 0.175),
                                      PointCoordinate(0.350, 0.170),
                                      PointCoordinate(0.355, 0.155),
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Bluegold",
                      "bluegold_quality_options": "Plump, Juicy, Large",
                       "blueberry_quality": 9
                  },
                  {
                      "label_ref": "blueberry_017",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Fifth donut + inner polygon
                              [
                                  # Outer ring
                                  [
                                      PointCoordinate(0.50, 0.10),
                                      PointCoordinate(0.62, 0.12),
                                      PointCoordinate(0.61, 0.22),
                                      PointCoordinate(0.49, 0.21),
                                      PointCoordinate(0.50, 0.10),
                                  ],
                                  # Inner ring
                                  [
                                      PointCoordinate(0.53, 0.13),
                                      PointCoordinate(0.53, 0.18),
                                      PointCoordinate(0.58, 0.18),
                                      PointCoordinate(0.58, 0.13),
                                      PointCoordinate(0.53, 0.13),
                                  ],
                              ],
                              # Shape inside the hole
                              [
                                  [
                                      PointCoordinate(0.545, 0.145),
                                      PointCoordinate(0.560, 0.150),
                                      PointCoordinate(0.555, 0.165),
                                      PointCoordinate(0.540, 0.160),
                                      PointCoordinate(0.545, 0.145),
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Other blueberry type",
                      "Specify blueberry type": "Highbush",
                       "blueberry_quality": 2
                  },
              ],
              105: [
                  {
                      "label_ref": "blueberry_016",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Fourth donut + inner polygon
                              [
                                  # Outer ring
                                  [
                                      PointCoordinate(0.33, 0.33),
                                      PointCoordinate(0.47, 0.34),
                                      PointCoordinate(0.45, 0.46),
                                      PointCoordinate(0.31, 0.45),
                                      PointCoordinate(0.33, 0.33),
                                  ],
                                  # Inner ring
                                  [
                                      PointCoordinate(0.36, 0.36),
                                      PointCoordinate(0.37, 0.41),
                                      PointCoordinate(0.42, 0.42),
                                      PointCoordinate(0.43, 0.37),
                                      PointCoordinate(0.36, 0.36),
                                  ],
                              ],
                              # Shape inside the hole
                              [
                                  [
                                      PointCoordinate(0.375, 0.375),
                                      PointCoordinate(0.395, 0.380),
                                      PointCoordinate(0.390, 0.395),
                                      PointCoordinate(0.370, 0.390),
                                      PointCoordinate(0.375, 0.375),
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Blueray",
                      "blueray_quality_options": "Plump",
                       "blueberry_quality": 5
                  },
                  {
                      "label_ref": "blueberry_014",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Second donut + inner polygon
                              [
                                  # Outer ring
                                  [
                                      PointCoordinate(0.33, 0.12),
                                      PointCoordinate(0.46, 0.13),
                                      PointCoordinate(0.44, 0.26),
                                      PointCoordinate(0.31, 0.25),
                                      PointCoordinate(0.33, 0.12),
                                  ],
                                  # Inner ring
                                  [
                                      PointCoordinate(0.36, 0.16),
                                      PointCoordinate(0.37, 0.21),
                                      PointCoordinate(0.41, 0.22),
                                      PointCoordinate(0.42, 0.17),
                                      PointCoordinate(0.36, 0.16),
                                  ],
                              ],
                              # Shape inside the hole
                              [
                                  [
                                      PointCoordinate(0.375, 0.175),
                                      PointCoordinate(0.390, 0.180),
                                      PointCoordinate(0.385, 0.195),
                                      PointCoordinate(0.370, 0.190),
                                      PointCoordinate(0.375, 0.175),
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Bluegold",
                      "bluegold_quality_options": "Plump, Juicy, Large",
                       "blueberry_quality": 8
                  },
                  {
                      "label_ref": "blueberry_017",
                      "coordinates": PolygonCoordinates(
                          polygons=[
                              # Fifth donut + inner polygon
                              [
                                  # Outer ring
                                  [
                                      PointCoordinate(0.53, 0.13),
                                      PointCoordinate(0.67, 0.14),
                                      PointCoordinate(0.66, 0.26),
                                      PointCoordinate(0.52, 0.25),
                                      PointCoordinate(0.53, 0.13),
                                  ],
                                  # Inner ring
                                  [
                                      PointCoordinate(0.56, 0.16),
                                      PointCoordinate(0.57, 0.21),
                                      PointCoordinate(0.62, 0.22),
                                      PointCoordinate(0.63, 0.17),
                                      PointCoordinate(0.56, 0.16),
                                  ],
                              ],
                              # Shape inside the hole
                              [
                                  [
                                      PointCoordinate(0.575, 0.175),
                                      PointCoordinate(0.595, 0.180),
                                      PointCoordinate(0.590, 0.195),
                                      PointCoordinate(0.570, 0.190),
                                      PointCoordinate(0.575, 0.175),
                                  ]
                              ],
                          ]
                      ),
                      "blueberry_type": "Other blueberry type",
                      "Specify blueberry type": "Highbush",
                       "blueberry_quality": 6
                  },
              ],
          },
      }

      # Loop through each data unit (image, video, etc.)
      for data_unit, frame_coordinates in video_frame_labels.items():
          object_instances_by_label_ref = {}

          # Get the label row for the current data unit
          label_rows = project.list_label_rows_v2(data_title_eq=data_unit)
          assert isinstance(label_rows, list), f"Expected list of label rows for '{data_unit}', got {type(label_rows)}"
          assert label_rows, f"No label rows found for data unit: {data_unit}"

          label_row = label_rows[0]
          assert label_row is not None, f"Label row is None for {data_unit}"

          # Initialize label row using bundle
          with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
              label_row.initialise_labels()
              assert label_row.ontology_structure is not None, f"Ontology not initialized for label row: {data_unit}"

              for frame_number, items in frame_coordinates.items():
                  assert isinstance(frame_number, int), f"Frame number must be int, got {type(frame_number)}"

                  if not isinstance(items, list):  # Single or multiple objects in the frame
                      items = [items]

                  for item in items:
                      label_ref = item["label_ref"]
                      coord = item["coordinates"]
                      blueberry_type = item["blueberry_type"]
                      blueberry_quality = item["blueberry_quality"]

                      assert blueberry_type in {
                          "Bluegold",
                          "Duke",
                          "Blueray",
                          "Other blueberry type",
                      }, f"Unexpected blueberry type '{blueberry_type}' in data unit '{data_unit}'"

                      if label_ref not in object_instances_by_label_ref:
                          polygon_object_instance: ObjectInstance = polygon_ontology_object.create_instance()
                          assert polygon_object_instance is not None, f"Failed to create ObjectInstance for {label_ref}"

                          object_instances_by_label_ref[label_ref] = polygon_object_instance
                          checklist_attribute = None

                          # Set blueberry quality attribute 
                          polygon_object_instance.set_answer(attribute=blueberry_quality_number_attribute, answer=blueberry_quality)

                          # Set blueberry type attribute
                          if blueberry_type == "Bluegold":
                              assert bluegold_option is not None, "Missing 'bluegold_option'"
                              polygon_object_instance.set_answer(
                                  attribute=blueberry_type_radio_attribute, answer=bluegold_option
                              )
                              checklist_attribute = bluegold_checklist_attribute
                          elif blueberry_type == "Duke":
                              assert duke_option is not None, "Missing 'duke_option'"
                              polygon_object_instance.set_answer(attribute=blueberry_type_radio_attribute, answer=duke_option)
                              checklist_attribute = duke_checklist_attribute
                          elif blueberry_type == "Blueray":
                              assert blueray_option is not None, "Missing 'blueray_option'"
                              polygon_object_instance.set_answer(
                                  attribute=blueberry_type_radio_attribute, answer=blueray_option
                              )
                              checklist_attribute = blueray_checklist_attribute
                          elif blueberry_type == "Other blueberry type":
                              assert other_blueberry_option is not None, "Missing 'other_blueberry_option'"
                              polygon_object_instance.set_answer(
                                  attribute=blueberry_type_radio_attribute, answer=other_blueberry_option
                              )
                              text_answer = item.get("Specify blueberry type", "")
                              assert isinstance(text_answer, str), "'Specify blueberry type' must be a string"
                              polygon_object_instance.set_answer(
                                  attribute=other_blueberry_option_text_attribute,
                                  answer=text_answer,
                              )

                          # Set checklist attributes
                          checklist_answers = []
                          quality_key = f"{blueberry_type.lower()}_quality_options"
                          quality_options = item.get(quality_key, "").split(", ")

                          for quality in quality_options:
                              option = None
                              if quality == "Plump":
                                  option = (
                                      bluegold_plump_option
                                      if blueberry_type == "Bluegold"
                                      else duke_plump_option
                                      if blueberry_type == "Duke"
                                      else blueray_plump_option
                                      if blueberry_type == "Blueray"
                                      else None
                                  )
                              elif quality == "Juicy":
                                  option = (
                                      bluegold_juicy_option
                                      if blueberry_type == "Bluegold"
                                      else duke_juicy_option
                                      if blueberry_type == "Duke"
                                      else blueray_juicy_option
                                      if blueberry_type == "Blueray"
                                      else None
                                  )
                              elif quality == "Large":
                                  option = (
                                      bluegold_large_option
                                      if blueberry_type == "Bluegold"
                                      else duke_large_option
                                      if blueberry_type == "Duke"
                                      else blueray_large_option
                                      if blueberry_type == "Blueray"
                                      else None
                                  )

                              if option:
                                  checklist_answers.append(option)
                              else:
                                  assert blueberry_type == "Other blueberry type", (
                                      f"Invalid quality '{quality}' for type '{blueberry_type}'"
                                  )

                          if checklist_attribute and checklist_answers:
                              polygon_object_instance.set_answer(
                                  attribute=checklist_attribute, answer=checklist_answers, overwrite=True
                              )

                      else:
                          polygon_object_instance = object_instances_by_label_ref[label_ref]

                      # Assign the object to the frame and track it
                      polygon_object_instance.set_for_frames(coordinates=coord, frames=frame_number)

              # Add object instances to label_row **only if they have frames assigned**
              for polygon_object_instance in object_instances_by_label_ref.values():
                  assert isinstance(polygon_object_instance, ObjectInstance), "Expected ObjectInstance type"
                  if polygon_object_instance.get_annotation_frames():
                      label_row.add_object_instance(polygon_object_instance)

              # Save label row using the bundle
              assert label_row is not None, "Trying to save a None label row"
              label_row.save(bundle=bundle)

      print("Labels with blueberry type radio buttons, checklist attributes, number attributes, and text labels added for all data units.")

      ```
    </CodeGroup>
  </Accordion>
</AccordionGroup>

<AccordionGroup>
  <Accordion title="DEPRECATED - Polygons">
    While this method works for simple polygons, we STRONGLY recommend using the new Polygon method for creating simple polygons.

    This example includes the following:

    * Single image labeling
    * Image Group labeling
    * Image Sequence labeling
    * Video labeling
    * Radio button options
    * Checklist options
    * Text input
    * Number input

    <CodeGroup>
      ```python DEPRECATED - Polygons expandable theme={"dark"}

      # Import dependencies
      from pathlib import Path

      from encord import EncordUserClient, Project
      from encord.objects import ChecklistAttribute, Object, ObjectInstance, Option, RadioAttribute, TextAttribute
      from encord.objects.attributes import NumericAttribute
      from encord.objects.coordinates import PointCoordinate, PolygonCoordinates

      # User input
      SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"
      # SSH_PATH = get_ssh_key() # replace it with access key
      PROJECT_ID = "00000000-0000-0000-0000-000000000000"
      BUNDLE_SIZE = 100

      # Create user client using access key
      user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path=SSH_PATH,
          # For US platform users use "https://api.us.encord.com"
          domain="https://api.encord.com",
      )

      # Get project for which labels are to be added
      project: Project = user_client.get_project(PROJECT_ID)
      assert project is not None, "Project not found — check PROJECT_ID"

      # Get ontology structure
      ontology_structure = project.ontology_structure
      assert ontology_structure is not None, "Ontology structure is missing in the project"

      # Find polygon object for blueberries
      polygon_ontology_object: Object = ontology_structure.get_child_by_title(title="Blueberries", type_=Object)
      assert polygon_ontology_object is not None, "Object 'Blueberries' not found in ontology"

      # Get radio attribute for blueberry type
      blueberry_type_radio_attribute = ontology_structure.get_child_by_title(type_=RadioAttribute, title="Type?")
      assert blueberry_type_radio_attribute is not None, "Radio attribute 'Type?' not found"

      # Find number attribute in the ontology
      blueberry_quality_number_attribute = ontology_structure.get_child_by_title(type_=NumericAttribute, title="Overall Quality")
      assert blueberry_quality_number_attribute is not None, "Number attribute 'Overall Quality' not found in ontology."

      # Get radio options
      bluegold_option = blueberry_type_radio_attribute.get_child_by_title(type_=Option, title="Bluegold")
      assert bluegold_option is not None, "Option 'Bluegold' not found under radio attribute 'Type?'"

      duke_option = blueberry_type_radio_attribute.get_child_by_title(type_=Option, title="Duke")
      assert duke_option is not None, "Option 'Duke' not found under radio attribute 'Type?'"

      blueray_option = blueberry_type_radio_attribute.get_child_by_title(type_=Option, title="Blueray")
      assert blueray_option is not None, "Option 'Blueray' not found under radio attribute 'Type?'"

      other_blueberry_option = blueberry_type_radio_attribute.get_child_by_title(type_=Option, title="Other blueberry type")
      assert other_blueberry_option is not None, "Option 'Other blueberry type' not found under radio attribute 'Type?'"

      # Bluegold Qualities
      bluegold_checklist_attribute = ontology_structure.get_child_by_title(
          type_=ChecklistAttribute, title="Bluegold Qualities?"
      )
      assert bluegold_checklist_attribute is not None, "Checklist attribute 'Bluegold Qualities?' not found"

      bluegold_plump_option = bluegold_checklist_attribute.get_child_by_title(type_=Option, title="Plump")
      assert bluegold_plump_option is not None, "Option 'Plump' not found under 'Bluegold Qualities?'"

      bluegold_juicy_option = bluegold_checklist_attribute.get_child_by_title(type_=Option, title="Juicy")
      assert bluegold_juicy_option is not None, "Option 'Juicy' not found under 'Bluegold Qualities?'"

      bluegold_large_option = bluegold_checklist_attribute.get_child_by_title(type_=Option, title="Large")
      assert bluegold_large_option is not None, "Option 'Large' not found under 'Bluegold Qualities?'"

      # Duke Qualities
      duke_checklist_attribute = ontology_structure.get_child_by_title(type_=ChecklistAttribute, title="Duke Qualities?")
      assert duke_checklist_attribute is not None, "Checklist attribute 'Duke Qualities?' not found"

      duke_plump_option = duke_checklist_attribute.get_child_by_title(type_=Option, title="Plump")
      assert duke_plump_option is not None, "Option 'Plump' not found under 'Duke Qualities?'"

      duke_juicy_option = duke_checklist_attribute.get_child_by_title(type_=Option, title="Juicy")
      assert duke_juicy_option is not None, "Option 'Juicy' not found under 'Duke Qualities?'"

      duke_large_option = duke_checklist_attribute.get_child_by_title(type_=Option, title="Large")
      assert duke_large_option is not None, "Option 'Large' not found under 'Duke Qualities?'"

      # Blueray Qualities
      blueray_checklist_attribute = ontology_structure.get_child_by_title(
          type_=ChecklistAttribute, title="Blueray Qualities?"
      )
      assert blueray_checklist_attribute is not None, "Checklist attribute 'Blueray Qualities?' not found"

      blueray_plump_option = blueray_checklist_attribute.get_child_by_title(type_=Option, title="Plump")
      assert blueray_plump_option is not None, "Option 'Plump' not found under 'Blueray Qualities?'"

      blueray_juicy_option = blueray_checklist_attribute.get_child_by_title(type_=Option, title="Juicy")
      assert blueray_juicy_option is not None, "Option 'Juicy' not found under 'Blueray Qualities?'"

      blueray_large_option = blueray_checklist_attribute.get_child_by_title(type_=Option, title="Large")
      assert blueray_large_option is not None, "Option 'Large' not found under 'Blueray Qualities?'"

      # Other blueberry type — text input
      other_blueberry_option_text_attribute = ontology_structure.get_child_by_title(
          type_=TextAttribute, title="Specify blueberry type"
      )
      assert other_blueberry_option_text_attribute is not None, "Text attribute 'Specify blueberry type' not found"

      # Dictionary of labels per data unit and per frame with blueberry type specified, including quality options
      video_frame_labels = {
          "blueberries-001.jpg": {
              0: {
                  "label_ref": "blueberry_001",
                  "coordinates": PolygonCoordinates(
                      [
                          PointCoordinate(0.01, 0.02),
                          PointCoordinate(0.03, 0.03),
                          PointCoordinate(0.05, 0.02),
                          PointCoordinate(0.04, 0.01),
                          PointCoordinate(0.02, 0.01),
                      ]
                  ),
                  "blueberry_type": "Bluegold",
                  "bluegold_quality_options": "Plump, Juicy",
                  "blueberry_quality": 7
              }
          },
          "blueberries-010.jpg": {
              0: [
                  {
                      "label_ref": "blueberry_002",
                      "coordinates": PolygonCoordinates(
                          [
                              PointCoordinate(0.01, 0.02),
                              PointCoordinate(0.03, 0.03),
                              PointCoordinate(0.05, 0.02),
                              PointCoordinate(0.04, 0.01),
                              PointCoordinate(0.02, 0.01),
                          ]
                      ),
                      "blueberry_type": "Duke",
                      "duke_quality_options": "Plump, Juicy, Large",
                      "blueberry_quality": 9
                  },
                  {
                      "label_ref": "blueberry_003",
                      "coordinates": PolygonCoordinates(
                          [
                              PointCoordinate(0.04, 0.05),
                              PointCoordinate(0.06, 0.06),
                              PointCoordinate(0.08, 0.05),
                              PointCoordinate(0.07, 0.04),
                              PointCoordinate(0.05, 0.04),
                          ]
                      ),
                      "blueberry_type": "Blueray",
                      "blueray_quality_options": "Plump",
                  },
                  {
                      "label_ref": "blueberry_004",
                      "coordinates": PolygonCoordinates(
                          [
                              PointCoordinate(0.07, 0.02),
                              PointCoordinate(0.09, 0.03),
                              PointCoordinate(0.11, 0.02),
                              PointCoordinate(0.10, 0.01),
                              PointCoordinate(0.08, 0.01),
                          ]
                      ),
                      "blueberry_type": "Other blueberry type",
                      "Specify blueberry type": "Highbush",
                  },
              ],
          },
          "blueberries-ig": {
              0: {
                  "label_ref": "blueberry_005",
                  "coordinates": PolygonCoordinates(
                      [
                          PointCoordinate(0.01, 0.02),
                          PointCoordinate(0.03, 0.03),
                          PointCoordinate(0.05, 0.02),
                          PointCoordinate(0.04, 0.01),
                          PointCoordinate(0.02, 0.01),
                      ]
                  ),
                  "blueberry_type": "Bluegold",
                  "bluegold_quality_options": "Plump, Juicy",
                  "blueberry_quality": 8
              },
              2: [
                  {
                      "label_ref": "blueberry_006",
                      "coordinates": PolygonCoordinates(
                          [
                              PointCoordinate(0.01, 0.02),
                              PointCoordinate(0.03, 0.03),
                              PointCoordinate(0.05, 0.02),
                              PointCoordinate(0.04, 0.01),
                              PointCoordinate(0.02, 0.01),
                          ]
                      ),
                      "blueberry_type": "Duke",
                      "duke_quality_options": "Large",
                      "blueberry_quality": 7
                  },
                  {
                      "label_ref": "blueberry_007",
                      "coordinates": PolygonCoordinates(
                          [
                              PointCoordinate(0.04, 0.05),
                              PointCoordinate(0.06, 0.06),
                              PointCoordinate(0.08, 0.05),
                              PointCoordinate(0.07, 0.04),
                              PointCoordinate(0.05, 0.04),
                          ]
                      ),
                      "blueberry_type": "Blueray",
                      "blueray_quality_options": "Plump",
                      "blueberry_quality": 4
                  },
                  {
                      "label_ref": "blueberry_008",
                      "coordinates": PolygonCoordinates(
                          [
                              PointCoordinate(0.07, 0.02),
                              PointCoordinate(0.09, 0.03),
                              PointCoordinate(0.11, 0.02),
                              PointCoordinate(0.10, 0.01),
                              PointCoordinate(0.08, 0.01),
                          ]
                      ),
                      "blueberry_type": "Other blueberry type",
                      "Specify blueberry type": "Lowbush",
                      "blueberry_quality": 3
                  },
              ],
          },
          "blueberries-is": {
              0: {
                  "label_ref": "blueberry_009",
                  "coordinates": PolygonCoordinates(
                      [
                          PointCoordinate(0.01, 0.02),
                          PointCoordinate(0.03, 0.03),
                          PointCoordinate(0.05, 0.02),
                          PointCoordinate(0.04, 0.01),
                          PointCoordinate(0.02, 0.01),
                      ]
                  ),
                  "blueberry_type": "Bluegold",
                  "bluegold_quality_options": "Plump",
                  "blueberry_quality": 5
              },
              3: [
                  {
                      "label_ref": "blueberry_010",
                      "coordinates": PolygonCoordinates(
                          [
                              PointCoordinate(0.01, 0.02),
                              PointCoordinate(0.03, 0.03),
                              PointCoordinate(0.05, 0.02),
                              PointCoordinate(0.04, 0.01),
                              PointCoordinate(0.02, 0.01),
                          ]
                      ),
                      "blueberry_type": "Duke",
                      "duke_quality_options": "Plump, Juicy, Large",
                      "blueberry_quality": 9
                  },
                  {
                      "label_ref": "blueberry_011",
                      "coordinates": PolygonCoordinates(
                          [
                              PointCoordinate(0.04, 0.05),
                              PointCoordinate(0.06, 0.06),
                              PointCoordinate(0.08, 0.05),
                              PointCoordinate(0.07, 0.04),
                              PointCoordinate(0.05, 0.04),
                          ]
                      ),
                      "blueberry_type": "Blueray",
                      "blueray_quality_options": "Plump",
                      "blueberry_quality": 5
                  },
                  {
                      "label_ref": "blueberry_012",
                      "coordinates": PolygonCoordinates(
                          [
                              PointCoordinate(0.07, 0.02),
                              PointCoordinate(0.09, 0.03),
                              PointCoordinate(0.11, 0.02),
                              PointCoordinate(0.10, 0.01),
                              PointCoordinate(0.08, 0.01),
                          ]
                      ),
                      "blueberry_type": "Other blueberry type",
                      "Specify blueberry type": "Powder Blue",
                      "blueberry_quality": 4
                  },
              ],
          },
          "blueberries-vid-001.mp4": {
              103: [
                  {
                      "label_ref": "blueberry_013",
                      "coordinates": PolygonCoordinates(
                          [
                              PointCoordinate(0.01, 0.02),
                              PointCoordinate(0.03, 0.03),
                              PointCoordinate(0.05, 0.02),
                              PointCoordinate(0.04, 0.01),
                              PointCoordinate(0.02, 0.01),
                          ]
                      ),
                      "blueberry_type": "Blueray",
                      "blueray_quality_options": "Plump",
                      "blueberry_quality": 4
                  },
                  {
                      "label_ref": "blueberry_014",
                      "coordinates": PolygonCoordinates(
                          [
                              PointCoordinate(0.04, 0.05),
                              PointCoordinate(0.06, 0.06),
                              PointCoordinate(0.08, 0.05),
                              PointCoordinate(0.07, 0.04),
                              PointCoordinate(0.05, 0.04),
                          ]
                      ),
                      "blueberry_type": "Bluegold",
                      "bluegold_quality_options": "Plump, Juicy, Large",
                      "blueberry_quality": 9
                  },
                  {
                      "label_ref": "blueberry_015",
                      "coordinates": PolygonCoordinates(
                          [
                              PointCoordinate(0.07, 0.02),
                              PointCoordinate(0.09, 0.03),
                              PointCoordinate(0.11, 0.02),
                              PointCoordinate(0.10, 0.01),
                              PointCoordinate(0.08, 0.01),
                          ]
                      ),
                      "blueberry_type": "Other blueberry type",
                      "Specify blueberry type": "Lowbush",
                      "blueberry_quality": 6
                  },
              ],
              104: [
                  {
                      "label_ref": "blueberry_016",
                      "coordinates": PolygonCoordinates(
                          [
                              PointCoordinate(0.01, 0.02),
                              PointCoordinate(0.03, 0.03),
                              PointCoordinate(0.05, 0.02),
                              PointCoordinate(0.04, 0.01),
                              PointCoordinate(0.02, 0.01),
                          ]
                      ),
                      "blueberry_type": "Blueray",
                      "blueray_quality_options": "Plump",
                  },
                  {
                      "label_ref": "blueberry_014",
                      "coordinates": PolygonCoordinates(
                          [
                              PointCoordinate(0.041, 0.052),
                              PointCoordinate(0.061, 0.062),
                              PointCoordinate(0.081, 0.052),
                              PointCoordinate(0.071, 0.042),
                              PointCoordinate(0.051, 0.042),
                          ]
                      ),
                      "blueberry_type": "Bluegold",
                      "bluegold_quality_options": "Plump, Juicy, Large",
                      "blueberry_quality": 9
                  },
                  {
                      "label_ref": "blueberry_017",
                      "coordinates": PolygonCoordinates(
                          [
                              PointCoordinate(0.07, 0.02),
                              PointCoordinate(0.09, 0.03),
                              PointCoordinate(0.11, 0.02),
                              PointCoordinate(0.10, 0.01),
                              PointCoordinate(0.08, 0.01),
                          ]
                      ),
                      "blueberry_type": "Other blueberry type",
                      "Specify blueberry type": "Highbush",
                      "blueberry_quality": 6
                  },
              ],
              105: [
                  {
                      "label_ref": "blueberry_016",
                      "coordinates": PolygonCoordinates(
                          [
                              PointCoordinate(0.011, 0.022),
                              PointCoordinate(0.031, 0.032),
                              PointCoordinate(0.051, 0.022),
                              PointCoordinate(0.041, 0.012),
                              PointCoordinate(0.021, 0.012),
                          ]
                      ),
                      "blueberry_type": "Blueray",
                      "blueray_quality_options": "Plump",
                      "blueberry_quality": 6
                  },
                  {
                      "label_ref": "blueberry_014",
                      "coordinates": PolygonCoordinates(
                          [
                              PointCoordinate(0.043, 0.055),
                              PointCoordinate(0.063, 0.065),
                              PointCoordinate(0.083, 0.055),
                              PointCoordinate(0.073, 0.045),
                              PointCoordinate(0.053, 0.045),
                          ]
                      ),
                      "blueberry_type": "Bluegold",
                      "bluegold_quality_options": "Plump, Juicy, Large",
                      "blueberry_quality": 7
                  },
                  {
                      "label_ref": "blueberry_017",
                      "coordinates": PolygonCoordinates(
                          [
                              PointCoordinate(0.071, 0.022),
                              PointCoordinate(0.091, 0.032),
                              PointCoordinate(0.111, 0.022),
                              PointCoordinate(0.101, 0.012),
                              PointCoordinate(0.081, 0.012),
                          ]
                      ),
                      "blueberry_type": "Other blueberry type",
                      "Specify blueberry type": "Powder Blue",
                      "blueberry_quality": 1
                  },
              ],
          },
      }


      # Loop through each data unit (image, video, etc.)
      for data_unit, frame_coordinates in video_frame_labels.items():
          object_instances_by_label_ref = {}

          # Get the label row for the current data unit
          label_rows = project.list_label_rows_v2(data_title_eq=data_unit)
          assert isinstance(label_rows, list), f"Expected list of label rows for '{data_unit}', got {type(label_rows)}"
          assert label_rows, f"No label rows found for data unit: {data_unit}"

          label_row = label_rows[0]
          assert label_row is not None, f"Label row is None for {data_unit}"

          # Initialize label row using bundle
          with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
              label_row.initialise_labels()
              assert label_row.ontology_structure is not None, f"Ontology not initialized for label row: {data_unit}"

              for frame_number, items in frame_coordinates.items():
                  assert isinstance(frame_number, int), f"Frame number must be int, got {type(frame_number)}"

                  if not isinstance(items, list):  # Single or multiple objects in the frame
                      items = [items]

                  for item in items:
                      label_ref = item["label_ref"]
                      coord = item["coordinates"]
                      blueberry_type = item["blueberry_type"]
                      blueberry_quality = item["blueberry_quality"]

                      assert blueberry_type in {
                          "Bluegold",
                          "Duke",
                          "Blueray",
                          "Other blueberry type",
                      }, f"Unexpected blueberry type '{blueberry_type}' in data unit '{data_unit}'"

                      if label_ref not in object_instances_by_label_ref:
                          polygon_object_instance: ObjectInstance = polygon_ontology_object.create_instance()
                          assert polygon_object_instance is not None, f"Failed to create ObjectInstance for {label_ref}"

                          object_instances_by_label_ref[label_ref] = polygon_object_instance
                          checklist_attribute = None

                          # Set blueberry quality attribute 
                          polygon_object_instance.set_answer(attribute=blueberry_quality_number_attribute, answer=blueberry_quality)

                          # Set blueberry type attribute
                          if blueberry_type == "Bluegold":
                              assert bluegold_option is not None, "Missing 'bluegold_option'"
                              polygon_object_instance.set_answer(
                                  attribute=blueberry_type_radio_attribute, answer=bluegold_option
                              )
                              checklist_attribute = bluegold_checklist_attribute
                          elif blueberry_type == "Duke":
                              assert duke_option is not None, "Missing 'duke_option'"
                              polygon_object_instance.set_answer(attribute=blueberry_type_radio_attribute, answer=duke_option)
                              checklist_attribute = duke_checklist_attribute
                          elif blueberry_type == "Blueray":
                              assert blueray_option is not None, "Missing 'blueray_option'"
                              polygon_object_instance.set_answer(
                                  attribute=blueberry_type_radio_attribute, answer=blueray_option
                              )
                              checklist_attribute = blueray_checklist_attribute
                          elif blueberry_type == "Other blueberry type":
                              assert other_blueberry_option is not None, "Missing 'other_blueberry_option'"
                              polygon_object_instance.set_answer(
                                  attribute=blueberry_type_radio_attribute, answer=other_blueberry_option
                              )
                              text_answer = item.get("Specify blueberry type", "")
                              assert isinstance(text_answer, str), "'Specify blueberry type' must be a string"
                              polygon_object_instance.set_answer(
                                  attribute=other_blueberry_option_text_attribute,
                                  answer=text_answer,
                              )

                          # Set checklist attributes
                          checklist_answers = []
                          quality_key = f"{blueberry_type.lower()}_quality_options"
                          quality_options = item.get(quality_key, "").split(", ")

                          for quality in quality_options:
                              option = None
                              if quality == "Plump":
                                  option = (
                                      bluegold_plump_option
                                      if blueberry_type == "Bluegold"
                                      else duke_plump_option
                                      if blueberry_type == "Duke"
                                      else blueray_plump_option
                                      if blueberry_type == "Blueray"
                                      else None
                                  )
                              elif quality == "Juicy":
                                  option = (
                                      bluegold_juicy_option
                                      if blueberry_type == "Bluegold"
                                      else duke_juicy_option
                                      if blueberry_type == "Duke"
                                      else blueray_juicy_option
                                      if blueberry_type == "Blueray"
                                      else None
                                  )
                              elif quality == "Large":
                                  option = (
                                      bluegold_large_option
                                      if blueberry_type == "Bluegold"
                                      else duke_large_option
                                      if blueberry_type == "Duke"
                                      else blueray_large_option
                                      if blueberry_type == "Blueray"
                                      else None
                                  )

                              if option:
                                  checklist_answers.append(option)
                              else:
                                  assert blueberry_type == "Other blueberry type", (
                                      f"Invalid quality '{quality}' for type '{blueberry_type}'"
                                  )

                          if checklist_attribute and checklist_answers:
                              polygon_object_instance.set_answer(
                                  attribute=checklist_attribute, answer=checklist_answers, overwrite=True
                              )

                      else:
                          polygon_object_instance = object_instances_by_label_ref[label_ref]

                      # Assign the object to the frame and track it
                      polygon_object_instance.set_for_frames(coordinates=coord, frames=frame_number)

              # Add object instances to label_row **only if they have frames assigned**
              for polygon_object_instance in object_instances_by_label_ref.values():
                  assert isinstance(polygon_object_instance, ObjectInstance), "Expected ObjectInstance type"
                  if polygon_object_instance.get_annotation_frames():
                      label_row.add_object_instance(polygon_object_instance)

              # Save label row using the bundle
              assert label_row is not None, "Trying to save a None label row"
              label_row.save(bundle=bundle)

      print("Labels with blueberry type radio buttons, checklist attributes, number attributes, and text labels added for all data units.")

      ```
    </CodeGroup>
  </Accordion>
</AccordionGroup>

<AccordionGroup>
  <Accordion title="Polyline">
    **Basic**

    This example includes the following:

    * Single image labeling
    * Image Group labeling
    * Image Sequence labeling
    * Video labeling

    **Advanced**

    This example includes the following:

    * Single image labeling
    * Image Group labeling
    * Image Sequence labeling
    * Video labeling
    * Radio button options
    * Checklist options
    * Text input
    * Number input

    **Polyline Ontology**

    ![Polyline Ontology](https://storage.googleapis.com/docs-media.encord.com/static/img/sdk/labels-polylines-branches.png)

    <CodeGroup>
      ```python Polylines Images/Videos - Basic expandable theme={"dark"}

      from encord import EncordUserClient, Project
      from encord.objects import Object, ObjectInstance
      from encord.objects.coordinates import PolylineCoordinates, PointCoordinate

      # User input
      SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"  # Replace with the file path to your SSH private key
      PROJECT_ID = "00000000-0000-0000-0000-000000000000"  # Replace with the unique Project ID
      BUNDLE_SIZE = 10

      # Data unit titles in your Project
      IMAGE_TITLE = "cherries-001.jpg"
      IMG_GROUP_TITLE = "cherries-ig"
      IMG_SEQUENCE_TITLE = "cherries-is"
      VIDEO_TITLE = "cherries-vid-001.mp4"

      # Ontology object title for your POLYLINE object
      POLYLINE_OBJECT_TITLE = "Branches"

      # Authorize connection to Encord
      user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path=SSH_PATH,
          # For US platform users use domain="https://api.us.encord.com"
          domain="https://api.encord.com",
      )

      project: Project = user_client.get_project(PROJECT_ID)

      # Find a POLYLINE object in the ontology by title
      ontology_structure = project.ontology_structure
      polyline_object: Object = ontology_structure.get_child_by_title(title=POLYLINE_OBJECT_TITLE, type_=Object)
      assert polyline_object is not None, f"Polyline object '{POLYLINE_OBJECT_TITLE}' not found in ontology."

      # Initialise label rows
      label_rows = {}
      all_titles = [IMAGE_TITLE, IMG_GROUP_TITLE, IMG_SEQUENCE_TITLE, VIDEO_TITLE]

      with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
          for title in all_titles:
              rows = project.list_label_rows_v2(data_title_eq=title)
              assert isinstance(rows, list), f"Expected list for '{title}', got {type(rows)}"
              if not rows:
                  print(f"Skipping: No label row found for {title}")
                  continue
              lr = rows[0]
              lr.initialise_labels(bundle=bundle)
              assert lr.ontology_structure is not None, f"Ontology not initialized for '{title}'"
              label_rows[title] = lr

      # Polyline coordinates: A simple bent line with 5 vertices
      pline = PolylineCoordinates([
          PointCoordinate(0.10, 0.80),
          PointCoordinate(0.20, 0.60),
          PointCoordinate(0.40, 0.55),
          PointCoordinate(0.65, 0.40),
          PointCoordinate(0.85, 0.35),
      ])

      # Create instances and attach to frames
      label_rows_to_save = []

      # 1. One image > frame 0
      image_lr = label_rows.get(IMAGE_TITLE)
      if image_lr is not None:
          inst: ObjectInstance = polyline_object.create_instance()
          inst.set_for_frames(coordinates=pline, frames=0)
          image_lr.add_object_instance(inst)
          label_rows_to_save.append(image_lr)

      # 2. One image group > frame 0
      img_group_lr = label_rows.get(IMG_GROUP_TITLE)
      if img_group_lr is not None:
          inst: ObjectInstance = polyline_object.create_instance()
          inst.set_for_frames(coordinates=pline, frames=0)
          img_group_lr.add_object_instance(inst)
          label_rows_to_save.append(img_group_lr)

      # 3. One image sequence > frame 0
      img_sequence_lr = label_rows.get(IMG_SEQUENCE_TITLE)
      if img_sequence_lr is not None:
          inst: ObjectInstance = polyline_object.create_instance()
          inst.set_for_frames(coordinates=pline, frames=0)
          img_sequence_lr.add_object_instance(inst)
          label_rows_to_save.append(img_sequence_lr)

      # 4. One video > reuse SAME instance across 3 consecutive frames (frames 100, 101, 102)
      video_lr = label_rows.get(VIDEO_TITLE)
      if video_lr is not None:
          inst: ObjectInstance = polyline_object.create_instance()
          for f in [100, 101, 102]:
              inst.set_for_frames(coordinates=pline, frames=f)
          video_lr.add_object_instance(inst)
          label_rows_to_save.append(video_lr)

      # Save label rows
      with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
          for lr in label_rows_to_save:
              lr.save(bundle=bundle)
              print(f"Saved label row for {lr.data_title}")

      print("Done: created one polyline on image, image group, image sequence, and 3 video frames.")

      ```

      ```python Polylines Images/Videos - Advanced expandable theme={"dark"}

      # Import dependencies
      from pathlib import Path

      from encord import EncordUserClient, Project
      from encord.objects import ChecklistAttribute, Object, ObjectInstance, Option, RadioAttribute, TextAttribute
      from encord.objects.coordinates import PointCoordinate, PolylineCoordinates
      from encord.objects.attributes import NumericAttribute

      # User input
      SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"
      # SSH_PATH = get_ssh_key() # replace it with access key
      PROJECT_ID = "00000000-0000-0000-0000-000000000000"
      BUNDLE_SIZE = 100

      # Create user client using access key
      user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path=SSH_PATH,
          # For US platform users use "https://api.us.encord.com"
          domain="https://api.encord.com",
      )

      # Get project for which labels are to be added
      project: Project = user_client.get_project(PROJECT_ID)
      assert project is not None, "Project not found — check PROJECT_ID"

      # Get ontology structure
      ontology_structure = project.ontology_structure
      assert ontology_structure is not None, "Ontology structure is missing in the project"

      # Get polyline object for branches
      polyline_ontology_object: Object = ontology_structure.get_child_by_title(title="Branches", type_=Object)
      assert polyline_ontology_object is not None, "Polyline object 'Branches' not found in ontology"

      # Get radio attribute for branch type
      branch_type_radio_attribute = ontology_structure.get_child_by_title(type_=RadioAttribute, title="Type?")
      assert branch_type_radio_attribute is not None, "Radio attribute 'Type?' not found in ontology"

      # Get radio options
      fruiting_spur_option = branch_type_radio_attribute.get_child_by_title(type_=Option, title="Fruiting spur")
      assert fruiting_spur_option is not None, "Option 'Fruiting spur' not found under radio attribute 'Type?'"

      sucker_option = branch_type_radio_attribute.get_child_by_title(type_=Option, title="Sucker")
      assert sucker_option is not None, "Option 'Sucker' not found under radio attribute 'Type?'"

      side_shoot_option = branch_type_radio_attribute.get_child_by_title(type_=Option, title="Side shoot")
      assert side_shoot_option is not None, "Option 'Side shoot' not found under radio attribute 'Type?'"

      other_branch_option = branch_type_radio_attribute.get_child_by_title(type_=Option, title="Other branch type")
      assert other_branch_option is not None, "Option 'Other branch type' not found under radio attribute 'Type?'"

      # Find number attribute in the ontology
      quality_number_attribute = ontology_structure.get_child_by_title(type_=NumericAttribute, title="Overall Quality")
      assert quality_number_attribute is not None, "Number attribute 'Overall Quality' not found in ontology."

      # Fruiting spur Qualities
      fruiting_spur_checklist_attribute = ontology_structure.get_child_by_title(
          type_=ChecklistAttribute, title="Fruiting spur Qualities?"
      )
      assert fruiting_spur_checklist_attribute is not None, "Checklist attribute 'Fruiting spur Qualities?' not found"

      fruiting_spur_short_length_option = fruiting_spur_checklist_attribute.get_child_by_title(
          type_=Option, title="Short length"
      )
      assert fruiting_spur_short_length_option is not None, "Option 'Short length' not found under 'Fruiting spur Qualities?'"

      fruiting_spur_high_bud_density_option = fruiting_spur_checklist_attribute.get_child_by_title(
          type_=Option, title="High bud density"
      )
      assert fruiting_spur_high_bud_density_option is not None, (
          "Option 'High bud density' not found under 'Fruiting spur Qualities?'"
      )

      fruiting_spur_healthy_option = fruiting_spur_checklist_attribute.get_child_by_title(type_=Option, title="Healthy")
      assert fruiting_spur_healthy_option is not None, "Option 'Healthy' not found under 'Fruiting spur Qualities?'"

      # Sucker Qualities
      sucker_checklist_attribute = ontology_structure.get_child_by_title(type_=ChecklistAttribute, title="Sucker Qualities?")
      assert sucker_checklist_attribute is not None, "Checklist attribute 'Sucker Qualities?' not found"

      sucker_short_length_option = sucker_checklist_attribute.get_child_by_title(type_=Option, title="Short length")
      assert sucker_short_length_option is not None, "Option 'Short length' not found under 'Sucker Qualities?'"

      sucker_high_bud_density_option = sucker_checklist_attribute.get_child_by_title(type_=Option, title="High bud density")
      assert sucker_high_bud_density_option is not None, "Option 'High bud density' not found under 'Sucker Qualities?'"

      sucker_healthy_option = sucker_checklist_attribute.get_child_by_title(type_=Option, title="Healthy")
      assert sucker_healthy_option is not None, "Option 'Healthy' not found under 'Sucker Qualities?'"

      # Side shoot Qualities
      side_shoot_checklist_attribute = ontology_structure.get_child_by_title(
          type_=ChecklistAttribute, title="Side shoot Qualities?"
      )
      assert side_shoot_checklist_attribute is not None, "Checklist attribute 'Side shoot Qualities?' not found"

      side_shoot_short_length_option = side_shoot_checklist_attribute.get_child_by_title(type_=Option, title="Short length")
      assert side_shoot_short_length_option is not None, "Option 'Short length' not found under 'Side shoot Qualities?'"

      side_shoot_high_bud_density_option = side_shoot_checklist_attribute.get_child_by_title(
          type_=Option, title="High bud density"
      )
      assert side_shoot_high_bud_density_option is not None, (
          "Option 'High bud density' not found under 'Side shoot Qualities?'"
      )

      side_shoot_healthy_option = side_shoot_checklist_attribute.get_child_by_title(type_=Option, title="Healthy")
      assert side_shoot_healthy_option is not None, "Option 'Healthy' not found under 'Side shoot Qualities?'"

      # Other branch type text attribute
      other_branch_option_text_attribute = ontology_structure.get_child_by_title(
          type_=TextAttribute, title="Specify branch type"
      )
      assert other_branch_option_text_attribute is not None, "Text attribute 'Specify branch type' not found"


      # Dictionary of labels per data unit and per frame with branch type specified, including quality options
      video_image_frame_labels = {
          "cherries-001.jpg": {
              0: {
                  "label_ref": "branch_001",
                  "coordinates": PolylineCoordinates(
                      [
                          PointCoordinate(0.013, 0.023),
                          PointCoordinate(0.033, 0.033),
                          PointCoordinate(0.053, 0.023),
                          PointCoordinate(0.043, 0.013),
                      ]
                  ),
                  "branch_type": "Fruiting spur",
                  "fruiting_spur_quality_options": "Short length, High bud density",
                  "quality_number": 8
              }
          },
          "cherries-010.jpg": {
              0: [
                  {
                      "label_ref": "branch_002",
                      "coordinates": PolylineCoordinates(
                          [
                              PointCoordinate(0.03, 0.023),
                              PointCoordinate(0.033, 0.033),
                              PointCoordinate(0.053, 0.033),
                              PointCoordinate(0.043, 0.013),
                          ]
                      ),
                      "branch_type": "Sucker",
                      "sucker_quality_options": "Short length, High bud density, Healthy",
                      "quality_number": 7
                  },
                  {
                      "label_ref": "branch_003",
                      "coordinates": PolylineCoordinates(
                          [
                              PointCoordinate(0.043, 0.053),
                              PointCoordinate(0.063, 0.063),
                              PointCoordinate(0.083, 0.053),
                              PointCoordinate(0.073, 0.043),
                          ]
                      ),
                      "branch_type": "Side shoot",
                      "side_shoot_quality_options": "Short length",
                      "quality_number": 8
                  },
                  {
                      "label_ref": "branch_004",
                      "coordinates": PolylineCoordinates(
                          [
                              PointCoordinate(0.073, 0.023),
                              PointCoordinate(0.093, 0.033),
                              PointCoordinate(0.113, 0.023),
                              PointCoordinate(0.103, 0.013),
                          ]
                      ),
                      "branch_type": "Other branch type",
                      "Specify branch type": "Cane",
                      "quality_number": 5
                  },
              ],
          },
          "cherries-ig": {
              0: {
                  "label_ref": "branch_005",
                  "coordinates": PolylineCoordinates(
                      [
                          PointCoordinate(0.013, 0.023),
                          PointCoordinate(0.033, 0.033),
                          PointCoordinate(0.053, 0.023),
                          PointCoordinate(0.043, 0.013),
                      ]
                  ),
                  "branch_type": "Fruiting spur",
                  "fruiting_spur_quality_options": "Short length, High bud density",
                  "quality_number": 9
              },
              2: [
                  {
                      "label_ref": "branch_006",
                      "coordinates": PolylineCoordinates(
                          [
                              PointCoordinate(0.013, 0.023),
                              PointCoordinate(0.033, 0.033),
                              PointCoordinate(0.053, 0.023),
                              PointCoordinate(0.043, 0.013),
                          ]
                      ),
                      "branch_type": "Sucker",
                      "sucker_quality_options": "Healthy",
                      "quality_number": 6
                  },
                  {
                      "label_ref": "branch_007",
                      "coordinates": PolylineCoordinates(
                          [
                              PointCoordinate(0.043, 0.053),
                              PointCoordinate(0.063, 0.063),
                              PointCoordinate(0.083, 0.053),
                              PointCoordinate(0.073, 0.043),
                          ]
                      ),
                      "branch_type": "Side shoot",
                      "side_shoot_quality_options": "Short length",
                      "quality_number": 5
                  },
                  {
                      "label_ref": "branch_008",
                      "coordinates": PolylineCoordinates(
                          [
                              PointCoordinate(0.073, 0.023),
                              PointCoordinate(0.093, 0.033),
                              PointCoordinate(0.113, 0.023),
                              PointCoordinate(0.103, 0.013),
                          ]
                      ),
                      "branch_type": "Other branch type",
                      "Specify branch type": "Cane",
                      "quality_number": 4
                  },
              ],
          },
          "cherries-is": {
              0: {
                  "label_ref": "branch_009",
                  "coordinates": PolylineCoordinates(
                      [
                          PointCoordinate(0.013, 0.023),
                          PointCoordinate(0.033, 0.033),
                          PointCoordinate(0.053, 0.023),
                          PointCoordinate(0.043, 0.013),
                      ]
                  ),
                  "branch_type": "Fruiting spur",
                  "fruiting_spur_quality_options": "Short length",
                  "quality_number": 7
              },
              3: [
                  {
                      "label_ref": "branch_010",
                      "coordinates": PolylineCoordinates(
                          [
                              PointCoordinate(0.013, 0.023),
                              PointCoordinate(0.033, 0.033),
                              PointCoordinate(0.053, 0.023),
                              PointCoordinate(0.043, 0.013),
                          ]
                      ),
                      "branch_type": "Sucker",
                      "sucker_quality_options": "Short length, High bud density, Healthy",
                      "quality_number": 9
                  },
                  {
                      "label_ref": "branch_011",
                      "coordinates": PolylineCoordinates(
                          [
                              PointCoordinate(0.043, 0.053),
                              PointCoordinate(0.063, 0.063),
                              PointCoordinate(0.083, 0.053),
                              PointCoordinate(0.073, 0.043),
                          ]
                      ),
                      "branch_type": "Side shoot",
                      "side_shoot_quality_options": "Short length",
                      "quality_number": 6
                  },
                  {
                      "label_ref": "branch_012",
                      "coordinates": PolylineCoordinates(
                          [
                              PointCoordinate(0.073, 0.023),
                              PointCoordinate(0.093, 0.033),
                              PointCoordinate(0.113, 0.023),
                              PointCoordinate(0.103, 0.013),
                          ]
                      ),
                      "branch_type": "Other branch type",
                      "Specify branch type": "Cane",
                      "quality_number": 7
                  },
              ],
          },
          "cherries-vid-001.mp4": {
              103: [
                  {
                      "label_ref": "branch_013",
                      "coordinates": PolylineCoordinates(
                          [
                              PointCoordinate(0.013, 0.023),
                              PointCoordinate(0.033, 0.033),
                              PointCoordinate(0.053, 0.023),
                              PointCoordinate(0.043, 0.013),
                          ]
                      ),
                      "branch_type": "Side shoot",
                      "side_shoot_quality_options": "Short length",
                      "quality_number": 8
                  },
                  {
                      "label_ref": "branch_014",
                      "coordinates": PolylineCoordinates(
                          [
                              PointCoordinate(0.043, 0.053),
                              PointCoordinate(0.063, 0.063),
                              PointCoordinate(0.083, 0.053),
                              PointCoordinate(0.073, 0.043),
                          ]
                      ),
                      "branch_type": "Fruiting spur",
                      "fruiting_spur_quality_options": "Short length, High bud density, Healthy",
                      "quality_number": 9
                  },
                  {
                      "label_ref": "branch_015",
                      "coordinates": PolylineCoordinates(
                          [
                              PointCoordinate(0.073, 0.023),
                              PointCoordinate(0.093, 0.033),
                              PointCoordinate(0.113, 0.023),
                              PointCoordinate(0.103, 0.013),
                          ]
                      ),
                      "branch_type": "Other branch type",
                      "Specify branch type": "Cane",
                      "quality_number": 5
                  },
              ],
              104: [
                  {
                      "label_ref": "branch_016",
                      "coordinates": PolylineCoordinates(
                          [
                              PointCoordinate(0.013, 0.023),
                              PointCoordinate(0.033, 0.033),
                              PointCoordinate(0.053, 0.023),
                              PointCoordinate(0.043, 0.013),
                          ]
                      ),
                      "branch_type": "Side shoot",
                      "side_shoot_quality_options": "Short length",
                      "quality_number": 8
                  },
                  {
                      "label_ref": "branch_014",
                      "coordinates": PolylineCoordinates(
                          [
                              PointCoordinate(0.0413, 0.0523),
                              PointCoordinate(0.0613, 0.0623),
                              PointCoordinate(0.0813, 0.0523),
                              PointCoordinate(0.0713, 0.0423),
                          ]
                      ),
                      "branch_type": "Fruiting spur",
                      "fruiting_spur_quality_options": "Short length, High bud density, Healthy",
                      "quality_number": 7
                  },
                  {
                      "label_ref": "branch_017",
                      "coordinates": PolylineCoordinates(
                          [
                              PointCoordinate(0.073, 0.023),
                              PointCoordinate(0.093, 0.033),
                              PointCoordinate(0.113, 0.023),
                              PointCoordinate(0.103, 0.013),
                          ]
                      ),
                      "branch_type": "Other branch type",
                      "Specify branch type": "Cane",
                      "quality_number": 4
                  },
              ],
              105: [
                  {
                      "label_ref": "branch_016",
                      "coordinates": PolylineCoordinates(
                          [
                              PointCoordinate(0.0113, 0.0223),
                              PointCoordinate(0.0313, 0.0323),
                              PointCoordinate(0.0513, 0.0223),
                              PointCoordinate(0.0413, 0.0123),
                          ]
                      ),
                      "branch_type": "Side shoot",
                      "side_shoot_quality_options": "Short length",
                      "quality_number": 3
                  },
                  {
                      "label_ref": "branch_014",
                      "coordinates": PolylineCoordinates(
                          [
                              PointCoordinate(0.0433, 0.0553),
                              PointCoordinate(0.0633, 0.0653),
                              PointCoordinate(0.0833, 0.0553),
                              PointCoordinate(0.0733, 0.0453),
                          ]
                      ),
                      "branch_type": "Fruiting spur",
                      "fruiting_spur_quality_options": "Short length, High bud density, Healthy",
                      "quality_number": 9
                  },
                  {
                      "label_ref": "branch_017",
                      "coordinates": PolylineCoordinates(
                          [
                              PointCoordinate(0.0713, 0.0223),
                              PointCoordinate(0.0913, 0.0323),
                              PointCoordinate(0.1113, 0.0223),
                              PointCoordinate(0.1013, 0.0123),
                          ]
                      ),
                      "branch_type": "Other branch type",
                      "Specify branch type": "Cane",
                      "quality_number": 2
                  },
              ],
          },
      }

      # Cache label rows after initialization
      label_row_map = {}

      # Step 1: Initialize all label rows using a bundle
      with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
          for data_unit in video_image_frame_labels.keys():
              label_rows = project.list_label_rows_v2(data_title_eq=data_unit)
              assert isinstance(label_rows, list), f"Expected list of label rows for '{data_unit}', got {type(label_rows)}"

              if not label_rows:
                  print(f"Skipping: No label row found for {data_unit}")
                  continue

              label_row = label_rows[0]
              label_row.initialise_labels(bundle=bundle)
              assert label_row.ontology_structure is not None, f"Ontology not initialized for label row: {data_unit}"

              label_row_map[data_unit] = label_row  # Cache the initialized label row

      # Step 2: Process all frame coordinates and prepare label rows for saving
      label_rows_to_save = []

      for data_unit, frame_coordinates in video_image_frame_labels.items():
          label_row = label_row_map.get(data_unit)
          assert label_row is not None, f"Label row not initialized for {data_unit}"

          object_instances_by_label_ref = {}

          for frame_number, items in frame_coordinates.items():
              assert isinstance(frame_number, int), f"Frame number must be int, got {type(frame_number)}"
              if not isinstance(items, list):
                  items = [items]

              for item in items:
                  label_ref = item["label_ref"]
                  coord = item["coordinates"]
                  branch_type = item["branch_type"]
                  quality_number = item["quality_number"]


                  assert branch_type in {
                      "Fruiting spur",
                      "Sucker",
                      "Side shoot",
                      "Other branch type",
                  }, f"Unexpected branch type '{branch_type}' in {data_unit}"

                  if label_ref not in object_instances_by_label_ref:
                      polyline_object_instance: ObjectInstance = polyline_ontology_object.create_instance()
                      assert polyline_object_instance is not None, "Failed to create ObjectInstance"
                      checklist_attribute = None
                      quality_options = []

                      # Set quality number attribute 
                      polyline_object_instance.set_answer(attribute=quality_number_attribute, answer=quality_number)

                      # Assign radio and checklist attributes based on branch type
                      if branch_type == "Fruiting spur":
                          assert fruiting_spur_option is not None, "Missing 'fruiting_spur_option'"
                          polyline_object_instance.set_answer(
                              attribute=branch_type_radio_attribute, answer=fruiting_spur_option
                          )
                          checklist_attribute = fruiting_spur_checklist_attribute
                          quality_options = item.get("fruiting_spur_quality_options", "").split(", ")
                      elif branch_type == "Sucker":
                          assert sucker_option is not None, "Missing 'sucker_option'"
                          polyline_object_instance.set_answer(attribute=branch_type_radio_attribute, answer=sucker_option)
                          checklist_attribute = sucker_checklist_attribute
                          quality_options = item.get("sucker_quality_options", "").split(", ")
                      elif branch_type == "Side shoot":
                          assert side_shoot_option is not None, "Missing 'side_shoot_option'"
                          polyline_object_instance.set_answer(attribute=branch_type_radio_attribute, answer=side_shoot_option)
                          checklist_attribute = side_shoot_checklist_attribute
                          quality_options = item.get("side_shoot_quality_options", "").split(", ")
                      elif branch_type == "Other branch type":
                          assert other_branch_option is not None, "Missing 'other_branch_option'"
                          polyline_object_instance.set_answer(
                              attribute=branch_type_radio_attribute, answer=other_branch_option
                          )
                          text_answer = item.get("Specify branch type", "")
                          assert isinstance(text_answer, str), "'Specify branch type' must be a string"
                          polyline_object_instance.set_answer(
                              attribute=other_branch_option_text_attribute, answer=text_answer
                          )
                          quality_options = []

                      # Process checklist options
                      checklist_answers = []
                      for quality in quality_options:
                          option = None
                          if quality == "Short length":
                              option = (
                                  fruiting_spur_short_length_option
                                  if branch_type == "Fruiting spur"
                                  else sucker_short_length_option
                                  if branch_type == "Sucker"
                                  else side_shoot_short_length_option
                                  if branch_type == "Side shoot"
                                  else None
                              )
                          elif quality == "High bud density":
                              option = (
                                  fruiting_spur_high_bud_density_option
                                  if branch_type == "Fruiting spur"
                                  else sucker_high_bud_density_option
                                  if branch_type == "Sucker"
                                  else side_shoot_high_bud_density_option
                                  if branch_type == "Side shoot"
                                  else None
                              )
                          elif quality == "Healthy":
                              option = (
                                  fruiting_spur_healthy_option
                                  if branch_type == "Fruiting spur"
                                  else sucker_healthy_option
                                  if branch_type == "Sucker"
                                  else side_shoot_healthy_option
                                  if branch_type == "Side shoot"
                                  else None
                              )

                          if option:
                              checklist_answers.append(option)
                          else:
                              assert branch_type == "Other branch type", (
                                  f"Invalid quality '{quality}' for branch type '{branch_type}'"
                              )

                      if checklist_attribute and checklist_answers:
                          polyline_object_instance.set_answer(
                              attribute=checklist_attribute, answer=checklist_answers, overwrite=True
                          )

                      object_instances_by_label_ref[label_ref] = polyline_object_instance

                  else:
                      polyline_object_instance = object_instances_by_label_ref[label_ref]

                  # Assign coordinates for this frame
                  polyline_object_instance.set_for_frames(coordinates=coord, frames=frame_number)

          # Add object instances to the label row if they have frames assigned
          for polyline_object_instance in object_instances_by_label_ref.values():
              assert isinstance(polyline_object_instance, ObjectInstance), "Expected ObjectInstance type"
              if polyline_object_instance.get_annotation_frames():
                  label_row.add_object_instance(polyline_object_instance)

          label_rows_to_save.append(label_row)

      # Step 3: Save all label rows using a bundle
      with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
          for label_row in label_rows_to_save:
              assert label_row is not None, "Trying to save a None label row"
              label_row.save(bundle=bundle)
              print(f"Saved label row for {label_row.data_title}")

      print("Labels with branch type radio buttons, checklist attributes, number attributes, and text labels added for all data units.")

      ```
    </CodeGroup>
  </Accordion>
</AccordionGroup>

<AccordionGroup>
  <Accordion title="Keypoint">
    **Basic**

    This example includes the following:

    * Single image labeling
    * Image Group labeling
    * Image Sequence labeling
    * Video labeling

    **Advanced**

    This example includes the following:

    * Single image labeling
    * Image Group labeling
    * Image Sequence labeling
    * Video labeling
    * Radio button options
    * Checklist options
    * Text input
    * Number input

    **Keypoint Ontology**

    ![Keypoint Ontology](https://storage.googleapis.com/docs-media.encord.com/static/img/sdk/labels-keypoints-floral-axis.png)

    <CodeGroup>
      ```python Keypoints Images/Videos expandable theme={"dark"}

      from encord import EncordUserClient, Project
      from encord.objects import Object, ObjectInstance
      from encord.objects.coordinates import PointCoordinate

      # User input
      SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"  # Replace with the file path to your SSH private key
      PROJECT_ID = "00000000-0000-0000-0000-000000000000"  # Replace with the unique Project ID
      BUNDLE_SIZE = 10

      # Data unit titles in your Project
      IMAGE_TITLE = "blueberries-001.jpg"
      IMG_GROUP_TITLE = "blueberries-ig"
      IMG_SEQUENCE_TITLE = "blueberries-is"
      VIDEO_TITLE = "blueberries-vid-001.mp4"

      # Ontology object title for your KEYPOINT object
      KEYPOINT_OBJECT_TITLE = "Floral axis"

      # Authorize connection to Encord
      user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path=SSH_PATH,
          # For US platform users use domain="https://api.us.encord.com"
          domain="https://api.encord.com",
      )

      project: Project = user_client.get_project(PROJECT_ID)

      # Find a KEYPOINT object in the ontology by title
      ontology_structure = project.ontology_structure
      keypoint_object: Object = ontology_structure.get_child_by_title(title=KEYPOINT_OBJECT_TITLE, type_=Object)
      assert keypoint_object is not None, f"Keypoint object '{KEYPOINT_OBJECT_TITLE}' not found in ontology."

      # Initialise label rows
      label_rows = {}
      all_titles = [IMAGE_TITLE, IMG_GROUP_TITLE, IMG_SEQUENCE_TITLE, VIDEO_TITLE]

      with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
          for title in all_titles:
              rows = project.list_label_rows_v2(data_title_eq=title)
              assert isinstance(rows, list), f"Expected list for '{title}', got {type(rows)}"
              if not rows:
                  print(f"Skipping: No label row found for {title}")
                  continue
              lr = rows[0]
              lr.initialise_labels(bundle=bundle)
              assert lr.ontology_structure is not None, f"Ontology not initialized for '{title}'"
              label_rows[title] = lr

      # Keypoint coordinates: A single point roughly near the center
      kp = PointCoordinate(0.5, 0.5)

      # Create instances and attach to frames
      label_rows_to_save = []

      # 1. One image > frame 0
      image_lr = label_rows.get(IMAGE_TITLE)
      if image_lr is not None:
          inst: ObjectInstance = keypoint_object.create_instance()
          inst.set_for_frames(coordinates=kp, frames=0)
          image_lr.add_object_instance(inst)
          label_rows_to_save.append(image_lr)

      # 2. One image group > frame 0
      img_group_lr = label_rows.get(IMG_GROUP_TITLE)
      if img_group_lr is not None:
          inst: ObjectInstance = keypoint_object.create_instance()
          inst.set_for_frames(coordinates=kp, frames=0)
          img_group_lr.add_object_instance(inst)
          label_rows_to_save.append(img_group_lr)

      # 3. One image sequence > frame 0
      img_sequence_lr = label_rows.get(IMG_SEQUENCE_TITLE)
      if img_sequence_lr is not None:
          inst: ObjectInstance = keypoint_object.create_instance()
          inst.set_for_frames(coordinates=kp, frames=0)
          img_sequence_lr.add_object_instance(inst)
          label_rows_to_save.append(img_sequence_lr)

      # 4. One video > reuse SAME instance across 3 consecutive frames (frames 100, 101, 102)
      video_lr = label_rows.get(VIDEO_TITLE)
      if video_lr is not None:
          inst: ObjectInstance = keypoint_object.create_instance()
          for f in [100, 101, 102]:
              inst.set_for_frames(coordinates=kp, frames=f)
          video_lr.add_object_instance(inst)
          label_rows_to_save.append(video_lr)

      # Save label rows
      with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
          for lr in label_rows_to_save:
              lr.save(bundle=bundle)
              print(f"Saved label row for {lr.data_title}")

      print("Done: created one keypoint on image, image group, image sequence, and 3 video frames.")

      ```

      ```python Keypoints Images/Videos expandable theme={"dark"}

      # Import dependencies
      from pathlib import Path

      from encord import EncordUserClient, Project
      from encord.objects import ChecklistAttribute, Object, ObjectInstance, Option, RadioAttribute, TextAttribute
      from encord.objects.coordinates import PointCoordinate
      from encord.objects.attributes import NumericAttribute

      SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"
      # SSH_PATH = get_ssh_key() # replace it with access key
      PROJECT_ID = "00000000-0000-0000-0000-000000000000"
      BUNDLE_SIZE = 100

      # Create user client using access key
      user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path=SSH_PATH,
          # For US platform users use "https://api.us.encord.com"
          domain="https://api.encord.com",
      )

      # Get project for which labels are to be added
      project: Project = user_client.get_project(PROJECT_ID)
      assert project is not None, "Project not found — check PROJECT_ID"

      # Get ontology structure
      ontology_structure = project.ontology_structure
      assert ontology_structure is not None, "Ontology structure is missing in the project"

      # Get keypoint object for floral axis
      keypoint_ontology_object: Object = ontology_structure.get_child_by_title(title="Floral axis", type_=Object)
      assert keypoint_ontology_object is not None, "Keypoint object 'Floral axis' not found in ontology"

      # Get radio attribute for floral axis type
      floral_axis_type_radio_attribute = ontology_structure.get_child_by_title(type_=RadioAttribute, title="Type?")
      assert floral_axis_type_radio_attribute is not None, "Radio attribute 'Type?' not found"

      # Get number attribute in the ontology
      quality_number_attribute = ontology_structure.get_child_by_title(type_=NumericAttribute, title="Overall Quality")
      assert quality_number_attribute is not None, "Number attribute 'Overall Quality' not found in ontology."

      # Get radio options
      pedicel_option = floral_axis_type_radio_attribute.get_child_by_title(type_=Option, title="Pedicel")
      assert pedicel_option is not None, "Option 'Pedicel' not found under radio attribute 'Type?'"

      peduncle_option = floral_axis_type_radio_attribute.get_child_by_title(type_=Option, title="Peduncle")
      assert peduncle_option is not None, "Option 'Peduncle' not found under radio attribute 'Type?'"

      other_floral_axis_option = floral_axis_type_radio_attribute.get_child_by_title(
          type_=Option, title="Other floral axis type"
      )
      assert other_floral_axis_option is not None, "Option 'Other floral axis type' not found under radio attribute 'Type?'"

      # Get checklist attributes and options for Pedicel
      pedicel_checklist_attribute = ontology_structure.get_child_by_title(
          type_=ChecklistAttribute, title="Pedicel Qualities?"
      )
      assert pedicel_checklist_attribute is not None, "Checklist attribute 'Pedicel Qualities?' not found"

      pedicel_robust_option = pedicel_checklist_attribute.get_child_by_title(type_=Option, title="Robust")
      assert pedicel_robust_option is not None, "Option 'Robust' not found under 'Pedicel Qualities?'"

      pedicel_healthy_option = pedicel_checklist_attribute.get_child_by_title(type_=Option, title="Healthy")
      assert pedicel_healthy_option is not None, "Option 'Healthy' not found under 'Pedicel Qualities?'"

      pedicel_growth_alignment_option = pedicel_checklist_attribute.get_child_by_title(
          type_=Option, title="Good Growth and Alignment"
      )
      assert pedicel_growth_alignment_option is not None, (
          "Option 'Good Growth and Alignment' not found under 'Pedicel Qualities?'"
      )

      # Get checklist attributes and options for Peduncle
      peduncle_checklist_attribute = ontology_structure.get_child_by_title(
          type_=ChecklistAttribute, title="Peduncle Qualities?"
      )
      assert peduncle_checklist_attribute is not None, "Checklist attribute 'Peduncle Qualities?' not found"

      peduncle_robust_option = peduncle_checklist_attribute.get_child_by_title(type_=Option, title="Robust")
      assert peduncle_robust_option is not None, "Option 'Robust' not found under 'Peduncle Qualities?'"

      peduncle_healthy_option = peduncle_checklist_attribute.get_child_by_title(type_=Option, title="Healthy")
      assert peduncle_healthy_option is not None, "Option 'Healthy' not found under 'Peduncle Qualities?'"

      peduncle_growth_alignment_option = peduncle_checklist_attribute.get_child_by_title(
          type_=Option, title="Good Growth and Alignment"
      )
      assert peduncle_growth_alignment_option is not None, (
          "Option 'Good Growth and Alignment' not found under 'Peduncle Qualities?'"
      )

      # Get text attribute for specifying other floral axis types
      other_floral_axis_option_text_attribute = ontology_structure.get_child_by_title(
          type_=TextAttribute, title="Specify floral axis type"
      )
      assert other_floral_axis_option_text_attribute is not None, "Text attribute 'Specify floral axis type' not found"

      # Dictionary of labels per data unit and per frame with floral axis type specified, including quality options
      video_image_frame_labels = {
          "blueberries-001.jpg": {
              0: {
                  "label_ref": "floral_axis_001",
                  "coordinates": PointCoordinate(x=0.01, y=0.02),
                  "floral_axis_type": "Pedicel",
                  "pedicel_quality_options": "Robust, Healthy",
                  "quality_number": 8
              }
          },
          "persimmons-010.jpg": {
              0: [
                  {
                      "label_ref": "floral_axis_002",
                      "coordinates": PointCoordinate(x=0.03, y=0.03),
                      "floral_axis_type": "Peduncle",
                      "peduncle_quality_options": "Robust, Healthy, Good Growth and Alignment",
                      "quality_number": 9
                  },
                  {
                      "label_ref": "floral_axis_003",
                      "coordinates": PointCoordinate(x=0.05, y=0.04),
                      "floral_axis_type": "Peduncle",
                      "peduncle_quality_options": "Robust",
                      "quality_number": 5
                  },
                  {
                      "label_ref": "floral_axis_004",
                      "coordinates": PointCoordinate(x=0.09, y=0.03),
                      "floral_axis_type": "Other floral axis type",
                      "Specify floral axis type": "Calyx",
                      "quality_number": 4
                  },
              ],
          },
          "blueberries-ig": {
              0: {
                  "label_ref": "floral_axis_005",
                  "coordinates": PointCoordinate(x=0.05, y=0.02),
                  "floral_axis_type": "Pedicel",
                  "pedicel_quality_options": "Robust, Healthy",
                  "quality_number": 7
              },
              2: [
                  {
                      "label_ref": "floral_axis_006",
                      "coordinates": PointCoordinate(x=0.03, y=0.03),
                      "floral_axis_type": "Pedicel",
                      "pedicel_quality_options": "Good Growth and Alignment",
                      "quality_number": 4
                  },
                  {
                      "label_ref": "floral_axis_007",
                      "coordinates": PointCoordinate(x=0.04, y=0.05),
                      "floral_axis_type": "Pedicel",
                      "pedicel_quality_options": "Robust",
                      "quality_number": 3
                  },
                  {
                      "label_ref": "floral_axis_008",
                      "coordinates": PointCoordinate(x=0.11, y=0.02),
                      "floral_axis_type": "Other floral axis type",
                      "Specify floral axis type": "Calyx",
                      "quality_number": 3
                  },
              ],
          },
          "persimmons-is": {
              0: {
                  "label_ref": "floral_axis_009",
                  "coordinates": PointCoordinate(x=0.01, y=0.02),
                  "floral_axis_type": "Peduncle",
                  "peduncle_quality_options": "Robust",
                  "quality_number": 5
              },
              3: [
                  {
                      "label_ref": "floral_axis_010",
                      "coordinates": PointCoordinate(x=0.03, y=0.03),
                      "floral_axis_type": "Peduncle",
                      "peduncle_quality_options": "Robust, Healthy, Good Growth and Alignment",
                      "quality_number": 9
                  },
                  {
                      "label_ref": "floral_axis_011",
                      "coordinates": PointCoordinate(x=0.08, y=0.05),
                      "floral_axis_type": "Peduncle",
                      "peduncle_quality_options": "Robust",
                      "quality_number": 2
                  },
                  {
                      "label_ref": "floral_axis_012",
                      "coordinates": PointCoordinate(x=0.11, y=0.02),
                      "floral_axis_type": "Other floral axis type",
                      "Specify floral axis type": "Calyx",
                      "quality_number": 1
                  },
              ],
          },
          "blueberries-vid-001.mp4": {
              103: [
                  {
                      "label_ref": "floral_axis_013",
                      "coordinates": PointCoordinate(x=0.02, y=0.01),
                      "floral_axis_type": "Pedicel",
                      "pedicel_quality_options": "Robust",
                      "quality_number": 5
                  },
                  {
                      "label_ref": "floral_axis_014",
                      "coordinates": PointCoordinate(x=0.06, y=0.06),
                      "floral_axis_type": "Pedicel",
                      "pedicel_quality_options": "Robust, Healthy, Good Growth and Alignment",
                      "quality_number": 8
                  },
                  {
                      "label_ref": "floral_axis_015",
                      "coordinates": PointCoordinate(x=0.10, y=0.01),
                      "floral_axis_type": "Other floral axis type",
                      "Specify floral axis type": "Calyx",
                      "quality_number": 7
                  },
              ],
              104: [
                  {
                      "label_ref": "floral_axis_016",
                      "coordinates": PointCoordinate(x=0.04, y=0.01),
                      "floral_axis_type": "Pedicel",
                      "pedicel_quality_options": "Robust",
                      "quality_number": 6
                  },
                  {
                      "label_ref": "floral_axis_014",
                      "coordinates": PointCoordinate(x=0.08, y=0.05),
                      "floral_axis_type": "Pedicel",
                      "pedicel_quality_options": "Robust, Healthy, Good Growth and Alignment",
                      "quality_number": 9
                  },
                  {
                      "label_ref": "floral_axis_017",
                      "coordinates": PointCoordinate(x=0.11, y=0.02),
                      "floral_axis_type": "Other floral axis type",
                      "Specify floral axis type": "Calyx",
                      "quality_number": 6
                  },
              ],
              105: [
                  {
                      "label_ref": "floral_axis_016",
                      "coordinates": PointCoordinate(x=0.05, y=0.02),
                      "floral_axis_type": "Pedicel",
                      "pedicel_quality_options": "Robust",
                      "quality_number": 5
                  },
                  {
                      "label_ref": "floral_axis_014",
                      "coordinates": PointCoordinate(x=0.07, y=0.04),
                      "floral_axis_type": "Pedicel",
                      "pedicel_quality_options": "Robust, Healthy, Good Growth and Alignment",
                      "quality_number": 5
                  },
                  {
                      "label_ref": "floral_axis_017",
                      "coordinates": PointCoordinate(x=0.09, y=0.03),
                      "floral_axis_type": "Other floral axis type",
                      "Specify floral axis type": "Calyx",
                      "quality_number": 3
                  },
              ],
          },
      }


      # Cache initialized label rows
      label_row_map = {}

      # Step 1: Initialize all label rows using a bundle
      with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
          for data_unit in video_image_frame_labels.keys():
              label_rows = project.list_label_rows_v2(data_title_eq=data_unit)
              assert isinstance(label_rows, list), f"Expected list of label rows for '{data_unit}', got {type(label_rows)}"

              if not label_rows:
                  print(f"Skipping: No label row found for {data_unit}")
                  continue

              label_row = label_rows[0]
              label_row.initialise_labels(bundle=bundle)
              assert label_row.ontology_structure is not None, f"Ontology not initialized for label row: {data_unit}"

              label_row_map[data_unit] = label_row  # Cache initialized label row for later use

      # Step 2: Process all frames/annotations and prepare label rows to save
      label_rows_to_save = []

      for data_unit, frame_coordinates in video_image_frame_labels.items():
          label_row = label_row_map.get(data_unit)
          if not label_row:
              print(f"Skipping: No initialized label row found for {data_unit}")
              continue

          object_instances_by_label_ref = {}

          # Loop through the frames for the current data unit
          for frame_number, items in frame_coordinates.items():
              assert isinstance(frame_number, int), f"Frame number must be int, got {type(frame_number)}"
              if not isinstance(items, list):
                  items = [items]

              for item in items:
                  label_ref = item["label_ref"]
                  coord = item["coordinates"]
                  floral_axis_type = item["floral_axis_type"]
                  quality_number = item["quality_number"]

                  assert floral_axis_type in {
                      "Pedicel",
                      "Peduncle",
                      "Other floral axis type",
                  }, f"Unexpected floral axis type '{floral_axis_type}' in data unit '{data_unit}'"

                  # Check if label_ref already exists for reusability
                  if label_ref not in object_instances_by_label_ref:
                      keypoint_object_instance: ObjectInstance = keypoint_ontology_object.create_instance()
                      assert keypoint_object_instance is not None, "Failed to create ObjectInstance"

                      object_instances_by_label_ref[label_ref] = keypoint_object_instance
                      checklist_attribute = None

                      # Set floral axis type attribute
                      if floral_axis_type == "Pedicel":
                          assert pedicel_option is not None, "Missing 'pedicel_option'"
                          keypoint_object_instance.set_answer(
                              attribute=floral_axis_type_radio_attribute, answer=pedicel_option
                          )
                          checklist_attribute = pedicel_checklist_attribute
                      elif floral_axis_type == "Peduncle":
                          assert peduncle_option is not None, "Missing 'peduncle_option'"
                          keypoint_object_instance.set_answer(
                              attribute=floral_axis_type_radio_attribute, answer=peduncle_option
                          )
                          checklist_attribute = peduncle_checklist_attribute
                      elif floral_axis_type == "Other floral axis type":
                          assert other_floral_axis_option is not None, "Missing 'other_floral_axis_option'"
                          keypoint_object_instance.set_answer(
                              attribute=floral_axis_type_radio_attribute, answer=other_floral_axis_option
                          )
                          text_answer = item.get("Specify floral axis type", "")
                          assert isinstance(text_answer, str), "'Specify floral axis type' must be a string"
                          keypoint_object_instance.set_answer(
                              attribute=other_floral_axis_option_text_attribute,
                              answer=text_answer,
                          )

                      # Set quality attribute 
                      keypoint_object_instance.set_answer(attribute=quality_number_attribute, answer=quality_number)

                      # Set checklist attributes
                      checklist_answers = []
                      quality_key = f"{floral_axis_type.lower()}_quality_options"
                      quality_options = item.get(quality_key, "").split(", ")

                      for quality in quality_options:
                          if quality == "Robust":
                              checklist_answers.append(
                                  pedicel_robust_option if floral_axis_type == "Pedicel" else peduncle_robust_option
                              )
                          elif quality == "Healthy":
                              checklist_answers.append(
                                  pedicel_healthy_option if floral_axis_type == "Pedicel" else peduncle_healthy_option
                              )
                          elif quality == "Good Growth and Alignment":
                              checklist_answers.append(
                                  pedicel_growth_alignment_option
                                  if floral_axis_type == "Pedicel"
                                  else peduncle_growth_alignment_option
                              )

                      if checklist_attribute and checklist_answers:
                          keypoint_object_instance.set_answer(
                              attribute=checklist_attribute, answer=checklist_answers, overwrite=True
                          )
                  else:
                      # Reuse existing instance across frames
                      keypoint_object_instance = object_instances_by_label_ref[label_ref]

                  # Assign the object to the frame and track it
                  keypoint_object_instance.set_for_frames(coordinates=coord, frames=frame_number)

          # Add object instances to label_row **only if they have frames assigned**
          for keypoint_object_instance in object_instances_by_label_ref.values():
              assert isinstance(keypoint_object_instance, ObjectInstance), "Expected ObjectInstance type"
              if keypoint_object_instance.get_annotation_frames():
                  label_row.add_object_instance(keypoint_object_instance)

          label_rows_to_save.append(label_row)

      # Step 3: Save all label rows using a bundle
      with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
          for label_row in label_rows_to_save:
              assert label_row is not None, "Trying to save a None label row"
              label_row.save(bundle=bundle)
              print(f"Saved label row for {label_row.data_title}")

      print("Labels with floral axis type radio buttons, checklist attributes, number attributes, and text labels added for all data units.")

      ```
    </CodeGroup>
  </Accordion>
</AccordionGroup>

<AccordionGroup>
  <Accordion title="Circle">
    Use `CircleCoordinates(center_x=0.XX, center_y=0.YY, radius=0.XX)` to specify the location and size of the Circle object label you want to import.

    <CodeGroup>
      ```python Image theme={"dark"}
      # Import dependencies
      from encord import EncordUserClient
      from encord.objects import Object, OntologyStructure
      from encord.objects.coordinates import CircleCoordinates

      SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"  # Replace with the file path to your SSH private key
      PROJECT_ID = "00000000-0000-0000-0000-000000000000"  # Replace with the unique Project ID
      DATA_TITLE = "image_001.jpg" # Replace with the name of the image
      ONTOLOGY_OBJECT_TITLE = "Defect" # Replace with the name of the Circle object label

      user_client = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path=SSH_PATH,
          # For US platform users use domain="https://api.us.encord.com"
          domain="https://api.encord.com",
      )

      project = user_client.get_project(PROJECT_ID)

      (label_row,) = project.list_label_rows_v2(data_title_eq=DATA_TITLE)
      label_row.initialise_labels()

      ontology_structure: OntologyStructure = label_row.ontology_structure
      circle_ontology_object: Object = ontology_structure.get_child_by_title(
          title=ONTOLOGY_OBJECT_TITLE, type_=Object
      )

      circle_object_instance = circle_ontology_object.create_instance()
      circle_object_instance.set_for_frames(
          coordinates=CircleCoordinates(center_x=0.5, center_y=0.5, radius=0.1),
          frames=0,
      )

      label_row.add_object_instance(circle_object_instance)
      label_row.save()
      ```

      ```python Image Group theme={"dark"}
      # Import dependencies
      from encord import EncordUserClient
      from encord.objects import Object, OntologyStructure
      from encord.objects.coordinates import CircleCoordinates

      SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"  # Replace with the file path to your SSH private key
      PROJECT_ID = "00000000-0000-0000-0000-000000000000"  # Replace with the unique Project ID
      DATA_TITLE = "image_group_001" # Replace with the name of the image group
      ONTOLOGY_OBJECT_TITLE = "Defect" # Replace with the name of the Circle object label

      IMAGE_INDEX = 2 # Frame number of the image inside the image group (0 = first image)

      user_client = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path=SSH_PATH,
          # For US platform users use domain="https://api.us.encord.com"
          domain="https://api.encord.com",
      )

      project = user_client.get_project(PROJECT_ID)

      (label_row,) = project.list_label_rows_v2(data_title_eq=DATA_TITLE)
      label_row.initialise_labels()

      ontology_structure: OntologyStructure = label_row.ontology_structure
      circle_ontology_object: Object = ontology_structure.get_child_by_title(
          title=ONTOLOGY_OBJECT_TITLE, type_=Object
      )

      circle_object_instance = circle_ontology_object.create_instance()
      circle_object_instance.set_for_frames(
          coordinates=CircleCoordinates(center_x=0.5, center_y=0.5, radius=0.1),
          frames=IMAGE_INDEX,
      )

      label_row.add_object_instance(circle_object_instance)
      label_row.save()
      ```

      ```python Image Sequence theme={"dark"}
      # Import dependencies
      from encord import EncordUserClient
      from encord.objects import Object, OntologyStructure
      from encord.objects.coordinates import CircleCoordinates

      SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"  # Replace with the file path to your SSH private key
      PROJECT_ID = "00000000-0000-0000-0000-000000000000"  # Replace with the unique Project ID
      DATA_TITLE = "image_sequence_001" # Replace with the name of the Image Sequence
      ONTOLOGY_OBJECT_TITLE = "Defect" # Replace with the name of the Circle object label

      FRAME_INDEX = 5 # Frame number of the image inside the image sequence (0 = first image)

      user_client = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path=SSH_PATH,
          # For US platform users use domain="https://api.us.encord.com"
          domain="https://api.encord.com",
      )

      project = user_client.get_project(PROJECT_ID)

      (label_row,) = project.list_label_rows_v2(data_title_eq=DATA_TITLE)
      label_row.initialise_labels()

      ontology_structure: OntologyStructure = label_row.ontology_structure
      circle_ontology_object: Object = ontology_structure.get_child_by_title(
          title=ONTOLOGY_OBJECT_TITLE, type_=Object
      )

      circle_object_instance = circle_ontology_object.create_instance()
      circle_object_instance.set_for_frames(
          coordinates=CircleCoordinates(center_x=0.5, center_y=0.5, radius=0.1),
          frames=FRAME_INDEX,
      )

      label_row.add_object_instance(circle_object_instance)
      label_row.save()
      ```

      ```python Video theme={"dark"}
      # Import dependencies
      from encord import EncordUserClient
      from encord.objects import Object, OntologyStructure
      from encord.objects.coordinates import CircleCoordinates
      from encord.objects.frames import Range

      SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"  # Replace with the file path to your SSH private key
      PROJECT_ID = "00000000-0000-0000-0000-000000000000"  # Replace with the unique Project ID
      DATA_TITLE = "video_001.mp4" # Replace with the name of the video
      ONTOLOGY_OBJECT_TITLE = "Defect" # Replace with the name of the Circle object label

      FRAME_RANGE = Range(start=10, end=12) # A range of three video frames: 10, 11, 12 to import the label.

      user_client = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path=SSH_PATH,
          # For US platform users use domain="https://api.us.encord.com"
          domain="https://api.encord.com",
      )

      project = user_client.get_project(PROJECT_ID)

      (label_row,) = project.list_label_rows_v2(data_title_eq=DATA_TITLE)
      label_row.initialise_labels()

      ontology_structure: OntologyStructure = label_row.ontology_structure
      circle_ontology_object: Object = ontology_structure.get_child_by_title(
          title=ONTOLOGY_OBJECT_TITLE, type_=Object
      )

      circle_object_instance = circle_ontology_object.create_instance()
      circle_object_instance.set_for_frames(
          coordinates=CircleCoordinates(center_x=0.5, center_y=0.5, radius=0.1),
          frames=FRAME_RANGE,
      )

      label_row.add_object_instance(circle_object_instance)
      label_row.save()
      ```
    </CodeGroup>
  </Accordion>
</AccordionGroup>

<AccordionGroup>
  <Accordion title="Bitmask">
    **Basic**

    This example includes the following:

    * Single image labeling
    * Image Group labeling
    * Image Sequence labeling
    * Video labeling

    **Advanced**

    This example includes the following:

    * Single image labeling
    * Image Group labeling
    * Image Sequence labeling
    * Video labeling
    * Radio button options
    * Checklist options
    * Text input
    * Number input

    **Bitmask Ontology**

    ![Bitmask Ontology](https://storage.googleapis.com/docs-media.encord.com/static/img/sdk/labels-bitmaks-apples.png)

    <CodeGroup>
      ```python Bitmasks Images/Videos - Basic expandable theme={"dark"}

      from encord import EncordUserClient, Project
      from encord.objects import Object, ObjectInstance
      from encord.objects.coordinates import BitmaskCoordinates
      import numpy as np

      # User input
      SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"  # Replace with your SSH private key
      PROJECT_ID = "00000000-0000-0000-0000-000000000000"   # Replace with your Project ID
      BUNDLE_SIZE = 10

      # Data unit titles in your Project
      IMAGE_TITLE = "apples-001.jpg"
      IMG_GROUP_TITLE = "apples-ig"
      IMG_SEQUENCE_TITLE = "apples-is"
      VIDEO_TITLE = "apples-vid-001.mp4"

      # Fixed frame size
      FRAME_H, FRAME_W = 1080, 1920

      # Authorize connection to Encord
      user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path=SSH_PATH,
          # For US platform users use domain="https://api.us.encord.com"
          domain="https://api.encord.com",
      )

      project: Project = user_client.get_project(PROJECT_ID)

      # Find the bitmask object "Apples" in the ontology
      ontology_structure = project.ontology_structure
      bitmask_ontology_object: Object = ontology_structure.get_child_by_title(title="Apples", type_=Object)
      assert bitmask_ontology_object is not None, "Bitmask object 'Apples' not found in ontology."

      # Initialise label rows
      label_rows = {}
      all_titles = [IMAGE_TITLE, IMG_GROUP_TITLE, IMG_SEQUENCE_TITLE, VIDEO_TITLE]

      with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
          for title in all_titles:
              rows = project.list_label_rows_v2(data_title_eq=title)
              assert isinstance(rows, list), f"Expected list for '{title}', got {type(rows)}"
              if not rows:
                  print(f"Skipping: No label row found for {title}")
                  continue
              lr = rows[0]
              lr.initialise_labels(bundle=bundle)
              assert lr.ontology_structure is not None, f"Ontology not initialized for '{title}'"
              label_rows[title] = lr

      # Prepare boolean masks with shape matching frame size
      mask_a_arr = np.ones((FRAME_H, FRAME_W), dtype=bool)
      assert mask_a_arr.shape == (FRAME_H, FRAME_W), "Mask dimensions must match 1080x1920"

      mask_b_arr = np.zeros((FRAME_H, FRAME_W), dtype=bool)
      mask_b_arr[0:FRAME_H//3, 0:FRAME_W//3] = True
      assert mask_b_arr.shape == (FRAME_H, FRAME_W), "Mask dimensions must match 1080x1920"

      mask_c_arr = np.zeros((FRAME_H, FRAME_W), dtype=bool)
      mask_c_arr[FRAME_H//4:FRAME_H//2, FRAME_W//4:FRAME_W//2] = True
      assert mask_c_arr.shape == (FRAME_H, FRAME_W), "Mask dimensions must match 1080x1920"

      mask_a = BitmaskCoordinates(mask_a_arr)
      mask_b = BitmaskCoordinates(mask_b_arr)
      mask_c = BitmaskCoordinates(mask_c_arr)

      # Create instances and attach to frames
      label_rows_to_save = []

      # 1. One image > annotate frame 0
      image_lr = label_rows.get(IMAGE_TITLE)
      if image_lr is not None:
          inst: ObjectInstance = bitmask_ontology_object.create_instance()
          inst.set_for_frames(coordinates=mask_a, frames=0, manual_annotation=True)
          image_lr.add_object_instance(inst)
          label_rows_to_save.append(image_lr)

      # 2. One image group > annotate frame 0
      img_group_lr = label_rows.get(IMG_GROUP_TITLE)
      if img_group_lr is not None:
          inst: ObjectInstance = bitmask_ontology_object.create_instance()
          inst.set_for_frames(coordinates=mask_b, frames=0, manual_annotation=True)
          img_group_lr.add_object_instance(inst)
          label_rows_to_save.append(img_group_lr)

      # 3. One image sequence > annotate frame 0
      img_sequence_lr = label_rows.get(IMG_SEQUENCE_TITLE)
      if img_sequence_lr is not None:
          inst: ObjectInstance = bitmask_ontology_object.create_instance()
          inst.set_for_frames(coordinates=mask_c, frames=0, manual_annotation=True)
          img_sequence_lr.add_object_instance(inst)
          label_rows_to_save.append(img_sequence_lr)

      # 4. One video > reuse SAME instance across 3 consecutive frames (100, 101, 102)
      video_lr = label_rows.get(VIDEO_TITLE)
      if video_lr is not None:
          inst: ObjectInstance = bitmask_ontology_object.create_instance()
          for f, bm in zip([100, 101, 102], [mask_a, mask_b, mask_c]):
              inst.set_for_frames(coordinates=bm, frames=f, manual_annotation=True)
          video_lr.add_object_instance(inst)
          label_rows_to_save.append(video_lr)

      # Save label rows
      with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
          for lr in label_rows_to_save:
              lr.save(bundle=bundle)
              print(f"Saved label row for {lr.data_title}")

      print("Done: created bitmasks on image, image group, image sequence, and 3 video frames for 'Apples'.")

      ```

      ```python Bitmasks Images/Videos - Advanced expandable theme={"dark"}

      # Import dependencies
      import numpy as np

      from pathlib import Path
      from encord import EncordUserClient, Project
      from encord.objects import (
          Object,
          ObjectInstance,
          RadioAttribute,
          ChecklistAttribute,
          TextAttribute,
          Option
      )
      from encord.objects.coordinates import BitmaskCoordinates
      from encord.objects.attributes import NumericAttribute

      # First, we need to prepare the mask itself.
      # For simplicity, we'll mask the entire frame
      # Note, that the size of the mask must be identical to the size of the image/frame
      numpy_coordinates = np.ones((1080, 1920))

      # we also need to make sure that the image/frame is in boolean format
      numpy_coordinates = numpy_coordinates.astype(bool)

      SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"
      PROJECT_ID = "00000000-0000-0000-0000-000000000000"

      # Create user client using ssh key
      user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path=SSH_PATH,
          # For US platform users use "https://api.us.encord.com"
          domain="https://api.encord.com",
      )

      # Get project for which labels are to be added
      project: Project = user_client.get_project(PROJECT_ID)

      # Create radio button attribute for apple type
      ontology_structure = project.ontology_structure

      # Find a bounding box annotation object in the project ontology
      bitmask_ontology_object: Object = ontology_structure.get_child_by_title(
          title="Apples", type_=Object
      )

      # Find radio attribute in the ontology
      apple_type_radio_attribute = ontology_structure.get_child_by_title(
          type_=RadioAttribute, title="Type?"
      )

      # Find number attribute in the ontology
      apple_quality_number_attribute = ontology_structure.get_child_by_title(type_=NumericAttribute, title="Overall Quality")
      assert apple_quality_number_attribute is not None, "Number attribute 'Overall Quality' not found in ontology."

      # Create options for the radio buttons
      sugar_bee_option = apple_type_radio_attribute.get_child_by_title(type_=Option, title="Sugar Bee")
      granny_smith_option = apple_type_radio_attribute.get_child_by_title(type_=Option, title="Granny Smith")
      honey_crisp_option = apple_type_radio_attribute.get_child_by_title(type_=Option, title="Honey Crisp")
      other_apple_option = apple_type_radio_attribute.get_child_by_title(type_=Option, title="Other apple type")

      # Create checklist attributes and options for each apple type
      # Sugar Bee Qualities
      sugar_bee_checklist_attribute = ontology_structure.get_child_by_title(
          type_=ChecklistAttribute, title="Sugar Bee Qualities?"
      )
      sugar_bee_plump_option = sugar_bee_checklist_attribute.get_child_by_title(type_=Option, title="Plump")
      sugar_bee_juicy_option = sugar_bee_checklist_attribute.get_child_by_title(type_=Option, title="Juicy")
      sugar_bee_large_option = sugar_bee_checklist_attribute.get_child_by_title(type_=Option, title="Large")

      # Granny Smith Qualities
      granny_smith_checklist_attribute = ontology_structure.get_child_by_title(
          type_=ChecklistAttribute, title="Granny Smith Qualities?"
      )
      granny_smith_plump_option = granny_smith_checklist_attribute.get_child_by_title(type_=Option, title="Plump")
      granny_smith_juicy_option = granny_smith_checklist_attribute.get_child_by_title(type_=Option, title="Juicy")
      granny_smith_large_option = granny_smith_checklist_attribute.get_child_by_title(type_=Option, title="Large")

      # Honey Crisp Qualities
      honey_crisp_checklist_attribute = ontology_structure.get_child_by_title(
          type_=ChecklistAttribute, title="Honey Crisp Qualities?"
      )
      honey_crisp_plump_option = honey_crisp_checklist_attribute.get_child_by_title(type_=Option, title="Plump")
      honey_crisp_juicy_option = honey_crisp_checklist_attribute.get_child_by_title(type_=Option, title="Juicy")
      honey_crisp_large_option = honey_crisp_checklist_attribute.get_child_by_title(type_=Option, title="Large")

      # Other apple Types
      other_apple_option_text_attribute = ontology_structure.get_child_by_title(
          type_=TextAttribute, title="Specify apple type"
      )

      # Dictionary of labels per data unit and per frame with apple type specified, including quality options
      video_frame_labels = {
          "apples-001.jpg": {
              0: {
                  "label_ref": "apple_001",
                  "coordinates": BitmaskCoordinates(numpy_coordinates), 
                  "apple_type": "Sugar Bee", 
                  "sugar_bee_quality_options": "Plump, Juicy",
                  "apple_quality": 7
                  }
          },
          "apples-010.jpg": {
              0: [
                  {
                      "label_ref": "apple_002", 
                      "coordinates": BitmaskCoordinates(numpy_coordinates), 
                      "apple_type": "Granny Smith", 
                      "granny_smith_quality_options": "Plump, Juicy, Large",
                      "apple_quality": 9
                      },
                  {
                      "label_ref": "apple_003",
                      "coordinates": BitmaskCoordinates(numpy_coordinates), 
                      "apple_type": "Honey Crisp", 
                      "honey_crisp_quality_options": "Plump",
                      "apple_quality": 8
                      },
                  {
                      "label_ref": "apple_004", 
                      "coordinates": BitmaskCoordinates(numpy_coordinates), 
                      "apple_type": "Other apple type", "Specify apple type": "Fuji",
                      "apple_quality": 4
                      },
              ],
          },
          "apples-ig": {
              0: {
                  "label_ref": "apple_005", 
                  "coordinates": BitmaskCoordinates(numpy_coordinates), 
                  "apple_type": "Sugar Bee", 
                  "sugar_bee_quality_options": "Plump, Juicy",
                  "apple_quality": 7
                  },
              2: [
                  {
                  "label_ref": "apple_006", 
                  "coordinates": BitmaskCoordinates(numpy_coordinates),
                  "apple_type": "Granny Smith", 
                  "granny_smith_quality_options": "Large",
                  "apple_quality": 6
                  },
                  {
                  "label_ref": "apple_007", 
                  "coordinates": BitmaskCoordinates(numpy_coordinates), 
                  "apple_type": "Honey Crisp", 
                  "honey_crisp_quality_options": "Plump",
                  "apple_quality": 3
                  },
                  {
                  "label_ref": "apple_008", 
                  "coordinates": BitmaskCoordinates(numpy_coordinates),
                  "apple_type": "Other apple type", 
                  "Specify apple type": "Jazz",
                  "apple_quality": 6
                  },
              ]
          },
          "apples-is": {
              0: {
                  "label_ref": "apple_009", 
                  "coordinates": BitmaskCoordinates(numpy_coordinates),
                  "apple_type": "Sugar Bee", 
                  "sugar_bee_quality_options": "Plump",
                  "apple_quality": 5
                  },
              3: [
                  {
                  "label_ref": "apple_010", 
                  "coordinates": BitmaskCoordinates(numpy_coordinates), 
                  "apple_type": "Granny Smith", 
                  "granny_smith_quality_options": "Plump, Juicy, Large",
                  "apple_quality": 9
                  },
                  {
                  "label_ref": "apple_011", 
                  "coordinates": BitmaskCoordinates(numpy_coordinates), 
                  "apple_type": "Honey Crisp", 
                  "honey_crisp_quality_options": "Plump",
                  "apple_quality": 8
                  },
                  {
                  "label_ref": "apple_012", 
                  "coordinates": BitmaskCoordinates(numpy_coordinates), 
                  "apple_type": "Other apple type", 
                  "Specify apple type": "Red Delicious",
                  "apple_quality": 8
                  },
              ]
          },
          "apples-vid-001.mp4": {
              103: [
                  {
                  "label_ref": "apple_013", 
                  "coordinates": BitmaskCoordinates(numpy_coordinates),
                  "apple_type": "Honey Crisp", 
                  "honey_crisp_quality_options": "Plump",
                  "apple_quality": 4
                  },
                  {
                  "label_ref": "apple_014", 
                  "coordinates": BitmaskCoordinates(numpy_coordinates),
                  "apple_type": "Sugar Bee", 
                  "sugar_bee_quality_options": "Plump, Juicy, Large",
                  "apple_quality": 9
                  },
                  {
                  "label_ref": "apple_015", 
                  "coordinates": BitmaskCoordinates(numpy_coordinates),
                  "apple_type": "Other apple type", 
                  "Specify apple type": "Jazz",
                  "apple_quality": 4
                  },
              ],
              104: [
                  {
                  "label_ref": "apple_016", 
                  "coordinates": BitmaskCoordinates(numpy_coordinates), 
                  "apple_type": "Honey Crisp", 
                  "honey_crisp_quality_options": "Plump",
                  "apple_quality": 4
                  },
                  {
                  "label_ref": "apple_014", 
                  "coordinates": BitmaskCoordinates(numpy_coordinates),
                  "apple_type": "Sugar Bee", 
                  "sugar_bee_quality_options": "Plump, Juicy, Large",
                  "apple_quality": 9
                  },
                  {
                  "label_ref": "apple_017", 
                  "coordinates": BitmaskCoordinates(numpy_coordinates),
                  "apple_type": "Other apple type",
                  "Specify apple type": "Fuji",
                  "apple_quality": 8
                  },
              ],
              105: [
                  {
                  "label_ref": "apple_016", 
                  "coordinates": BitmaskCoordinates(numpy_coordinates), 
                  "apple_type": "Honey Crisp", 
                  "honey_crisp_quality_options": "Plump",
                  "apple_quality": 4
                  },
                  {
                  "label_ref": "apple_014", 
                  "coordinates": BitmaskCoordinates(numpy_coordinates),
                  "apple_type": "Sugar Bee", 
                  "sugar_bee_quality_options": "Plump, Juicy, Large",
                  "apple_quality": 9
                  },
                  {
                  "label_ref": "apple_017", 
                  "coordinates": BitmaskCoordinates(numpy_coordinates),
                  "apple_type": "Other apple type",
                  "Specify apple type": "Red Delicious",
                  "apple_quality": 7
                  },
              ],
          },
      }


      # Loop through each data unit (image, video, etc.)
      for data_unit, frame_coordinates in video_frame_labels.items():
          object_instances_by_label_ref = {}

          # Get the label row for the current data unit
          label_row = project.list_label_rows_v2(data_title_eq=data_unit)[0]
          label_row.initialise_labels()

          # Loop through the frames for the current data unit
          for frame_number, items in frame_coordinates.items():
              if not isinstance(items, list):  #  Multiple objects in the frame
                  items = [items]

              for item in items:
                  label_ref = item["label_ref"]
                  coord = item["coordinates"]
                  apple_type = item["apple_type"]
                  apple_quality = item["apple_quality"]

                  #  Check if label_ref already exists for reusability
                  if label_ref not in object_instances_by_label_ref:
                      bitmask_object_instance: ObjectInstance = bitmask_ontology_object.create_instance()
                      object_instances_by_label_ref[label_ref] = bitmask_object_instance  #  Store for reuse
                      checklist_attribute = None

                      # Set apple quality attribute 
                      bitmask_object_instance.set_answer(attribute=apple_quality_number_attribute, answer=apple_quality)

                      # Set apple type attribute
                      if apple_type == "Sugar Bee":
                          bitmask_object_instance.set_answer(attribute=apple_type_radio_attribute, answer=sugar_bee_option)
                          checklist_attribute = sugar_bee_checklist_attribute
                      elif apple_type == "Granny Smith":
                          bitmask_object_instance.set_answer(attribute=apple_type_radio_attribute, answer=granny_smith_option)
                          checklist_attribute = granny_smith_checklist_attribute
                      elif apple_type == "Honey Crisp":
                          bitmask_object_instance.set_answer(attribute=apple_type_radio_attribute, answer=honey_crisp_option)
                          checklist_attribute = honey_crisp_checklist_attribute
                      elif apple_type == "Other apple type":
                          bitmask_object_instance.set_answer(attribute=apple_type_radio_attribute, answer=other_apple_option)
                          bitmask_object_instance.set_answer(attribute=other_apple_option_text_attribute, answer=item.get("Specify apple type", ""))

                      # Set checklist attributes
                      checklist_answers = []
                      quality_options = item.get(f"{apple_type.lower()}_quality_options", "").split(", ")

                      for quality in quality_options:
                          if quality == "Plump":
                              checklist_answers.append(sugar_bee_plump_option if apple_type == "Sugar Bee" else granny_smith_plump_option if apple_type == "Granny Smith" else honey_crisp_plump_option)
                          elif quality == "Juicy":
                              checklist_answers.append(sugar_bee_juicy_option if apple_type == "Sugar Bee" else granny_smith_juicy_option if apple_type == "Granny Smith" else honey_crisp_juicy_option)
                          elif quality == "Large":
                              checklist_answers.append(sugar_bee_large_option if apple_type == "Sugar Bee" else granny_smith_large_option if apple_type == "Granny Smith" else honey_crisp_large_option)

                      if checklist_attribute and checklist_answers:
                          bitmask_object_instance.set_answer(attribute=checklist_attribute, answer=checklist_answers, overwrite=True)

                  else:
                      #  Reuse existing instance across frames
                      bitmask_object_instance = object_instances_by_label_ref[label_ref]

                  #  Assign the object to the frame and track it
                  bitmask_object_instance.set_for_frames(coordinates=coord, frames=frame_number)

          #  Add object instances to label_row **only if they have frames assigned**
          for bitmask_object_instance in object_instances_by_label_ref.values():
              if bitmask_object_instance.get_annotation_frames():  #  Ensures it has at least one frame
                  label_row.add_object_instance(bitmask_object_instance)

          #  Upload all labels for this data unit (video/image) to the server
          label_row.save()

      print(" Labels with apple type radio buttons, checklist attributes, number attributes, and text labels added for all data units.")
      ```
    </CodeGroup>
  </Accordion>
</AccordionGroup>

<AccordionGroup>
  <Accordion title="Object Primitives">
    <Info>Before you can import Object Primitive labels into Encord, the Object Primitive Template MUST exist in Encord. [Use the UI to create the Object Primitive Template](/platform-documentation/Annotate/annotate-ontologies/annotate-working-with-ontologies#object-primitives) so you can visually inspect the Object Primitive.</Info>

    **Import Object Primitive labels**

    **Basic**

    This example includes the following:

    * Single image labeling
    * Image Group labeling
    * Image Sequence labeling
    * Video labeling

    **Advanced**

    This example includes the following:

    * Single image labeling
    * Image Group labeling
    * Image Sequence labeling
    * Video labeling
    * Radio button options
    * Checklist options
    * Text input
    * Number input

    **Primitives Ontology**

    The title for the primitive object is *Triangle*.

    ![Primitive Ontology](https://storage.googleapis.com/docs-media.encord.com/static/img/sdk/labels-primitives-strawberries.png)

    <CodeGroup>
      ```python Primitives Images/Videos - Basic expandable theme={"dark"}

      from encord import EncordUserClient, Project
      from encord.objects import Object, ObjectInstance
      from encord.objects.coordinates import SkeletonCoordinate, SkeletonCoordinates
      from encord.objects.skeleton_template import SkeletonTemplate

      # User input
      SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"  # Replace with the file path to your SSH private key
      PROJECT_ID = "00000000-0000-0000-0000-000000000000"  # Replace with the unique Project ID
      BUNDLE_SIZE = 10

      IMAGE_TITLE = "cherries-001.jpg"
      IMG_GROUP_TITLE = "cherries-ig"
      IMG_SEQUENCE_TITLE = "cherries-is"
      VIDEO_TITLE = "cherries-vid-001.mp4"

      # Authorize connection to Encord
      user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path=SSH_PATH,
          # For US platform users use domain="https://api.us.encord.com"
          domain="https://api.encord.com",
      )

      project: Project = user_client.get_project(PROJECT_ID)

      # Ontology pieces
      ontology = project.ontology_structure
      skeleton_object: Object = ontology.get_child_by_title(title="Strawberries", type_=Object)
      assert skeleton_object is not None, "Ontology object 'Strawberries' not found."

      # The primitive template your object uses
      assert "Triangle" in ontology.skeleton_templates, "Skeleton template 'Triangle' not found in ontology."
      template: SkeletonTemplate = ontology.skeleton_templates["Triangle"]

      # Grab the point ids defined by the template
      point_ids = [pt.feature_hash for pt in template.skeleton.values()]
      assert len(point_ids) >= 3, "Template 'Triangle' should have at least 3 points."

      # Coordinate set
      tri_coords = SkeletonCoordinates(
          values=[
              SkeletonCoordinate(x=0.30, y=0.30, name="point_0", color="#000000", value="point_0", feature_hash=point_ids[0]),
              SkeletonCoordinate(x=0.45, y=0.30, name="point_1", color="#000000", value="point_1", feature_hash=point_ids[1]),
              SkeletonCoordinate(x=0.35, y=0.45, name="point_2", color="#000000", value="point_2", feature_hash=point_ids[2]),
          ],
          name="Triangle",
      )

      # Initialize label rows
      label_rows = {}
      with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
          for title in [IMAGE_TITLE, IMG_GROUP_TITLE, IMG_SEQUENCE_TITLE, VIDEO_TITLE]:
              rows = project.list_label_rows_v2(data_title_eq=title)
              assert isinstance(rows, list), f"Expected list for '{title}', got {type(rows)}"
              if not rows:
                  print(f"Skipping: No label row found for {title}")
                  continue
              lr = rows[0]
              lr.initialise_labels(bundle=bundle)
              assert lr.ontology_structure is not None, f"Ontology not initialized for '{title}'"
              label_rows[title] = lr

      # Create one skeleton instance per data unit and assign frames
      to_save = []

      # 1. One image > frame 0
      lr = label_rows.get(IMAGE_TITLE)
      if lr:
          inst: ObjectInstance = skeleton_object.create_instance()
          inst.set_for_frames(coordinates=tri_coords, frames=0)
          lr.add_object_instance(inst)
          to_save.append(lr)

      # 2. One image group > frame 0
      lr = label_rows.get(IMG_GROUP_TITLE)
      if lr:
          inst: ObjectInstance = skeleton_object.create_instance()
          inst.set_for_frames(coordinates=tri_coords, frames=0)
          lr.add_object_instance(inst)
          to_save.append(lr)

      # 3. One image sequence > frame 0
      lr = label_rows.get(IMG_SEQUENCE_TITLE)
      if lr:
          inst: ObjectInstance = skeleton_object.create_instance()
          inst.set_for_frames(coordinates=tri_coords, frames=0)
          lr.add_object_instance(inst)
          to_save.append(lr)

      # 4. One video > reuse same instance across 3 consecutive frames
      lr = label_rows.get(VIDEO_TITLE)
      if lr:
          inst: ObjectInstance = skeleton_object.create_instance()
          for f in [100, 101, 102]:
              inst.set_for_frames(coordinates=tri_coords, frames=f)
          lr.add_object_instance(inst)
          to_save.append(lr)

      # Save label rows
      with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
          for lr in to_save:
              lr.save(bundle=bundle)
              print(f"Saved label row for {lr.data_title}")

      print("Done: placed a minimal 'Strawberries' skeleton (Triangle) on image, image group, image sequence, and 3 video frames.")

      ```

      ```python Primitives Images/Videos - Advanced expandable theme={"dark"}

      # Import dependencies
      from pathlib import Path

      from encord import EncordUserClient, Project
      from encord.objects import ChecklistAttribute, Object, ObjectInstance, Option, RadioAttribute, TextAttribute
      from encord.objects.coordinates import SkeletonCoordinate, SkeletonCoordinates
      from encord.objects.skeleton_template import SkeletonTemplate
      from encord.objects.attributes import NumericAttribute

      # User input
      SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"
      # SSH_PATH = get_ssh_key() # replace it with access key
      PROJECT_ID = "00000000-0000-0000-0000-000000000000"
      BUNDLE_SIZE = 100

      # Create user client using access key
      user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path=SSH_PATH,
          # For US platform users use "https://api.us.encord.com"
          domain="https://api.encord.com",
      )

      # Get project for which labels are to be added
      project: Project = user_client.get_project(PROJECT_ID)
      assert project is not None, "Project not found — check PROJECT_ID"

      # Get ontology structure
      ontology_structure = project.ontology_structure
      assert ontology_structure is not None, "Ontology structure is missing from the project"

      # Get the skeleton annotation object
      skeleton_ontology_object: Object = ontology_structure.get_child_by_title(title="Strawberries", type_=Object)
      assert skeleton_ontology_object is not None, "Object 'Strawberries' not found in ontology"

      # Get skeleton template
      assert "Triangle" in project.ontology_structure.skeleton_templates, "Skeleton template 'Triangle' not found"
      skeleton_template: SkeletonTemplate = project.ontology_structure.skeleton_templates["Triangle"]
      assert skeleton_template is not None, "Skeleton template 'Triangle' is None"

      # Get skeleton point IDs
      skeleton_ids = [coord.feature_hash for coord in skeleton_template.skeleton.values()]
      assert skeleton_ids, "Skeleton template 'Triangle' has no keypoints"

      # Get radio attribute for strawberry type
      strawberry_type_radio_attribute = ontology_structure.get_child_by_title(type_=RadioAttribute, title="Type?")
      assert strawberry_type_radio_attribute is not None, "Radio attribute 'Type?' not found"

      # Get radio options
      albion_option = strawberry_type_radio_attribute.get_child_by_title(type_=Option, title="Albion")
      assert albion_option is not None, "Option 'Albion' not found under 'Type?'"

      redcoat_option = strawberry_type_radio_attribute.get_child_by_title(type_=Option, title="Redcoat")
      assert redcoat_option is not None, "Option 'Redcoat' not found under 'Type?'"

      sweet_kiss_option = strawberry_type_radio_attribute.get_child_by_title(type_=Option, title="Sweet Kiss")
      assert sweet_kiss_option is not None, "Option 'Sweet Kiss' not found under 'Type?'"

      other_strawberry_option = strawberry_type_radio_attribute.get_child_by_title(
          type_=Option, title="Other strawberry type"
      )
      assert other_strawberry_option is not None, "Option 'Other strawberry type' not found under 'Type?'"

      # Albion Qualities
      albion_checklist_attribute = ontology_structure.get_child_by_title(type_=ChecklistAttribute, title="Albion Qualities?")
      assert albion_checklist_attribute is not None, "Checklist attribute 'Albion Qualities?' not found"

      albion_plump_option = albion_checklist_attribute.get_child_by_title(type_=Option, title="Plump")
      assert albion_plump_option is not None, "Option 'Plump' not found under 'Albion Qualities?'"

      albion_juicy_option = albion_checklist_attribute.get_child_by_title(type_=Option, title="Juicy")
      assert albion_juicy_option is not None, "Option 'Juicy' not found under 'Albion Qualities?'"

      albion_large_option = albion_checklist_attribute.get_child_by_title(type_=Option, title="Large")
      assert albion_large_option is not None, "Option 'Large' not found under 'Albion Qualities?'"

      # Redcoat Qualities
      redcoat_checklist_attribute = ontology_structure.get_child_by_title(
          type_=ChecklistAttribute, title="Redcoat Qualities?"
      )
      assert redcoat_checklist_attribute is not None, "Checklist attribute 'Redcoat Qualities?' not found"

      redcoat_plump_option = redcoat_checklist_attribute.get_child_by_title(type_=Option, title="Plump")
      assert redcoat_plump_option is not None, "Option 'Plump' not found under 'Redcoat Qualities?'"

      redcoat_juicy_option = redcoat_checklist_attribute.get_child_by_title(type_=Option, title="Juicy")
      assert redcoat_juicy_option is not None, "Option 'Juicy' not found under 'Redcoat Qualities?'"

      redcoat_large_option = redcoat_checklist_attribute.get_child_by_title(type_=Option, title="Large")
      assert redcoat_large_option is not None, "Option 'Large' not found under 'Redcoat Qualities?'"

      # Sweet Kiss Qualities
      sweet_kiss_checklist_attribute = ontology_structure.get_child_by_title(
          type_=ChecklistAttribute, title="Sweet Kiss Qualities?"
      )
      assert sweet_kiss_checklist_attribute is not None, "Checklist attribute 'Sweet Kiss Qualities?' not found"

      sweet_kiss_plump_option = sweet_kiss_checklist_attribute.get_child_by_title(type_=Option, title="Plump")
      assert sweet_kiss_plump_option is not None, "Option 'Plump' not found under 'Sweet Kiss Qualities?'"

      sweet_kiss_juicy_option = sweet_kiss_checklist_attribute.get_child_by_title(type_=Option, title="Juicy")
      assert sweet_kiss_juicy_option is not None, "Option 'Juicy' not found under 'Sweet Kiss Qualities?'"

      sweet_kiss_large_option = sweet_kiss_checklist_attribute.get_child_by_title(type_=Option, title="Large")
      assert sweet_kiss_large_option is not None, "Option 'Large' not found under 'Sweet Kiss Qualities?'"

      # Other strawberry type (text input)
      other_strawberry_option_text_attribute = ontology_structure.get_child_by_title(
          type_=TextAttribute, title="Specify strawberry type"
      )
      assert other_strawberry_option_text_attribute is not None, "Text attribute 'Specify strawberry type' not found"

      # Find number attribute in the ontology
      quality_number_attribute = ontology_structure.get_child_by_title(type_=NumericAttribute, title="Overall Quality")
      assert quality_number_attribute is not None, "Number attribute 'Overall Quality' not found in ontology."

      # Dictionary of labels per data unit and per frame with strawberry type specified, including quality options
      video_frame_labels = {
          "strawberries-001.jpg": {
              0: {
                  "label_ref": "strawberry_001",
                  "coordinates": SkeletonCoordinates(
                      values=[
                          SkeletonCoordinate(
                              x=0.25, y=0.25, name="point_0", color="#000000", value="point_0", feature_hash=skeleton_ids[0]
                          ),
                          SkeletonCoordinate(
                              x=0.35, y=0.25, name="point_1", color="#000000", value="point_1", feature_hash=skeleton_ids[1]
                          ),
                          SkeletonCoordinate(
                              x=0.25, y=0.35, name="point_2", color="#000000", value="point_2", feature_hash=skeleton_ids[2]
                          ),
                      ],
                      name="Triangle",
                  ),
                  "strawberry_type": "Albion",
                  "albion_quality_options": "Plump, Juicy",
                  "quality_number": 8
              }
          },
          "strawberries-010.jpg": {
              0: [
                  {
                      "label_ref": "strawberry_002",
                      "coordinates": SkeletonCoordinates(
                          values=[
                              SkeletonCoordinate(
                                  x=0.25,
                                  y=0.25,
                                  name="point_0",
                                  color="#000000",
                                  value="point_0",
                                  feature_hash=skeleton_ids[0],
                              ),
                              SkeletonCoordinate(
                                  x=0.35,
                                  y=0.25,
                                  name="point_1",
                                  color="#000000",
                                  value="point_1",
                                  feature_hash=skeleton_ids[1],
                              ),
                              SkeletonCoordinate(
                                  x=0.25,
                                  y=0.35,
                                  name="point_2",
                                  color="#000000",
                                  value="point_2",
                                  feature_hash=skeleton_ids[2],
                              ),
                          ],
                          name="Triangle",
                      ),
                      "strawberry_type": "Redcoat",
                      "redcoat_quality_options": "Plump, Juicy, Large",
                      "quality_number": 9
                  },
                  {
                      "label_ref": "strawberry_003",
                      "coordinates": SkeletonCoordinates(
                          values=[
                              SkeletonCoordinate(
                                  x=0.45,
                                  y=0.45,
                                  name="point_0",
                                  color="#000000",
                                  value="point_0",
                                  feature_hash=skeleton_ids[0],
                              ),
                              SkeletonCoordinate(
                                  x=0.55,
                                  y=0.45,
                                  name="point_1",
                                  color="#000000",
                                  value="point_1",
                                  feature_hash=skeleton_ids[1],
                              ),
                              SkeletonCoordinate(
                                  x=0.45,
                                  y=0.55,
                                  name="point_2",
                                  color="#000000",
                                  value="point_2",
                                  feature_hash=skeleton_ids[2],
                              ),
                          ],
                          name="Triangle",
                      ),
                      "strawberry_type": "Sweet Kiss",
                      "sweet_kiss_quality_options": "Plump",
                      "quality_number": 7
                  },
                  {
                      "label_ref": "strawberry_004",
                      "coordinates": SkeletonCoordinates(
                          values=[
                              SkeletonCoordinate(
                                  x=0.65,
                                  y=0.65,
                                  name="point_0",
                                  color="#000000",
                                  value="point_0",
                                  feature_hash=skeleton_ids[0],
                              ),
                              SkeletonCoordinate(
                                  x=0.75,
                                  y=0.65,
                                  name="point_1",
                                  color="#000000",
                                  value="point_1",
                                  feature_hash=skeleton_ids[1],
                              ),
                              SkeletonCoordinate(
                                  x=0.65,
                                  y=0.75,
                                  name="point_2",
                                  color="#000000",
                                  value="point_2",
                                  feature_hash=skeleton_ids[2],
                              ),
                          ],
                          name="Triangle",
                      ),
                      "strawberry_type": "Other strawberry type",
                      "Specify strawberry type": "Pineberry",
                      "quality_number": 4
                  },
              ],
          },
          "strawberries-ig": {
              0: {
                  "label_ref": "strawberry_005",
                  "coordinates": SkeletonCoordinates(
                      values=[
                          SkeletonCoordinate(
                              x=0.25, y=0.25, name="point_0", color="#000000", value="point_0", feature_hash=skeleton_ids[0]
                          ),
                          SkeletonCoordinate(
                              x=0.35, y=0.25, name="point_1", color="#000000", value="point_1", feature_hash=skeleton_ids[1]
                          ),
                          SkeletonCoordinate(
                              x=0.25, y=0.35, name="point_2", color="#000000", value="point_2", feature_hash=skeleton_ids[2]
                          ),
                      ],
                      name="Triangle",
                  ),
                  "strawberry_type": "Albion",
                  "albion_quality_options": "Plump, Juicy",
                  "quality_number": 8
              },
              2: [
                  {
                      "label_ref": "strawberry_006",
                      "coordinates": SkeletonCoordinates(
                          values=[
                              SkeletonCoordinate(
                                  x=0.25,
                                  y=0.25,
                                  name="point_0",
                                  color="#000000",
                                  value="point_0",
                                  feature_hash=skeleton_ids[0],
                              ),
                              SkeletonCoordinate(
                                  x=0.35,
                                  y=0.25,
                                  name="point_1",
                                  color="#000000",
                                  value="point_1",
                                  feature_hash=skeleton_ids[1],
                              ),
                              SkeletonCoordinate(
                                  x=0.25,
                                  y=0.35,
                                  name="point_2",
                                  color="#000000",
                                  value="point_2",
                                  feature_hash=skeleton_ids[2],
                              ),
                          ],
                          name="Triangle",
                      ),
                      "strawberry_type": "Redcoat",
                      "redcoat_quality_options": "Large",
                      "quality_number": 6
                  },
                  {
                      "label_ref": "strawberry_007",
                      "coordinates": SkeletonCoordinates(
                          values=[
                              SkeletonCoordinate(
                                  x=0.45,
                                  y=0.45,
                                  name="point_0",
                                  color="#000000",
                                  value="point_0",
                                  feature_hash=skeleton_ids[0],
                              ),
                              SkeletonCoordinate(
                                  x=0.55,
                                  y=0.45,
                                  name="point_1",
                                  color="#000000",
                                  value="point_1",
                                  feature_hash=skeleton_ids[1],
                              ),
                              SkeletonCoordinate(
                                  x=0.45,
                                  y=0.55,
                                  name="point_2",
                                  color="#000000",
                                  value="point_2",
                                  feature_hash=skeleton_ids[2],
                              ),
                          ],
                          name="Triangle",
                      ),
                      "strawberry_type": "Sweet Kiss",
                      "sweet_kiss_quality_options": "Plump",
                      "quality_number": 5
                  },
                  {
                      "label_ref": "strawberry_008",
                      "coordinates": SkeletonCoordinates(
                          values=[
                              SkeletonCoordinate(
                                  x=0.65,
                                  y=0.65,
                                  name="point_0",
                                  color="#000000",
                                  value="point_0",
                                  feature_hash=skeleton_ids[0],
                              ),
                              SkeletonCoordinate(
                                  x=0.75,
                                  y=0.65,
                                  name="point_1",
                                  color="#000000",
                                  value="point_1",
                                  feature_hash=skeleton_ids[1],
                              ),
                              SkeletonCoordinate(
                                  x=0.65,
                                  y=0.75,
                                  name="point_2",
                                  color="#000000",
                                  value="point_2",
                                  feature_hash=skeleton_ids[2],
                              ),
                          ],
                          name="Triangle",
                      ),
                      "strawberry_type": "Other strawberry type",
                      "Specify strawberry type": "Pineberry",
                      "quality_number": 7
                  },
              ],
          },
          "strawberries-is": {
              0: {
                  "label_ref": "strawberry_009",
                  "coordinates": SkeletonCoordinates(
                      values=[
                          SkeletonCoordinate(
                              x=0.25, y=0.25, name="point_0", color="#000000", value="point_0", feature_hash=skeleton_ids[0]
                          ),
                          SkeletonCoordinate(
                              x=0.35, y=0.25, name="point_1", color="#000000", value="point_1", feature_hash=skeleton_ids[1]
                          ),
                          SkeletonCoordinate(
                              x=0.25, y=0.35, name="point_2", color="#000000", value="point_2", feature_hash=skeleton_ids[2]
                          ),
                      ],
                      name="Triangle",
                  ),
                  "strawberry_type": "Albion",
                  "albion_quality_options": "Plump",
                  "quality_number": 4
              },
              3: [
                  {
                      "label_ref": "strawberry_010",
                      "coordinates": SkeletonCoordinates(
                          values=[
                              SkeletonCoordinate(
                                  x=0.25,
                                  y=0.25,
                                  name="point_0",
                                  color="#000000",
                                  value="point_0",
                                  feature_hash=skeleton_ids[0],
                              ),
                              SkeletonCoordinate(
                                  x=0.35,
                                  y=0.25,
                                  name="point_1",
                                  color="#000000",
                                  value="point_1",
                                  feature_hash=skeleton_ids[1],
                              ),
                              SkeletonCoordinate(
                                  x=0.25,
                                  y=0.35,
                                  name="point_2",
                                  color="#000000",
                                  value="point_2",
                                  feature_hash=skeleton_ids[2],
                              ),
                          ],
                          name="Triangle",
                      ),
                      "strawberry_type": "Redcoat",
                      "redcoat_quality_options": "Plump, Juicy, Large",
                      "quality_number": 9
                  },
                  {
                      "label_ref": "strawberry_011",
                      "coordinates": SkeletonCoordinates(
                          values=[
                              SkeletonCoordinate(
                                  x=0.45,
                                  y=0.45,
                                  name="point_0",
                                  color="#000000",
                                  value="point_0",
                                  feature_hash=skeleton_ids[0],
                              ),
                              SkeletonCoordinate(
                                  x=0.55,
                                  y=0.45,
                                  name="point_1",
                                  color="#000000",
                                  value="point_1",
                                  feature_hash=skeleton_ids[1],
                              ),
                              SkeletonCoordinate(
                                  x=0.45,
                                  y=0.55,
                                  name="point_2",
                                  color="#000000",
                                  value="point_2",
                                  feature_hash=skeleton_ids[2],
                              ),
                          ],
                          name="Triangle",
                      ),
                      "strawberry_type": "Sweet Kiss",
                      "sweet_kiss_quality_options": "Plump",
                      "quality_number": 7
                  },
                  {
                      "label_ref": "strawberry_012",
                      "coordinates": SkeletonCoordinates(
                          values=[
                              SkeletonCoordinate(
                                  x=0.65,
                                  y=0.65,
                                  name="point_0",
                                  color="#000000",
                                  value="point_0",
                                  feature_hash=skeleton_ids[0],
                              ),
                              SkeletonCoordinate(
                                  x=0.75,
                                  y=0.65,
                                  name="point_1",
                                  color="#000000",
                                  value="point_1",
                                  feature_hash=skeleton_ids[1],
                              ),
                              SkeletonCoordinate(
                                  x=0.65,
                                  y=0.75,
                                  name="point_2",
                                  color="#000000",
                                  value="point_2",
                                  feature_hash=skeleton_ids[2],
                              ),
                          ],
                          name="Triangle",
                      ),
                      "strawberry_type": "Other strawberry type",
                      "Specify strawberry type": "Pineberry",
                      "quality_number": 7
                  },
              ],
          },
          "strawberries-vid-001.mp4": {
              103: [
                  {
                      "label_ref": "strawberry_013",
                      "coordinates": SkeletonCoordinates(
                          values=[
                              SkeletonCoordinate(
                                  x=0.25,
                                  y=0.25,
                                  name="point_0",
                                  color="#000000",
                                  value="point_0",
                                  feature_hash=skeleton_ids[0],
                              ),
                              SkeletonCoordinate(
                                  x=0.35,
                                  y=0.25,
                                  name="point_1",
                                  color="#000000",
                                  value="point_1",
                                  feature_hash=skeleton_ids[1],
                              ),
                              SkeletonCoordinate(
                                  x=0.25,
                                  y=0.35,
                                  name="point_2",
                                  color="#000000",
                                  value="point_2",
                                  feature_hash=skeleton_ids[2],
                              ),
                          ],
                          name="Triangle",
                      ),
                      "strawberry_type": "Sweet Kiss",
                      "sweet_kiss_quality_options": "Plump",
                      "quality_number": 7
                  },
                  {
                      "label_ref": "strawberry_014",
                      "coordinates": SkeletonCoordinates(
                          values=[
                              SkeletonCoordinate(
                                  x=0.45,
                                  y=0.45,
                                  name="point_0",
                                  color="#000000",
                                  value="point_0",
                                  feature_hash=skeleton_ids[0],
                              ),
                              SkeletonCoordinate(
                                  x=0.55,
                                  y=0.45,
                                  name="point_1",
                                  color="#000000",
                                  value="point_1",
                                  feature_hash=skeleton_ids[1],
                              ),
                              SkeletonCoordinate(
                                  x=0.45,
                                  y=0.55,
                                  name="point_2",
                                  color="#000000",
                                  value="point_2",
                                  feature_hash=skeleton_ids[2],
                              ),
                          ],
                          name="Triangle",
                      ),
                      "strawberry_type": "Albion",
                      "albion_quality_options": "Plump, Juicy, Large",
                      "quality_number": 9
                  },
                  {
                      "label_ref": "strawberry_015",
                      "coordinates": SkeletonCoordinates(
                          values=[
                              SkeletonCoordinate(
                                  x=0.65,
                                  y=0.65,
                                  name="point_0",
                                  color="#000000",
                                  value="point_0",
                                  feature_hash=skeleton_ids[0],
                              ),
                              SkeletonCoordinate(
                                  x=0.75,
                                  y=0.65,
                                  name="point_1",
                                  color="#000000",
                                  value="point_1",
                                  feature_hash=skeleton_ids[1],
                              ),
                              SkeletonCoordinate(
                                  x=0.65,
                                  y=0.75,
                                  name="point_2",
                                  color="#000000",
                                  value="point_2",
                                  feature_hash=skeleton_ids[2],
                              ),
                          ],
                          name="Triangle",
                      ),
                      "strawberry_type": "Other strawberry type",
                      "Specify strawberry type": "Pineberry",
                      "quality_number": 6
                  },
              ],
              104: [
                  {
                      "label_ref": "strawberry_016",
                      "coordinates": SkeletonCoordinates(
                          values=[
                              SkeletonCoordinate(
                                  x=0.15,
                                  y=0.15,
                                  name="point_0",
                                  color="#000000",
                                  value="point_0",
                                  feature_hash=skeleton_ids[0],
                              ),
                              SkeletonCoordinate(
                                  x=0.25,
                                  y=0.25,
                                  name="point_1",
                                  color="#000000",
                                  value="point_1",
                                  feature_hash=skeleton_ids[1],
                              ),
                              SkeletonCoordinate(
                                  x=0.15,
                                  y=0.15,
                                  name="point_2",
                                  color="#000000",
                                  value="point_2",
                                  feature_hash=skeleton_ids[2],
                              ),
                          ],
                          name="Triangle",
                      ),
                      "strawberry_type": "Sweet Kiss",
                      "sweet_kiss_quality_options": "Plump",
                      "quality_number": 8
                  },
                  {
                      "label_ref": "strawberry_014",
                      "coordinates": SkeletonCoordinates(
                          values=[
                              SkeletonCoordinate(
                                  x=0.35,
                                  y=0.35,
                                  name="point_0",
                                  color="#000000",
                                  value="point_0",
                                  feature_hash=skeleton_ids[0],
                              ),
                              SkeletonCoordinate(
                                  x=0.45,
                                  y=0.35,
                                  name="point_1",
                                  color="#000000",
                                  value="point_1",
                                  feature_hash=skeleton_ids[1],
                              ),
                              SkeletonCoordinate(
                                  x=0.35,
                                  y=0.45,
                                  name="point_2",
                                  color="#000000",
                                  value="point_2",
                                  feature_hash=skeleton_ids[2],
                              ),
                          ],
                          name="Triangle",
                      ),
                      "strawberry_type": "Albion",
                      "albion_quality_options": "Plump, Juicy, Large",
                      "quality_number": 8
                  },
                  {
                      "label_ref": "strawberry_017",
                      "coordinates": SkeletonCoordinates(
                          values=[
                              SkeletonCoordinate(
                                  x=0.55,
                                  y=0.55,
                                  name="point_0",
                                  color="#000000",
                                  value="point_0",
                                  feature_hash=skeleton_ids[0],
                              ),
                              SkeletonCoordinate(
                                  x=0.65,
                                  y=0.55,
                                  name="point_1",
                                  color="#000000",
                                  value="point_1",
                                  feature_hash=skeleton_ids[1],
                              ),
                              SkeletonCoordinate(
                                  x=0.55,
                                  y=0.65,
                                  name="point_2",
                                  color="#000000",
                                  value="point_2",
                                  feature_hash=skeleton_ids[2],
                              ),
                          ],
                          name="Triangle",
                      ),
                      "strawberry_type": "Other strawberry type",
                      "Specify strawberry type": "Pineberry",
                      "quality_number": 7
                  },
              ],
              105: [
                  {
                      "label_ref": "strawberry_016",
                      "coordinates": SkeletonCoordinates(
                          values=[
                              SkeletonCoordinate(
                                  x=0.25,
                                  y=0.25,
                                  name="point_0",
                                  color="#000000",
                                  value="point_0",
                                  feature_hash=skeleton_ids[0],
                              ),
                              SkeletonCoordinate(
                                  x=0.35,
                                  y=0.25,
                                  name="point_1",
                                  color="#000000",
                                  value="point_1",
                                  feature_hash=skeleton_ids[1],
                              ),
                              SkeletonCoordinate(
                                  x=0.25,
                                  y=0.35,
                                  name="point_2",
                                  color="#000000",
                                  value="point_2",
                                  feature_hash=skeleton_ids[2],
                              ),
                          ],
                          name="Triangle",
                      ),
                      "strawberry_type": "Sweet Kiss",
                      "sweet_kiss_quality_options": "Plump",
                      "quality_number": 6
                  },
                  {
                      "label_ref": "strawberry_014",
                      "coordinates": SkeletonCoordinates(
                          values=[
                              SkeletonCoordinate(
                                  x=0.45,
                                  y=0.45,
                                  name="point_0",
                                  color="#000000",
                                  value="point_0",
                                  feature_hash=skeleton_ids[0],
                              ),
                              SkeletonCoordinate(
                                  x=0.55,
                                  y=0.45,
                                  name="point_1",
                                  color="#000000",
                                  value="point_1",
                                  feature_hash=skeleton_ids[1],
                              ),
                              SkeletonCoordinate(
                                  x=0.45,
                                  y=0.55,
                                  name="point_2",
                                  color="#000000",
                                  value="point_2",
                                  feature_hash=skeleton_ids[2],
                              ),
                          ],
                          name="Triangle",
                      ),
                      "strawberry_type": "Albion",
                      "albion_quality_options": "Plump, Juicy, Large",
                      "quality_number": 9
                  },
                  {
                      "label_ref": "strawberry_017",
                      "coordinates": SkeletonCoordinates(
                          values=[
                              SkeletonCoordinate(
                                  x=0.75,
                                  y=0.75,
                                  name="point_0",
                                  color="#000000",
                                  value="point_0",
                                  feature_hash=skeleton_ids[0],
                              ),
                              SkeletonCoordinate(
                                  x=0.65,
                                  y=0.75,
                                  name="point_1",
                                  color="#000000",
                                  value="point_1",
                                  feature_hash=skeleton_ids[1],
                              ),
                              SkeletonCoordinate(
                                  x=0.75,
                                  y=0.65,
                                  name="point_2",
                                  color="#000000",
                                  value="point_2",
                                  feature_hash=skeleton_ids[2],
                              ),
                          ],
                          name="Triangle",
                      ),
                      "strawberry_type": "Other strawberry type",
                      "Specify strawberry type": "Pineberry",
                      "quality_number": 5
                  },
              ],
          },
      }


      # Loop through each data unit (image, video, etc.)
      for data_unit, frame_coordinates in video_frame_labels.items():
          object_instances_by_label_ref = {}

          # Get the label row for the current data unit
          label_rows = project.list_label_rows_v2(data_title_eq=data_unit)
          assert isinstance(label_rows, list), f"Expected list of label rows for '{data_unit}', got {type(label_rows)}"
          assert label_rows, f"No label row found for data unit: {data_unit}"

          label_row = label_rows[0]
          assert label_row is not None, f"Label row is None for {data_unit}"

          # Initialize label row using bundle
          with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
              label_row.initialise_labels()
              assert label_row.ontology_structure is not None, f"Ontology not initialized for label row: {data_unit}"

              for frame_number, items in frame_coordinates.items():
                  assert isinstance(frame_number, int), f"Frame number must be int, got {type(frame_number)}"
                  if not isinstance(items, list):
                      items = [items]

                  for item in items:
                      label_ref = item["label_ref"]
                      coord = item["coordinates"]
                      strawberry_type = item["strawberry_type"]
                      quality_number = item["quality_number"]

                      assert strawberry_type in {
                          "Albion",
                          "Redcoat",
                          "Sweet Kiss",
                          "Other strawberry type",
                      }, f"Unexpected strawberry type '{strawberry_type}' in data unit '{data_unit}'"

                      if label_ref not in object_instances_by_label_ref:
                          skeleton_object_instance: ObjectInstance = skeleton_ontology_object.create_instance()
                          assert skeleton_object_instance is not None, f"Failed to create ObjectInstance for {label_ref}"

                          # Set quality number attribute 
                          skeleton_object_instance.set_answer(attribute=quality_number_attribute, answer=quality_number)

                          object_instances_by_label_ref[label_ref] = skeleton_object_instance
                          checklist_attribute = None

                          # Set strawberry type radio attribute
                          if strawberry_type == "Albion":
                              assert albion_option is not None, "Missing 'albion_option'"
                              skeleton_object_instance.set_answer(
                                  attribute=strawberry_type_radio_attribute, answer=albion_option
                              )
                              checklist_attribute = albion_checklist_attribute
                          elif strawberry_type == "Redcoat":
                              assert redcoat_option is not None, "Missing 'redcoat_option'"
                              skeleton_object_instance.set_answer(
                                  attribute=strawberry_type_radio_attribute, answer=redcoat_option
                              )
                              checklist_attribute = redcoat_checklist_attribute
                          elif strawberry_type == "Sweet Kiss":
                              assert sweet_kiss_option is not None, "Missing 'sweet_kiss_option'"
                              skeleton_object_instance.set_answer(
                                  attribute=strawberry_type_radio_attribute, answer=sweet_kiss_option
                              )
                              checklist_attribute = sweet_kiss_checklist_attribute
                          elif strawberry_type == "Other strawberry type":
                              assert other_strawberry_option is not None, "Missing 'other_strawberry_option'"
                              skeleton_object_instance.set_answer(
                                  attribute=strawberry_type_radio_attribute, answer=other_strawberry_option
                              )
                              text_answer = item.get("Specify strawberry type", "")
                              assert isinstance(text_answer, str), "'Specify strawberry type' must be a string"
                              skeleton_object_instance.set_answer(
                                  attribute=other_strawberry_option_text_attribute,
                                  answer=text_answer,
                              )

                          # Set checklist attributes
                          checklist_answers = []
                          quality_key = f"{strawberry_type.lower().replace(' ', '_')}_quality_options"
                          quality_options = item.get(quality_key, "").split(", ")

                          for quality in quality_options:
                              option = None
                              if quality == "Plump":
                                  option = (
                                      albion_plump_option
                                      if strawberry_type == "Albion"
                                      else redcoat_plump_option
                                      if strawberry_type == "Redcoat"
                                      else sweet_kiss_plump_option
                                      if strawberry_type == "Sweet Kiss"
                                      else None
                                  )
                              elif quality == "Juicy":
                                  option = (
                                      albion_juicy_option
                                      if strawberry_type == "Albion"
                                      else redcoat_juicy_option
                                      if strawberry_type == "Redcoat"
                                      else sweet_kiss_juicy_option
                                      if strawberry_type == "Sweet Kiss"
                                      else None
                                  )
                              elif quality == "Large":
                                  option = (
                                      albion_large_option
                                      if strawberry_type == "Albion"
                                      else redcoat_large_option
                                      if strawberry_type == "Redcoat"
                                      else sweet_kiss_large_option
                                      if strawberry_type == "Sweet Kiss"
                                      else None
                                  )

                              if option:
                                  checklist_answers.append(option)
                              else:
                                  assert strawberry_type == "Other strawberry type", (
                                      f"Invalid quality '{quality}' for strawberry type '{strawberry_type}'"
                                  )

                          if checklist_attribute and checklist_answers:
                              skeleton_object_instance.set_answer(
                                  attribute=checklist_attribute, answer=checklist_answers, overwrite=True
                              )

                      else:
                          skeleton_object_instance = object_instances_by_label_ref[label_ref]

                      # Assign the object to the frame and track it
                      skeleton_object_instance.set_for_frames(coordinates=coord, frames=frame_number)

              # Add object instances to label_row **only if they have frames assigned**
              for skeleton_object_instance in object_instances_by_label_ref.values():
                  assert isinstance(skeleton_object_instance, ObjectInstance), "Expected ObjectInstance type"
                  if skeleton_object_instance.get_annotation_frames():
                      label_row.add_object_instance(skeleton_object_instance)

              # Save label row using the bundle
              assert label_row is not None, "Trying to save a None label row"
              label_row.save(bundle=bundle)

      print("Labels with strawberry type radio buttons, checklist attributes, number attributes, and text labels added for all data units.")

      ```
    </CodeGroup>
  </Accordion>
</AccordionGroup>

## Classifications

<AccordionGroup>
  <Accordion title="Text Classification">
    The following example assumes the Ontology includes a text classification field named `Mood`. In this example, the text classification for the first label row (data unit) in the Project is set to `Melancholy` on the first frame.

    * Replace `<private_key_path>` with the key to your private key for authentication.
    * Replace `<project_hash>` with the hash of your Project.
    * Replace the Classification names and answers to suit your needs.

    ```python theme={"dark"}
    # Import dependencies
    from typing import List

    from encord import EncordUserClient
    from encord.objects import LabelRowV2, Classification, ClassificationInstance, OntologyStructure

    # Instantiate Encord client by replacing <private_key_path> with the path to your private key
    user_client = EncordUserClient.create_with_ssh_private_key(
        ssh_private_key_path="<private_key_path>"
    )

    # Specify the Project. Replace <project_hash> with the hash of your Project
    project = user_client.get_project("<project_hash>")

    # For simplicity, get only the first label row
    first_label_row: List[LabelRowV2] = project.list_label_rows_v2()[0]

    # Download the existing labels 
    first_label_row.initialise_labels()

    # Get Ontology Structure
    ontology_structure: OntologyStructure = first_label_row.ontology_structure

    # Assume that the following text classification exists in the Ontology.
    text_ontology_classification: Classification = (
        ontology_structure.get_child_by_title(
            title="Mood", type_=Classification
        )
    )
    text_classification_instance = text_ontology_classification.create_instance()

    # Set the value of the classification instance
    text_classification_instance.set_answer(answer="Melancholy")

    # Select the frames where the classification instance is present. Not required for global classifications
    text_classification_instance.set_for_frames(frames=0)

    # Add it to the label row
    first_label_row.add_classification_instance(text_classification_instance)

    # Save labels
    first_label_row.save()
    ```
  </Accordion>
</AccordionGroup>

<AccordionGroup>
  <Accordion title="Text">
    **Example 1:**

    Adds a Text classification to a specific data unit. Ensure you replace `<data-unit-name>` with the name of the data unit you want to add the classification to.

    **Example 2:**

    Adds a Text attribute to an arbitrary bounding box on a specific data unit. Ensure you replace `<data-unit-name>` with the name of the data unit you want to add the classification to, and `<project_id>` with the unique ID of the Project.

    <CodeGroup>
      ```python Example 1 theme={"dark"}
      from encord import EncordUserClient
      from encord.objects import OntologyStructure, Classification

      user_client = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path="<private_key_path>"
      )

      project = user_client.get_project("<project_id>")

      label_row = project.list_label_rows_v2(
          data_title_eq="<data-unit-name>"
      )[0]

      label_row.initialise_labels()

      # Get Ontology Structure
      ontology_structure: OntologyStructure = label_row.ontology_structure

      # Assume that the following text classification exists in the Ontology.
      text_ontology_classification: Classification = (
          ontology_structure.get_child_by_title(
              title="Name", type_=Classification
          )
      )

      text_classification_instance = text_ontology_classification.create_instance()

      # Set the value of the classification instance
      text_classification_instance.set_answer(answer="Dexter")

      # Select the frames where the classification instance is present. Not required for global classifications
      text_classification_instance.set_for_frames(frames=0)

      # Add it to the label row
      label_row.add_classification_instance(text_classification_instance)

      # Save labels
      label_row.save()
      print('added classification instance')
      ```

      ```python Example 2 theme={"dark"}
      from encord import EncordUserClient
      from encord.objects import OntologyStructure, Object

      from encord.objects.attributes import TextAttribute
      from encord.objects.coordinates import BoundingBoxCoordinates

      # Instantiate Encord client by replacing <private_key_path> with the path to your private key
      user_client = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path="<private_key_path>"
      )

      # Get Project
      project = user_client.get_project("<project_id>")

      # Get label rows
      label_row = project.list_label_rows_v2(
          data_title_eq="<data-unit-name>"
      )[0]

      #Initialise labels
      label_row.initialise_labels()

      # Get Ontology Structure
      ontology_structure: OntologyStructure = label_row.ontology_structure

      # Define the object
      person_object: Object = ontology_structure.get_child_by_title(
                  title="Person", type_=Object
              )

      # Define the text attribute
      name_attribute = person_object.get_child_by_title("Name", type_=TextAttribute)

      # Create object instance
      person_object_instance = person_object.create_instance()

      # Add arbitrary bounding box
      person_object_instance.set_for_frames(
          coordinates=BoundingBoxCoordinates(0.5, 0.5, 0.5, 0.5),
          frames=0,
          manual_annotation=True
      )

      # Set attribute 
      person_object_instance.set_answer(
          answer="Dexter",
          attribute=name_attribute,
      )

      # Add object instance
      label_row.add_object_instance(person_object_instance)

      # Save labels 
      label_row.save()

      print('added object instance')
      ```
    </CodeGroup>
  </Accordion>
</AccordionGroup>

<AccordionGroup>
  <Accordion title="Number">
    **Example 1:**

    Adds a Number input to a specific data unit. Ensure you replace `<data-unit-name>` with the name of the data unit you want to add the classification to.

    **Example 2:**

    Adds a Number attribute to an arbitrary bounding box on a specific data unit. Ensure you replace `<data-unit-name>` with the name of the data unit you want to add the classification to, and `<project_id>` with the unique ID of the Project.

    <CodeGroup>
      ```python Example 1 theme={"dark"}
      from encord import EncordUserClient
      from encord.objects import OntologyStructure, Classification

      user_client = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path="<private_key_path>"
      )

      project = user_client.get_project("<project_id>")

      label_row = project.list_label_rows_v2(
          data_title_eq="<data-unit-name>"
      )[0]

      label_row.initialise_labels()

      # Get Ontology Structure
      ontology_structure: OntologyStructure = label_row.ontology_structure

      # Assume that the following Number input exists in the Ontology.
      number_ontology_classification: Classification = (
          ontology_structure.get_child_by_title(
              title="Score", type_=Classification
          )
      )

      number_classification_instance = number_ontology_classification.create_instance()

      # Set the value of the classification instance
      number_classification_instance.set_answer(answer=2)

      # Select the frames where the classification instance is present. Not required for global classifications
      number_classification_instance.set_for_frames(frames=0)

      # Add it to the label row
      label_row.add_classification_instance(number_classification_instance)

      # Save labels
      label_row.save()
      print('added classification instance')
      ```

      ```python Example 2 theme={"dark"}
      from encord import EncordUserClient
      from encord.objects import OntologyStructure, Object

      from encord.objects.attributes import NumericAttribute
      from encord.objects.coordinates import BoundingBoxCoordinates

      # Instantiate Encord client by replacing <private_key_path> with the path to your private key
      user_client = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path="<private_key_path>"
      )

      # Get Project
      project = user_client.get_project("<project_id>")

      # Get label rows
      label_row = project.list_label_rows_v2(
          data_title_eq="<data-unit-name>"
      )[0]

      #Initialise labels
      label_row.initialise_labels()

      # Get Ontology Structure
      ontology_structure: OntologyStructure = label_row.ontology_structure

      # Define the object
      car_object: Object = ontology_structure.get_child_by_title(
                  title="Car", type_=Object
              )

      # Get the numerical attribute
      race_position_attribute = car_object.get_child_by_title("Race Position", type_=NumericAttribute)

      # Create object instance
      car_object_instance = car_object.create_instance()

      # Add arbitrary bounding box
      car_object_instance.set_for_frames(
          coordinates=BoundingBoxCoordinates(0.5, 0.5, 0.5, 0.5),
          frames=0,
          manual_annotation=True
      )

      # Set attribute answer
      car_object_instance.set_answer(
          answer=2,
          attribute=race_position_attribute,
      )

      # Add object instance
      label_row.add_object_instance(car_object_instance)

      # Save labels 
      label_row.save()

      print('added object instance')
      ```
    </CodeGroup>
  </Accordion>
</AccordionGroup>

<AccordionGroup>
  <Accordion title="Radio Button">
    **Example 1:**

    Imports a Radio button options (`Blueberry or Cherry?`) to a single image (`blueberry_003.jpg`).

    **Example 2:**

    Imports a Radio button options (`Blueberry or Cherry?`) across a range of sequential frames (193 to 197) to a video (`Blueberries_video.mp4`).

    <CodeGroup>
      ```python Radio Button Template theme={"dark"}
      #Import dependencies
      from __future__ import annotations
      from pathlib import Path
      from encord import EncordUserClient, Project
      from encord.objects import (
          Classification,
      )
      from collections import defaultdict
      from copy import deepcopy
      from dataclasses import dataclass, field
      from datetime import datetime
      from typing import (
          TYPE_CHECKING,
          Any,
          Dict,
          Iterable,
          List,
          Optional,
          Sequence,
          Set,
          Tuple,
          Union,
      )
      from dateutil.parser import parse
      from encord.constants.enums import DataType
      from encord.exceptions import LabelRowError
      from encord.objects import ChecklistAttribute, RadioAttribute, TextAttribute
      from encord.objects.answers import (
          Answer,
          _get_static_answer_map,
          get_default_answer_from_attribute,
      )

      from encord.objects.frames import (
          Frames,
          Ranges,
      )
      from encord.objects.internal_helpers import (
          _infer_attribute_from_answer,
          _search_child_attributes,
      )
      from encord.objects.ontology_object import Object
      from encord.objects.options import Option
      from encord.objects.utils import check_email, short_uuid_str

      if TYPE_CHECKING:
          from encord.objects.ontology_labels_impl import LabelRowV2


      SSH_PATH = "<file-path-to-ssh-private-key>"
      PROJECT_ID = "<project-unique-id>"

      # Create user client using access key
      user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
          Path(SSH_PATH).read_text()
      )

      # Get project for which predictions are to be added.
      project: Project = user_client.get_project(PROJECT_ID)


      # Creating classification- START
      # Specify the data unit to apply classification
      label_row = project.list_label_rows_v2(
          data_title_eq="<data-unit-name>"
      )[0]

      label_row.initialise_labels()


      # Assume that the following radio classification exists in the ontology.

      radio_ontology_classification: Classification = project.ontology_structure.get_child_by_title(
          title="<classification-name>",
          type_=Classification,
      )

      blueberry_option = radio_ontology_classification.get_child_by_title(
          title="<radio-button-option-title>", type_=Option
      )

      radio_classification_instance = (
         radio_ ontology_classification.create_instance()
      )

      radio_classification_instance.set_answer(
          answer=<radio-button-option>
      )
      radio_classification_instance.set_for_frames(
          # Add the classification to the image
          frames=0,
          # There are multiple additional fields that can be set optionally:
          manual_annotation=True,
          confidence=1.0,
      )

      label_row.add_classification_instance(radio_classification_instance)


      label_row.save()
      ```

      ```python Example 1 theme={"dark"}
      #Import dependencies
      from __future__ import annotations
      from pathlib import Path
      from encord import EncordUserClient, Project
      from encord.objects import (
          Classification,
      )
      from collections import defaultdict
      from copy import deepcopy
      from dataclasses import dataclass, field
      from datetime import datetime
      from typing import (
          TYPE_CHECKING,
          Any,
          Dict,
          Iterable,
          List,
          Optional,
          Sequence,
          Set,
          Tuple,
          Union,
      )
      from dateutil.parser import parse
      from encord.constants.enums import DataType
      from encord.exceptions import LabelRowError
      from encord.objects import ChecklistAttribute, RadioAttribute, TextAttribute
      from encord.objects.answers import (
          Answer,
          _get_static_answer_map,
          get_default_answer_from_attribute,
      )

      from encord.objects.frames import (
          Frames,
          Ranges,
      )
      from encord.objects.internal_helpers import (
          _infer_attribute_from_answer,
          _search_child_attributes,
      )
      from encord.objects.ontology_object import Object
      from encord.objects.options import Option
      from encord.objects.utils import check_email, short_uuid_str

      if TYPE_CHECKING:
          from encord.objects.ontology_labels_impl import LabelRowV2


      SSH_PATH = "/Users/chris-encord/sdk-ssh-private-key.txt"
      PROJECT_ID = "7d4ead9c-4087-4832-a301-eb2545e7d43b"

      # Create user client using access key
      user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
          Path(SSH_PATH).read_text()
      )

      # Get project for which predictions are to be added.
      project: Project = user_client.get_project(PROJECT_ID)


      # Creating classification- START
      # Specify the data unit to apply classification
      label_row = project.list_label_rows_v2(
          data_title_eq="blueberry_003.jpg"
      )[0]

      label_row.initialise_labels()


      # Assume that the following radio classification exists in the ontology.

      radio_ontology_classification: Classification = project.ontology_structure.get_child_by_title(
          title="Blueberry or Cherry?",
          type_=Classification,
      )

      blueberry_option = radio_ontology_classification.get_child_by_title(
          title="Blueberry", type_=Option
      )

      radio_classification_instance = (
         radio_ontology_classification.create_instance()
      )

      radio_classification_instance.set_answer(
          answer=blueberry_option
      )
      radio_classification_instance.set_for_frames(
          # Add the classification to the image
          frames=0,
          # There are multiple additional fields that can be set optionally:
          manual_annotation=True,
          confidence=1.0,
      )

      label_row.add_classification_instance(radio_classification_instance)


      label_row.save()

      ```

      ```python Example 2 theme={"dark"}
      #Import dependencies
      from __future__ import annotations
      from pathlib import Path
      from encord import EncordUserClient, Project
      from encord.objects import (
          Classification,
      )
      from collections import defaultdict
      from copy import deepcopy
      from dataclasses import dataclass, field
      from datetime import datetime
      from typing import (
          TYPE_CHECKING,
          Any,
          Dict,
          Iterable,
          List,
          Optional,
          Sequence,
          Set,
          Tuple,
          Union,
      )
      from dateutil.parser import parse
      from encord.constants.enums import DataType
      from encord.exceptions import LabelRowError
      from encord.objects import ChecklistAttribute, RadioAttribute, TextAttribute
      from encord.objects.answers import (
          Answer,
          _get_static_answer_map,
          get_default_answer_from_attribute,
      )

      from encord.objects.frames import (
          Frames,
          Range,
          Ranges,
      )
      from encord.objects.internal_helpers import (
          _infer_attribute_from_answer,
          _search_child_attributes,
      )
      from encord.objects.ontology_object import Object
      from encord.objects.options import Option
      from encord.objects.utils import check_email, short_uuid_str

      if TYPE_CHECKING:
          from encord.objects.ontology_labels_impl import LabelRowV2


      SSH_PATH = "/Users/chris-encord/sdk-ssh-private-key.txt"
      PROJECT_ID = "7d4ead9c-4087-4832-a301-eb2545e7d43b"

      # Create user client using access key
      user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
          Path(SSH_PATH).read_text()
      )

      # Get project for which classifications are to be added.
      project: Project = user_client.get_project(PROJECT_ID)


      # Creating Checklist options- START
      # Specify the data unit to add classification
      label_row = project.list_label_rows_v2(
          data_title_eq="Blueberries_video.mp4"
      )[0]

      label_row.initialise_labels()


      # Assume that the following radio classification exists in the ontology.

      radio_ontology_classification: Classification = project.ontology_structure.get_child_by_title(
          title="Blueberry or Cherry?",
          type_=Classification,
      )

      blueberry_option = radio_ontology_classification.get_child_by_title(
          title="Blueberry", type_=Option
      )

      radio_classification_instance = (
          radio_ontology_classification.create_instance()
      )

      radio_classification_instance.set_answer(
          answer=blueberry_option,

      )
      radio_classification_instance.set_for_frames(
          frames=Range(start=160, end=165),
          # There are multiple additional fields that can be set optionally:
          manual_annotation=True,
          confidence=1.0,
      )

      label_row.add_classification_instance(radio_classification_instance)


      label_row.save()
      ```
    </CodeGroup>
  </Accordion>
</AccordionGroup>

<AccordionGroup>
  <Accordion title="Checklist">
    **Example 1:**

    Imports a Checklist options (`Many types of fruit?`) to a single image (`apple_003.jpg`). The selected items from the list are `apple` and `kiwi`.

    **Example 2:**

    Imports a Checklist options (`Many types of fruit?`) across a range of sequential frames: 193 to 197) to a video (`Blueberries_video.mp4`). The selected items from the list are `apple` and `kiwi`.

    <CodeGroup>
      ```python Checklist Template theme={"dark"}
      #Import dependencies
      from __future__ import annotations
      from pathlib import Path
      from encord import EncordUserClient, Project
      from encord.objects import (
          Classification,
      )
      from collections import defaultdict
      from copy import deepcopy
      from dataclasses import dataclass, field
      from datetime import datetime
      from typing import (
          TYPE_CHECKING,
          Any,
          Dict,
          Iterable,
          List,
          Optional,
          Sequence,
          Set,
          Tuple,
          Union,
      )
      from dateutil.parser import parse
      from encord.constants.enums import DataType
      from encord.exceptions import LabelRowError
      from encord.objects import ChecklistAttribute, RadioAttribute, TextAttribute
      from encord.objects.answers import (
          Answer,
          _get_static_answer_map,
          get_default_answer_from_attribute,
      )

      from encord.objects.frames import (
          Frames,
          Ranges,
      )
      from encord.objects.internal_helpers import (
          _infer_attribute_from_answer,
          _search_child_attributes,
      )
      from encord.objects.ontology_object import Object
      from encord.objects.options import Option
      from encord.objects.utils import check_email, short_uuid_str

      if TYPE_CHECKING:
          from encord.objects.ontology_labels_impl import LabelRowV2


      SSH_PATH = "/Users/chris-encord/sdk-ssh-private-key.txt"
      PROJECT_ID = "7d4ead9c-4087-4832-a301-eb2545e7d43b"

      # Create user client using access key
      user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
          Path(SSH_PATH).read_text()
      )

      # Get project for which predictions are to be added.
      project: Project = user_client.get_project(PROJECT_ID)


      # Creating one polyline- START
      label_row = project.list_label_rows_v2(
          data_title_eq="Blueberries_video.mp4"
      )[0]

      label_row.initialise_labels()


      # Assume that the following radio classification exists in the ontology.

      checklist_ontology_classification: Classification = project.ontology_structure.get_child_by_title(
          title="Many types of fruit?",
          type_=Classification,
      )

      apple_option = checklist_ontology_classification.get_child_by_title(
          title="Apple", type_=Option
      )

      kiwi_option = checklist_ontology_classification.get_child_by_title(
          title="Kiwi", type_=Option
      )
      checklist_classification_instance = (
          checklist_ontology_classification.create_instance()
      )

      checklist_classification_instance.set_answer(
          [apple_option, kiwi_option]
      )
      checklist_classification_instance.set_for_frames(
          # Add the classification to the image
          frames=177,
          # There are multiple additional fields that can be set optionally:
          manual_annotation=True,
          confidence=1.0,
      )

      label_row.add_classification_instance(checklist_classification_instance)


      label_row.save()

      ```

      ```python Example 1 theme={"dark"}
      #Import dependencies
      from __future__ import annotations
      from pathlib import Path
      from encord import EncordUserClient, Project
      from encord.objects import (
          Classification,
      )
      from collections import defaultdict
      from copy import deepcopy
      from dataclasses import dataclass, field
      from datetime import datetime
      from typing import (
          TYPE_CHECKING,
          Any,
          Dict,
          Iterable,
          List,
          Optional,
          Sequence,
          Set,
          Tuple,
          Union,
      )
      from dateutil.parser import parse
      from encord.constants.enums import DataType
      from encord.exceptions import LabelRowError
      from encord.objects import ChecklistAttribute, RadioAttribute, TextAttribute
      from encord.objects.answers import (
          Answer,
          _get_static_answer_map,
          get_default_answer_from_attribute,
      )

      from encord.objects.frames import (
          Frames,
          Ranges,
      )
      from encord.objects.internal_helpers import (
          _infer_attribute_from_answer,
          _search_child_attributes,
      )
      from encord.objects.ontology_object import Object
      from encord.objects.options import Option
      from encord.objects.utils import check_email, short_uuid_str

      if TYPE_CHECKING:
          from encord.objects.ontology_labels_impl import LabelRowV2


      SSH_PATH = "/Users/chris-encord/sdk-ssh-private-key.txt"
      PROJECT_ID = "7d4ead9c-4087-4832-a301-eb2545e7d43b"

      # Create user client using access key
      user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
          Path(SSH_PATH).read_text()
      )

      # Get project for which predictions are to be added.
      project: Project = user_client.get_project(PROJECT_ID)


      # Creating Checklist options- START
      # Specify the data unit to add classification
      label_row = project.list_label_rows_v2(
          data_title_eq="apple_003.jpg"
      )[0]

      label_row.initialise_labels()


      # Assume that the following Checklist options exists in the ontology.

      checklist_ontology_classification: Classification = project.ontology_structure.get_child_by_title(
          title="Many types of fruit?",
          type_=Classification,
      )

      apple_option = checklist_ontology_classification.get_child_by_title(
          title="Apple", type_=Option
      )

      kiwi_option = checklist_ontology_classification.get_child_by_title(
          title="Kiwi", type_=Option
      )
      checklist_classification_instance = (
          checklist_ontology_classification.create_instance()
      )

      checklist_classification_instance.set_answer(
          [apple_option, kiwi_option]
      )
      checklist_classification_instance.set_for_frames(
          # Add the classification to the image
          frames=0,
          # There are multiple additional fields that can be set optionally:
          manual_annotation=True,
      )

      label_row.add_classification_instance(checklist_classification_instance)


      label_row.save()

      ```

      ```python Example 2 theme={"dark"}
      #Import dependencies
      from __future__ import annotations
      from pathlib import Path
      from encord import EncordUserClient, Project
      from encord.objects import (
          Classification,
      )
      from collections import defaultdict
      from copy import deepcopy
      from dataclasses import dataclass, field
      from datetime import datetime
      from typing import (
          TYPE_CHECKING,
          Any,
          Dict,
          Iterable,
          List,
          Optional,
          Sequence,
          Set,
          Tuple,
          Union,
      )
      from dateutil.parser import parse
      from encord.constants.enums import DataType
      from encord.exceptions import LabelRowError
      from encord.objects import ChecklistAttribute, RadioAttribute, TextAttribute
      from encord.objects.answers import (
          Answer,
          _get_static_answer_map,
          get_default_answer_from_attribute,
      )

      from encord.objects.frames import (
          Frames,
          Range,
          Ranges,
      )
      from encord.objects.internal_helpers import (
          _infer_attribute_from_answer,
          _search_child_attributes,
      )
      from encord.objects.ontology_object import Object
      from encord.objects.options import Option
      from encord.objects.utils import check_email, short_uuid_str

      if TYPE_CHECKING:
          from encord.objects.ontology_labels_impl import LabelRowV2


      SSH_PATH = "/Users/chris-encord/sdk-ssh-private-key.txt"
      PROJECT_ID = "7d4ead9c-4087-4832-a301-eb2545e7d43b"

      # Create user client using access key
      user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
          Path(SSH_PATH).read_text()
      )

      # Get project for which classification are to be added.
      project: Project = user_client.get_project(PROJECT_ID)


      # Creating Checklist options- START
      # Specify the data unit to add classification
      label_row = project.list_label_rows_v2(
          data_title_eq="Blueberries_video.mp4"
      )[0]

      label_row.initialise_labels()


      # Assume that the following Checklist options exists in the ontology.

      checklist_ontology_classification: Classification = project.ontology_structure.get_child_by_title(
          title="Many types of fruit?",
          type_=Classification,
      )

      apple_option = checklist_ontology_classification.get_child_by_title(
          title="Apple", type_=Option
      )

      kiwi_option = checklist_ontology_classification.get_child_by_title(
          title="Kiwi", type_=Option
      )

      checklist_classification_instance = (
          checklist_ontology_classification.create_instance()
      )

      checklist_classification_instance.set_answer(
          [apple_option, kiwi_option]
      )

      checklist_classification_instance.set_for_frames(
          frames=Range(start=193, end=197),
          # There are multiple additional fields that can be set optionally:
          manual_annotation=True,
      )

      label_row.add_classification_instance(checklist_classification_instance)


      label_row.save()
      ```
    </CodeGroup>
  </Accordion>
</AccordionGroup>

***

## Attributes

The following scripts assume that an object label called `Whale` has already been created. Each script retrieves the object instance and searches for the corresponding attribute within the Project's Ontology. For radio buttons and checklists, the scripts also identify the relevant attribute options.

* Replace `<private_key_path>` with the key to your private key for authentication.
* Replace `<project_hash>` with the hash of your Project.
* Replace `Whale` with the name of your object.
* Replace the attributes and attribute answers to suit your needs.

<CodeGroup>
  ```python Text theme={"dark"}
  # Import dependencies
  from typing import List

  from encord import EncordUserClient
  from encord.objects import LabelRowV2, OntologyStructure, Object, OntologyStructure

  # Instantiate Encord client by replacing <private_key_path> with the path to your private key
  user_client = EncordUserClient.create_with_ssh_private_key(
      ssh_private_key_path="<private_key_path>"
  )

  # Specify the Project. Replace <project_hash> with the hash of your Project
  project = user_client.get_project("<project_hash>")

  # For simplicity, get only the first label row
  first_label_row: List[LabelRowV2] = project.list_label_rows_v2()[0]

  # Download the existing labels 
  first_label_row.initialise_labels()

  # Get the Ontology structure
  ontology_structure: OntologyStructure = first_label_row.ontology_structure

  #Assume that the following Object exists in the Ontology.
  object_label = ontology_structure.get_child_by_title(
      title="Whale",
      type_=Object
  )

  # Create object instance. We assume only 1 label
  object_instance = first_label_row.get_object_instances()[0]

  # Find the attribute name
  attribute = object_label.get_child_by_title("Description")

  # Set the answer for the attribute
  object_instance.set_answer(attribute=attribute, answer="This is a picture of a whale")

  # Save labels
  first_label_row.save()
  ```

  ```python Radio Button theme={"dark"}
  # Import dependencies
  from typing import List

  from encord import EncordUserClient
  from encord.objects import LabelRowV2, Option, Object, OntologyStructure

  # Instantiate Encord client by replacing <private_key_path> with the path to your private key
  user_client = EncordUserClient.create_with_ssh_private_key(
      ssh_private_key_path="<private_key_path>"
  )

  # Specify the Project. Replace <project_hash> with the hash of your Project
  project = user_client.get_project("<project_hash>")

  # For simplicity, get only the first label row
  first_label_row: List[LabelRowV2] = project.list_label_rows_v2()[0]

  # Download the existing labels 
  first_label_row.initialise_labels()

  # Get the ontology structure
  ontology_structure: OntologyStructure = first_label_row.ontology_structure

  # Find Object label
  object_label = ontology_structure.get_child_by_title(
      title="Whale",
      type_=Object
  )

  # Create object instance. We assume only 1 label
  object_instance = first_label_row.get_object_instances()[0]

  # Find the attribute
  object_attribute = object_label.get_child_by_title("Colour")

  # Find the attribute option you want to set
  attribute_option = object_attribute.get_child_by_title(
      title="Purple",
      type_=Option
  )

  # Set the attribute option
  object_instance.set_answer(attribute_option)

  # Save labels
  first_label_row.save()
  ```

  ```python Checklist theme={"dark"}
  # Import dependencies
  from typing import List

  from encord import EncordUserClient
  from encord.objects import LabelRowV2, Option, Object, OntologyStructure

  # Instantiate Encord client by replacing <private_key_path> with the path to your private key
  user_client = EncordUserClient.create_with_ssh_private_key(
      ssh_private_key_path="<private_key_path>"
  )

  # Specify the Project. Replace <project_hash> with the hash of your Project
  project = user_client.get_project("<project_hash>")

  # For simplicity, get only the first label row
  first_label_row: List[LabelRowV2] = project.list_label_rows_v2()[0]

  # Download the existing labels 
  first_label_row.initialise_labels()

  # Get the Ontology structure
  ontology_structure: OntologyStructure = first_label_row.ontology_structure

  # Find Object label
  object_label = ontology_structure.get_child_by_title(
      title="Whale",
      type_=Object
  )

  # Create object instance. We assume only 1 label
  object_instance = first_label_row.get_object_instances()[0]

  # Find the attribute
  object_attribute = object_label.get_child_by_title("Characteristics")

  # Find the attribute option you want to set
  mammal_option = object_attribute.get_child_by_title(
      title="Mammal",
      type_=Option
  )

  # Find the attribute option you want to set
  big_option = object_attribute.get_child_by_title(
      title="Big",
      type_=Option
  )

  # Set the attribute options
  object_instance.set_answer([mammal_option, big_option])

  # Save labels
  first_label_row.save()
  ```
</CodeGroup>

### Nested Attributes

Radio button attributes can be nested. The following script assumes that an object label called `Whale` has already been created.

```python Nested Radio Attributes theme={"dark"}
# Import dependencies
from typing import List

from encord import EncordUserClient
from encord.objects import LabelRowV2, Option, Object, OntologyStructure

# Instantiate Encord client by replacing <private_key_path> with the path to your private key
user_client = EncordUserClient.create_with_ssh_private_key(
    ssh_private_key_path="<private_key_path>"
)

# Specify the Project. Replace <project_hash> with the hash of your Project
project = user_client.get_project("<project_hash>")

# For simplicity, get only the first label row
first_label_row: List[LabelRowV2] = project.list_label_rows_v2()[0]

# Download the existing labels 
first_label_row.initialise_labels()

# Get the ontology structure
ontology_structure: OntologyStructure = first_label_row.ontology_structure

# Find Object label
object_label = ontology_structure.get_child_by_title(
    title="Whale",
    type_=Object
)

# Create object instance. We assume only 1 label
object_instance = first_label_row.get_object_instances()[0]

# Find the attribute
object_attribute = object_label.get_child_by_title("Colour")

# Find the attribute option you want to set
attribute_option = object_attribute.get_child_by_title(
    title="Blue",
    type_=Option
)

# Set the attribute option
object_instance.set_answer(attribute_option)

# Assume that the following Radio button options exists in the Ontology.
nested_radio_ontology_attribute: Classification = (
    ontology_structure.get_child_by_title(
        title="Any Other Colors?", type_=RadioAttribute
    )
)

# Assume the following radio button nested attribute exists in the Ontology
nested_radio_attribute_option = object_label.get_child_by_title(
    title="Pink",
    type_=Option
)

# Save labels
first_label_row.save()
```

***

### Relation Attributes

Relation attributes use text attributes as pointers to show a relationship between labels. When an attribute is marked as *Relation* the string `#relation` is appended to the attribute name.

You can specify relationships between any object labels in a data unit, if a Relation attribute is added to one object label type with Relation.

<Tip>Learn more about relation attributes in Encord [here](/platform-documentation/Annotate/annotate-ontologies/annotate-ontologies#relation-attributes).</Tip>

The following example uses bounding box and polygon object labels with a Text-Relation attribute and a Text attribute. The Text attribute can be used to provide more context for the relationship between object labels.

```python Relation Attributes expandable theme={"dark"}
from typing import List

from encord import EncordUserClient
from encord.objects import LabelRowV2, Object, OntologyStructure, ObjectInstance, TextAttribute
from encord.objects.coordinates import BoundingBoxCoordinates, PolygonCoordinates, PointCoordinate


# User input
SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"  # Replace with the file path to your access key
PROJECT_ID = "00000000-0000-0000-0000-000000000000"  # Replace with the Project ID

# Ontology titles. Replace with your ontology titles
BB_OBJECT_TITLE = "Bounding Box"
PG_OBJECT_TITLE = "Polygon"
REL_ATTR_TITLE = "Relationship #relation"
SPECIFY_ATTR_TITLE = "Specify relationship"


# --- Connect to Encord ---
user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
    ssh_private_key_path=SSH_PATH,
    # For US platform users use "https://api.us.encord.com"
    domain="https://api.encord.com",
)

project = user_client.get_project(PROJECT_ID)


# Import labels to data units
data_unit_specs = {
    # -------- Image --------
    "cherries-015.jpg": {
        0: {
            "bb": BoundingBoxCoordinates(height=0.30, width=0.30, top_left_x=0.05, top_left_y=0.05),
            "pg": PolygonCoordinates(
                polygons=[
                    [
                        [
                            PointCoordinate(x=0.40, y=0.40),
                            PointCoordinate(x=0.60, y=0.40),
                            PointCoordinate(x=0.50, y=0.60),
                        ]
                    ]
                ]
            ),
            "bb_specify_text": "BB references the Polygon",
            "pg_specify_text": "Polygon is referenced by the BB",
        }
    },

    # -------- Video 1 --------
    "cherries-vid-002.mp4": {
        12: {
            "bb": BoundingBoxCoordinates(height=0.25, width=0.25, top_left_x=0.10, top_left_y=0.10),
            "pg": PolygonCoordinates(
                polygons=[
                    [
                        [
                            PointCoordinate(x=0.55, y=0.55),
                            PointCoordinate(x=0.75, y=0.55),
                            PointCoordinate(x=0.65, y=0.75),
                        ]
                    ]
                ]
            ),
            "bb_specify_text": "BB references PG (video-001)",
            "pg_specify_text": "PG references BB (video-001)",
        },
        15: {
            "bb": BoundingBoxCoordinates(height=0.27, width=0.27, top_left_x=0.12, top_left_y=0.12),
            "pg": PolygonCoordinates(
                polygons=[
                    [
                        [
                            PointCoordinate(x=0.57, y=0.57),
                            PointCoordinate(x=0.77, y=0.57),
                            PointCoordinate(x=0.67, y=0.77),
                        ]
                    ]
                ]
            ),
        },
    },

    # -------- Video 2 --------
    "blueberry-02.mp4": {
        101: {
            "bb": BoundingBoxCoordinates(height=0.20, width=0.20, top_left_x=0.00, top_left_y=0.00),
            "pg": PolygonCoordinates(
                polygons=[
                    [
                        [
                            PointCoordinate(x=0.30, y=0.30),
                            PointCoordinate(x=0.50, y=0.30),
                            PointCoordinate(x=0.40, y=0.50),
                        ]
                    ]
                ]
            ),
            "bb_specify_text": "BB references PG (video-002)",
            "pg_specify_text": "PG references BB (video-002)",
        }
    },
}


# Process each data unit
for data_title, frame_map in data_unit_specs.items():
    print(f"\nProcessing {data_title}")

    # Get label row for this data unit
    label_rows: List[LabelRowV2] = project.list_label_rows_v2(data_title_eq=data_title)
    if not label_rows:
        print(f"Skipping {data_title}: no label row found")
        continue

    label_row: LabelRowV2 = label_rows[0]

    # Initialise labels
    label_row.initialise_labels()

    # Get ontology FROM label row
    ontology_structure: OntologyStructure = label_row.ontology_structure
    assert ontology_structure is not None, "Ontology not available after initialise_labels()"

    # Find ontology objects
    bb_object_label: Object = ontology_structure.get_child_by_title(title=BB_OBJECT_TITLE, type_=Object)
    pg_object_label: Object = ontology_structure.get_child_by_title(title=PG_OBJECT_TITLE, type_=Object)

    assert bb_object_label is not None, f"Object {BB_OBJECT_TITLE!r} not found in ontology."
    assert pg_object_label is not None, f"Object {PG_OBJECT_TITLE!r} not found in ontology."

    # Find attributes ON EACH object
    bb_relation_attr: TextAttribute = bb_object_label.get_child_by_title(type_=TextAttribute, title=REL_ATTR_TITLE)
    bb_specify_attr: TextAttribute = bb_object_label.get_child_by_title(type_=TextAttribute, title=SPECIFY_ATTR_TITLE)

    pg_relation_attr: TextAttribute = pg_object_label.get_child_by_title(type_=TextAttribute, title=REL_ATTR_TITLE)
    pg_specify_attr: TextAttribute = pg_object_label.get_child_by_title(type_=TextAttribute, title=SPECIFY_ATTR_TITLE)

    assert bb_relation_attr is not None, f"{REL_ATTR_TITLE!r} not found on {BB_OBJECT_TITLE!r}"
    assert bb_specify_attr is not None, f"{SPECIFY_ATTR_TITLE!r} not found on {BB_OBJECT_TITLE!r}"
    assert pg_relation_attr is not None, f"{REL_ATTR_TITLE!r} not found on {PG_OBJECT_TITLE!r}"
    assert pg_specify_attr is not None, f"{SPECIFY_ATTR_TITLE!r} not found on {PG_OBJECT_TITLE!r}"

    # Create labels
    bb_instance: ObjectInstance = bb_object_label.create_instance()
    pg_instance: ObjectInstance = pg_object_label.create_instance()

    bb_specify_text_to_set = None
    pg_specify_text_to_set = None

    # Assign coordinates per frame
    for frame_number, coords in frame_map.items():
        bb_instance.set_for_frames(coordinates=coords["bb"], frames=frame_number)
        pg_instance.set_for_frames(coordinates=coords["pg"], frames=frame_number)

        # set specify text once
        if bb_specify_text_to_set is None:
            bb_specify_text_to_set = coords.get("bb_specify_text")
        if pg_specify_text_to_set is None:
            pg_specify_text_to_set = coords.get("pg_specify_text")

    # Add instances to the label row
    label_row.add_object_instance(pg_instance)
    label_row.add_object_instance(bb_instance)

    # Relations
    bb_instance.set_answer(attribute=bb_relation_attr, answer=pg_instance.object_hash)
    pg_instance.set_answer(attribute=pg_relation_attr, answer=bb_instance.object_hash)

    # Human-readable relationship text
    if isinstance(bb_specify_text_to_set, str) and bb_specify_text_to_set:
        bb_instance.set_answer(attribute=bb_specify_attr, answer=bb_specify_text_to_set)

    if isinstance(pg_specify_text_to_set, str) and pg_specify_text_to_set:
        pg_instance.set_answer(attribute=pg_specify_attr, answer=pg_specify_text_to_set)

    # Save labels
    label_row.save()
    print(f"Saved labels for {data_title}")

print("\nDone: Bounding Box ↔ Polygon relations added for image + video data units.")

```

### Dynamic Attributes

Dynamic attributes are attributes for object instances where the answer can change in each frame. You can read more about them [here](/platform-documentation/Annotate/annotate-label-editor/annotate-videos#dynamic-attributes).

The following example adds bounding boxes for the label `Person` to three frames. It then sets the dynamic attribute `Position` to `Walking` and `Standing`. Wherever you can set frames, you can either set a single integer, a Range, or a list of Ranges.

```python theme={"dark"}
# Import dependencies
from typing import List

from encord import EncordUserClient
from encord.objects import LabelRowV2, Object, ObjectInstance, OntologyStructure
from encord.objects.coordinates import PolygonCoordinates, PointCoordinate

# Instantiate Encord client by replacing <private_key_path> with the path to your private key
user_client = EncordUserClient.create_with_ssh_private_key(
    ssh_private_key_path="<private_key_path>"
)

# Specify the project. Replace <project_hash> with the hash of your Project
project = user_client.get_project("<project_hash>")

# For simplicity, get only the first label row
first_label_row: LabelRowV2 = project.list_label_rows_v2()[0]

# Download the existing labels
first_label_row.initialise_labels()

# Find the object in the Ontology
person_ontology_object: Object = ontology_structure.get_child_by_title(
    "Person", type_=Object
)

# Find the dynamic attribute in the Ontology
position_attribute = person_ontology_object.get_child_by_title(
    title="Position",  # The options here are "Standing" or "Walking"
    type_=RadioAttribute,
)

# Coordinates for bounding boxes on frames 3, 4, and 5
coordinates_per_frame = {
    3: BoundingBoxCoordinates(
        height=0.5,
        width=0.5,
        top_left_x=0.2,
        top_left_y=0.2,
    ),
    4: BoundingBoxCoordinates(
        height=0.5,
        width=0.5,
        top_left_x=0.3,
        top_left_y=0.3,
    ),
    5: BoundingBoxCoordinates(
        height=0.5,
        width=0.5,
        top_left_x=0.4,
        top_left_y=0.4,
    ),
}

# Add the bounding box labels to the object instance for each frame
for frame_number, coordinates in coordinates_per_frame.items():
    box_object_instance.set_for_frames(
        coordinates=coordinates, frames=frame_number
    )

# Link the object instance to the label row
first_label_row.add_object_instance(box_object_instance)

# Assume the person is standing in frame 1
person_object_instance.set_answer(
    answer=position_attribute.get_child_by_title("Standing", type_=Option),
    frames=0,
)

# Assume the person is walking in frames 2 and 3
person_object_instance.set_answer(
    answer=position_attribute.get_child_by_title("Walking", type_=Option),
    frames=Range(start=1, end=3),
)

# Save labels
first_label_row.save()
```

## Import Labels in Bulk

When importing a large number of labels, here are some tips to improve your label import performance:

* A data unit is one image, one image group, one image sequence, one video, or one DICOM series. One data unit is equivalent to one label row. You only need to call the [initialise\_labels](/sdk-documentation/sdk-references/objects.ontology_labels_impl#labelrowv2-objects#initialise-labels) function and save the label row ONCE per data unit. It does not matter how many labels are added to the data unit between the `initialise_labels` function and saving the label row.

* Use the [bundle](/sdk-documentation/sdk-references/http.bundle#bundle) function to significantly improve the import performance when you do any of the following:
  * Import labels on a large number of individual images (NOT image groups, image sequences, videos, or DICOM sets).
  * Import labels on a large number of data units at once.

<Warning>
  In the following code, ensure you replace:

  * `<private_key_path>` with the full path to your private key.
  * `<project-id>` with the unique ID of your Project.
  * `#Perform label row operation before in this loop` with the label row operations you want to perform.
  * Optionally, change the value of `BUNDLE_SIZE` to suit your needs. We strongly recommend NOT bundling more than 1000 operations at once, because bundling more than 1000 operations can reduce performance instead of improving performance.
</Warning>

<CodeGroup>
  ```python Bundle template for label import theme={"dark"}

  # Import dependencies
  from pathlib import Path

  from encord import EncordUserClient, Project
  from encord.objects import (
      Object,
      ObjectInstance,
      OntologyStructure,
  )
  from encord.objects.coordinates import BoundingBoxCoordinates

  SSH_PATH = "<private-key-path>"
  PROJECT_HASH = "<project-unique-id>"

  # Authenticate
  user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(ssh_private_key_path=SSH_PATH)

  # Gets Project to export labels
  project: Project = user_client.get_project(PROJECT_HASH)

  label_rows = project.list_label_rows_v2()
  BUNDLE_SIZE = 100

  # Initialize label rows using bundles
  with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
      for label_row in label_rows:
          label_row.initialise_labels(bundle=bundle)

  for label_row in label_rows:

      # Write any label row operation here. For example import, or export label rows. 


  # Saving changes to label rows using bundles
  with project.create_bundle(bundle_size=BUNDLE_SIZE) as bundle:
      for label_row in label_rows:
          label_row.save(bundle=bundle) 
  ```
</CodeGroup>
