> ## 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.

# Data Groups & Label Spaces

Working with Data Group labels requires the use of Label Spaces. Each Data Group's Label Row contains multiple Label Spaces, with each Space corresponding to a specific Data Group item. [Multi-layer Data Groups](/sdk-documentation/index-sdk/sdk-data-groups#multi-layer-data-groups) also contain a root Label Space that contains labels pertaining to the Data Group as a whole.

## Get Label Spaces

The following script gets all Label Spaces in Label Row and prints their IDs.

```python Get All Label Space IDs theme={"dark"}
from encord import EncordUserClient, Project

# User input
SSH_PATH = "<private_key_path>"  # Replace with the file path to your SSH private key
PROJECT_ID = "<project_id>"  # Replace with the unique Project ID
DATA_TITLE = "<data_unit_title>" # Replace with the title of the data unit 

# --- 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",
)

# Get Project
project: Project = user_client.get_project(PROJECT_ID)

# Get all Label Rows for the data unit
rows = project.list_label_rows_v2(data_title_eq=DATA_TITLE)
# Assume we want the first Label Row
lr = rows[0]
lr.initialise_labels()

# Get all Label Spaces for the Label Row
label_spaces = lr.get_spaces()

# Print IDs
for space in label_spaces:
    print(
        f"spaceId: {space.space_id}, "
        f"file_name: {space.metadata.file_name}, "
        f"layout_key: {space.metadata.layout_key}"
    )
```

## Get & Update Labels

Use the following scripts to get all annotations in a Label Space. The script shows how annotations can be updated by changing the `last_edited_by` and annotation coordinates for each annotation in the Label Space.

Ensure that you replace:

* All variables in the `User input` section at the top of the script.
* The names of objects in your Ontology.
* The type and position of the label(s).

<Tip>
  Label Spaces can be specified using:

  * A storage item's unique ID: `label_space = lr.get_space(id="7E3KERd9arYTiPicaijP6c1LfI73", type_="image")`
  * Its [Data Group](/sdk-documentation/index-sdk/sdk-data-groups) layout key: `label_space = lr.get_space(layout_key="2", type_="image")`.

  Using `layout_key`s lets you reuse the same code across multiple label rows and Data Groups (for example, "left-video" and "right-video"), without needing to look up the underlying storage item ID each time.
</Tip>

<CodeGroup>
  ```python Image theme={"dark"}
  from encord import EncordUserClient, Project
  from encord.objects.coordinates import BoundingBoxCoordinates

  # User input
  SSH_PATH = "<private_key_path>"  # Replace with the file path to your SSH private key
  PROJECT_ID = "<project_id>"  # Replace with the unique Project ID
  DATA_TITLE = "<data_unit_title>" # Replace with the title of the data unit 
  LABEL_SPACE = "<label_space_id>" # Replace with the unique ID of the label space

  # --- 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: Project = user_client.get_project(PROJECT_ID)

  # Get all Label Rows for the data unit
  rows = project.list_label_rows_v2(data_title_eq=DATA_TITLE)
  # Assume we want the first Label Row
  lr = rows[0]
  lr.initialise_labels()

  # Replace ID with the unique ID of the Label Space 
  label_space = lr.get_space(id=LABEL_SPACE, type_="image")

  # Get object instances
  object_instances = label_space.get_object_instances()

  # Get annotations
  for annotation in label_space.get_annotations(type_="object"):
  	print(annotation.coordinates)
  	print(annotation.last_edited_by)
  	print(annotation.last_edited_at)
  	print(annotation.confidence)
  	print(annotation.object_hash)
  	print(annotation.space)

  	# Update the annotations
  	annotation.last_edited_by = "user@encord.com"
  	annotation.coordinates = BoundingBoxCoordinates(
          top_left_x=0.6,
          top_left_y=0.4,
          width=0.3,
          height=0.1,
      )

  # Save Label Row
  lr.save()
  ```

  ```python Image Sequence theme={"dark"}
  from encord import EncordUserClient, Project
  from encord.objects.coordinates import BoundingBoxCoordinates

  # User input
  SSH_PATH = "<private_key_path>"  # Replace with the file path to your SSH private key
  PROJECT_ID = "<project_id>"  # Replace with the unique Project ID
  DATA_TITLE = "<data_unit_title>" # Replace with the title of the data unit 
  LABEL_SPACE = "<label_space_id>" # Replace with the unique ID of the label space

  # --- 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: Project = user_client.get_project(PROJECT_ID)

  # Get all Label Rows for the data unit
  rows = project.list_label_rows_v2(data_title_eq=DATA_TITLE)
  # Assume we want the first Label Row
  lr = rows[0]
  lr.initialise_labels()

  # Replace ID with the unique ID of the Label Space 
  label_space = lr.get_space(id=LABEL_SPACE, type_="image_sequence")

  # Get object instances
  object_instances = label_space.get_object_instances()

  # Get annotations
  for annotation in label_space.get_annotations(type_="object"):
  	print(annotation.coordinates)
  	print(annotation.last_edited_by)
  	print(annotation.last_edited_at)
  	print(annotation.confidence)
  	print(annotation.frame)
  	print(annotation.object_hash)
  	print(annotation.space)

  	# Update the annotations
  	annotation.last_edited_by = "user@encord.com"
  	annotation.coordinates = BoundingBoxCoordinates(
          top_left_x=0.6,
          top_left_y=0.4,
          width=0.3,
          height=0.1,
      )
  # Save Label Row
  lr.save()
  ```

  ```python Video theme={"dark"}
  from encord import EncordUserClient, Project
  from encord.objects.coordinates import BoundingBoxCoordinates

  # User input
  SSH_PATH = "<private_key_path>"  # Replace with the file path to your SSH private key
  PROJECT_ID = "<project_id>"  # Replace with the unique Project ID
  DATA_TITLE = "<data_unit_title>" # Replace with the title of the data unit 
  LABEL_SPACE = "<label_space_id>" # Replace with the unique ID of the label space

  # --- 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: Project = user_client.get_project(PROJECT_ID)

  # Get all Label Rows for the data unit
  rows = project.list_label_rows_v2(data_title_eq=DATA_TITLE)
  # Assume we want the first Label Row
  lr = rows[0]
  lr.initialise_labels()

  # Replace ID with the unique ID of the Label Space 
  label_space = lr.get_space(id=LABEL_SPACE, type_="video")

  # Get object instances
  object_instances = label_space.get_object_instances()

  # Get annotations
  for annotation in label_space.get_annotations(type_="object"):
  	print(annotation.coordinates)
  	print(annotation.last_edited_by)
  	print(annotation.last_edited_at)
  	print(annotation.confidence)
  	print(annotation.frame)
  	print(annotation.object_hash)
  	print(annotation.space)

  	# Update the annotations
  	annotation.last_edited_by = "user@encord.com"
  	annotation.coordinates = BoundingBoxCoordinates(
          top_left_x=0.6,
          top_left_y=0.4,
          width=0.3,
          height=0.1,
      )

  # Save Label Row
  lr.save()
  ```

  ```python Audio theme={"dark"}
  from encord import EncordUserClient, Project
  from encord.objects import Range

  # User input
  SSH_PATH = "<private_key_path>"  # Replace with the file path to your SSH private key
  PROJECT_ID = "<project_id>"  # Replace with the unique Project ID
  DATA_TITLE = "<data_unit_title>" # Replace with the title of the data unit 
  LABEL_SPACE = "<label_space_id>" # Replace with the unique ID of the label space

  # --- 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: Project = user_client.get_project(PROJECT_ID)

  # Get all Label Rows for the data unit
  rows = project.list_label_rows_v2(data_title_eq=DATA_TITLE)
  # Assume we want the first Label Row
  lr = rows[0]
  lr.initialise_labels()

  # Replace ID with the unique ID of the Label Space 
  label_space = lr.get_space(id=LABEL_SPACE, type_="audio")

  # Get object instances
  object_instances = label_space.get_object_instances()

  # Get annotations
  for annotation in label_space.get_annotations(type_="object"):
  	print(annotation.ranges)
  	print(annotation.last_edited_by)
  	print(annotation.last_edited_at)
  	print(annotation.object_hash)
  	print(annotation.space)

  	# Update the annotations
  	annotation.last_edited_by = "user@encord.com"
  	annotation.ranges = Range(start=0, end=100)

  # Save Label Row
  lr.save()
  ```

  ```python Text theme={"dark"}
  from encord import EncordUserClient, Project
  from encord.objects import Range

  # User input
  SSH_PATH = "<private_key_path>"  # Replace with the file path to your SSH private key
  PROJECT_ID = "<project_id>"  # Replace with the unique Project ID
  DATA_TITLE = "<data_unit_title>" # Replace with the title of the data unit 
  LABEL_SPACE = "<label_space_id>" # Replace with the unique ID of the label space

  # --- 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: Project = user_client.get_project(PROJECT_ID)

  # Get all Label Rows for the data unit
  rows = project.list_label_rows_v2(data_title_eq=DATA_TITLE)
  # Assume we want the first Label Row
  lr = rows[0]
  lr.initialise_labels()

  # Replace ID with the unique ID of the Label Space 
  label_space = lr.get_space(id=LABEL_SPACE, type_="text")

  # Get object instances
  object_instances = label_space.get_object_instances()

  # Get annotations
  for annotation in label_space.get_annotations(type_="object"):
  	print(annotation.last_edited_by)
  	print(annotation.last_edited_at)
  	print(annotation.object_hash)
  	print(annotation.space)

  	# Update the annotations
  	annotation.last_edited_by = "user@encord.com"
  	annotation.ranges = Range(start=0, end=100)

  # Save Label Row
  lr.save()
  ```

  ```python HTML theme={"dark"}
  from encord import EncordUserClient, Project
  from encord.objects import HtmlRange, HtmlNode

  # User input
  SSH_PATH = "<private_key_path>"  # Replace with the file path to your SSH private key
  PROJECT_ID = "<project_id>"  # Replace with the unique Project ID
  DATA_TITLE = "<data_unit_title>" # Replace with the title of the data unit 
  LABEL_SPACE = "<label_space_id>" # Replace with the unique ID of the label space

  # --- 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: Project = user_client.get_project(PROJECT_ID)

  # Get all Label Rows for the data unit
  rows = project.list_label_rows_v2(data_title_eq=DATA_TITLE)
  # Assume we want the first Label Row
  lr = rows[0]
  lr.initialise_labels()

  # Replace ID with the unique ID of the Label Space 
  label_space = lr.get_space(id=LABEL_SPACE, type_="html")

  # Get object instances
  object_instances = label_space.get_object_instances()

  # Get annotations
  for annotation in label_space.get_annotations(type_="object"):
  	print(annotation.last_edited_by)
  	print(annotation.last_edited_at)
  	print(annotation.object_hash)
  	print(annotation.space)

  	# Update the annotations
  	annotation.last_edited_by = "user@encord.com"
  	annotation.range = HtmlRange(start=HtmlNode(xpath="start", offset=0), end=HtmlNode(xpath="end", offset=1))

  # Save Label Row
  lr.save()
  ```

  ```python PDF theme={"dark"}
  from encord import EncordUserClient, Project
  from encord.objects.coordinates import BoundingBoxCoordinates

  # User input
  SSH_PATH = "<private_key_path>"  # Replace with the file path to your SSH private key
  PROJECT_ID = "<project_id>"  # Replace with the unique Project ID
  DATA_TITLE = "<data_unit_title>" # Replace with the title of the data unit 
  LABEL_SPACE = "<label_space_id>" # Replace with the unique ID of the label space

  # --- 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: Project = user_client.get_project(PROJECT_ID)

  # Get all Label Rows for the data unit
  rows = project.list_label_rows_v2(data_title_eq=DATA_TITLE)
  # Assume we want the first Label Row
  lr = rows[0]
  lr.initialise_labels()

  # Replace ID with the unique ID of the Label Space 
  label_space = lr.get_space(id=LABEL_SPACE, type_="pdf")

  # Get object instances
  object_instances = label_space.get_object_instances()

  # Get annotations
  for annotation in label_space.get_annotations(type_="object"):
  	print(annotation.coordinates)
  	print(annotation.last_edited_by)
  	print(annotation.last_edited_at)
  	print(annotation.confidence)
  	print(annotation.object_hash)
  	print(annotation.space)

  	# Update the annotations
  	annotation.last_edited_by = "user@encord.com"
  	annotation.coordinates = BoundingBoxCoordinates(
          top_left_x=0.6,
          top_left_y=0.4,
          width=0.3,
          height=0.1,
      )

  # Save Label Row
  lr.save()
  ```

  ```python DICOM / NIfTI theme={"dark"}
  from encord import EncordUserClient, Project
  from encord.objects.coordinates import BoundingBoxCoordinates

  # User input
  SSH_PATH = "<private_key_path>"  # Replace with the file path to your SSH private key
  PROJECT_ID = "<project_id>"  # Replace with the unique Project ID
  DATA_TITLE = "<data_unit_title>" # Replace with the title of the data unit 
  LABEL_SPACE = "<label_space_id>" # Replace with the unique ID of the label space

  # --- 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: Project = user_client.get_project(PROJECT_ID)

  # Get all Label Rows for the data unit
  rows = project.list_label_rows_v2(data_title_eq=DATA_TITLE)
  # Assume we want the first Label Row
  lr = rows[0]
  lr.initialise_labels()

  # Replace ID with the unique ID of the Label Space 
  label_space = lr.get_space(id=LABEL_SPACE, type_="medical")

  # Get object instances
  object_instances = label_space.get_object_instances()

  # Get annotations
  for annotation in label_space.get_annotations(type_="object"):
  	print(annotation.coordinates)
  	print(annotation.last_edited_by)
  	print(annotation.last_edited_at)
  	print(annotation.confidence)
  	print(annotation.frame)
  	print(annotation.object_hash)
  	print(annotation.space)

  	# Update the annotations
  	annotation.last_edited_by = "user@encord.com"
  	annotation.coordinates = BoundingBoxCoordinates(
          top_left_x=0.6,
          top_left_y=0.4,
          width=0.3,
          height=0.1,
      )

  # Save Label Row
  lr.save()
  ```
</CodeGroup>

## Add Labels

The following scripts add a single object with an attribute, and a classification to two different Label Spaces.

<Info>
  Attributes are set on the object instance itself, so the same attribute values apply across all Label Spaces the instance is added to.
</Info>

Ensure that you replace:

* All variables in the `User input` section at the top of the script.
* The names of objects in your Ontology.
* The type and position of the label(s).

<Tip>
  Use the `on_overlap="replace"` parameter in the `put_classification_instance` and `put_object_instance` methods if you want existing labels to be replaced by the new object.
</Tip>

<CodeGroup>
  ```python Image theme={"dark"}
  from encord import EncordUserClient, Project
  from encord.objects import Object, Classification, ClassificationInstance, ObjectInstance, LabelRowV2
  from encord.objects.coordinates import BoundingBoxCoordinates
  from encord.objects.options import Option

  # User input
  SSH_PATH = "<private_key_path>"  # Replace with the file path to your SSH private key
  PROJECT_ID = "<project_id>"  # Replace with the unique Project ID
  DATA_TITLE = "<data_unit_title>" # Replace with the title of the data unit 
  LABEL_SPACE = "<label_space_id>" # Replace with the unique ID of the label space

  # --- 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",
  )

  # Get Project
  project: Project = user_client.get_project(PROJECT_ID)

  # Get all Label Rows for the data unit
  rows = project.list_label_rows_v2(data_title_eq=DATA_TITLE)
  # Assume we want the first Label Row
  lr = rows[0]
  lr.initialise_labels()

  # Find bounding box object "Cherry" in the Ontology.
  ontology_structure = project.ontology_structure
  box_ontology_object: Object = ontology_structure.get_child_by_title(title="Cherry", type_=Object)

  # Find classification "Day or Night" in the Ontology
  classification: Classification = ontology_structure.get_child_by_title(title="Day or Night", type_=Classification)

  # Find classification answer "Day" in the Ontology
  classification_answer = classification.get_child_by_title(
      title="Day", type_=Option
  )

  # Get Label Spaces
  label_space_1 = lr.get_space(layout_key="Fruit_1", type_="image")
  label_space_2 = lr.get_space(layout_key="Fruit_2", type_="image")

  # Create bounding box instance
  bb_inst: ObjectInstance = box_ontology_object.create_instance()

  # Find the text attribute "Ripeness description" in the Ontology and set the answer
  attribute = box_ontology_object.get_child_by_title("Ripeness description")
  bb_inst.set_answer(attribute=attribute, answer="Fully ripe, deep red color with no visible blemishes")

  # Create classification instance
  classification_inst: ClassificationInstance = classification.create_instance()

  classification_inst.set_answer(
      answer=classification_answer
  )

  # Add the bounding box instance to both Label Spaces
  label_space_1.put_object_instance(
      object_instance=bb_inst,
      on_overlap="replace",
      coordinates=BoundingBoxCoordinates(
          top_left_x=0.6,
          top_left_y=0.4,
          width=0.3,
          height=0.2
      ),
      frames=[0, 1, 2]
      )

  label_space_2.put_object_instance(
      object_instance=bb_inst,
      on_overlap="replace",
      coordinates=BoundingBoxCoordinates(
          top_left_x=0.6,
          top_left_y=0.4,
          width=0.3,
          height=0.2
      ),
      frames=[0, 1, 2]
      )

  # Add the classification instance to both Label Spaces
  label_space_1.put_classification_instance(
      classification_instance=classification_inst,
      frames=[0, 1, 2]
  )

  label_space_2.put_classification_instance(
      classification_instance=classification_inst,
      frames=[0, 1, 2]
  )

  lr.save()
  print(f"Saved label row for {lr.data_title}")
  ```

  ```python Image Sequence theme={"dark"}
  from encord import EncordUserClient, Project
  from encord.objects import Object, Classification, ClassificationInstance, ObjectInstance, LabelRowV2
  from encord.objects.coordinates import BoundingBoxCoordinates
  from encord.objects.options import Option

  # User input
  SSH_PATH = "<private_key_path>"  # Replace with the file path to your SSH private key
  PROJECT_ID = "<project_id>"  # Replace with the unique Project ID
  DATA_TITLE = "<data_unit_title>" # Replace with the title of the data unit 
  LABEL_SPACE = "<label_space_id>" # Replace with the unique ID of the label space

  # --- 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",
  )

  # Get Project
  project: Project = user_client.get_project(PROJECT_ID)

  # Get all Label Rows for the data unit
  rows = project.list_label_rows_v2(data_title_eq=DATA_TITLE)
  # Assume we want the first Label Row
  lr = rows[0]
  lr.initialise_labels()

  # Find bounding box object "Person" in the Ontology.
  ontology_structure = project.ontology_structure
  box_ontology_object: Object = ontology_structure.get_child_by_title(title="Person", type_=Object)

  # Find classification "Day or Night" in the Ontology
  classification: Classification = ontology_structure.get_child_by_title(title="Day or Night", type_=Classification)

  # Find classification answer "Day" in the Ontology
  classification_answer = classification.get_child_by_title(
      title="Day", type_=Option
  )

  # Get Label Spaces
  label_space_1 = lr.get_space(layout_key="cctv_1", type_="image_sequence")
  label_space_2 = lr.get_space(layout_key="cctv_2", type_="image_sequence")

  # Create bounding box instance
  bb_inst: ObjectInstance = box_ontology_object.create_instance()

  # Find the text attribute "Visibility description" in the Ontology and set the answer
  attribute = box_ontology_object.get_child_by_title("Visibility description")
  bb_inst.set_answer(attribute=attribute, answer="Face fully visible. Body partially occluded.")

  # Create classification instance
  classification_inst: ClassificationInstance = classification.create_instance()

  classification_inst.set_answer(
      answer=classification_answer
  )

  # Add the bounding box instance to both Label Spaces 
  label_space_1.put_object_instance(
      object_instance=bb_inst,
      on_overlap="replace",
      coordinates=BoundingBoxCoordinates(
          top_left_x=0.6,
          top_left_y=0.4,
          width=0.3,
          height=0.2
      ),
      frames=[0, 1, 2]
      )

  label_space_2.put_object_instance(
      object_instance=bb_inst,
      on_overlap="replace",
      coordinates=BoundingBoxCoordinates(
          top_left_x=0.6,
          top_left_y=0.4,
          width=0.3,
          height=0.2
      ),
      frames=[0, 1, 2]
      )

  # Add the classification instance to both Label Spaces
  label_space_1.put_classification_instance(
      classification_instance=classification_inst,
      frames=[0, 1, 2]
  )

  label_space_2.put_classification_instance(
      classification_instance=classification_inst,
      frames=[0, 1, 2]
  )

  # Save Label Row
  lr.save()
  print(f"Saved label row for {lr.data_title}")
  ```

  ```python Video theme={"dark"}
  from encord import EncordUserClient, Project
  from encord.objects import Object, Classification, ClassificationInstance, ObjectInstance, LabelRowV2
  from encord.objects.coordinates import BoundingBoxCoordinates
  from encord.objects.options import Option

  # User input
  SSH_PATH = "<private_key_path>"  # Replace with the file path to your SSH private key
  PROJECT_ID = "<project_id>"  # Replace with the unique Project ID
  DATA_TITLE = "<data_unit_title>" # Replace with the title of the data unit 
  LABEL_SPACE = "<label_space_id>" # Replace with the unique ID of the label space

  # --- 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",
  )

  # Get Project
  project: Project = user_client.get_project(PROJECT_ID)

  # Get all Label Rows for the data unit
  rows = project.list_label_rows_v2(data_title_eq=DATA_TITLE)
  # Assume we want the first Label Row
  lr = rows[0]
  lr.initialise_labels()

  # Find bounding box object "Person" in the Ontology.
  ontology_structure = project.ontology_structure
  box_ontology_object: Object = ontology_structure.get_child_by_title(title="Person", type_=Object)

  # Find classification "Day or Night" in the Ontology
  classification: Classification = ontology_structure.get_child_by_title(title="Day or Night", type_=Classification)

  # Find classification answer "Day" in the Ontology
  classification_answer = classification.get_child_by_title(
      title="Day", type_=Option
  )

  # Get Label Spaces
  label_space_1 = lr.get_space(layout_key="cctv_1", type_="video")
  label_space_2 = lr.get_space(layout_key="cctv_2", type_="video")

  # Create bounding box instance
  bb_inst: ObjectInstance = box_ontology_object.create_instance()

  # Find the text attribute "Visibility description" in the Ontology object and set the answer
  attribute = box_ontology_object.get_child_by_title("Visibility description")
  bb_inst.set_answer(attribute=attribute, answer="Face fully visible. Body partially occluded.")

  # Create classification instance
  classification_inst: ClassificationInstance = classification.create_instance()

  classification_inst.set_answer(
      answer=classification_answer
  )

  # Add the bounding box instance to both Label Spaces
  label_space_1.put_object_instance(
      object_instance=bb_inst,
      on_overlap="replace",
      coordinates=BoundingBoxCoordinates(
          top_left_x=0.6,
          top_left_y=0.4,
          width=0.3,
          height=0.2
      ),
      frames=[0, 1, 2]
      )

  label_space_2.put_object_instance(
      object_instance=bb_inst,
      on_overlap="replace",
      coordinates=BoundingBoxCoordinates(
          top_left_x=0.6,
          top_left_y=0.4,
          width=0.3,
          height=0.2
      ),
      frames=[0, 1, 2]
      )

  # Add the classification instance to both Label Spaces
  label_space_1.put_classification_instance(
      classification_instance=classification_inst,
      frames=[0, 1, 2]
  )

  label_space_2.put_classification_instance(
      classification_instance=classification_inst,
      frames=[0, 1, 2]
  )

  # Save Label Row
  lr.save()
  print(f"Saved label row for {lr.data_title}")
  ```

  ```python Audio theme={"dark"}
  from encord import EncordUserClient, Project
  from encord.objects import Object, Classification, ClassificationInstance, ObjectInstance, LabelRowV2, Range
  from encord.objects.options import Option

  # User input
  SSH_PATH = "<private_key_path>"  # Replace with the file path to your SSH private key
  PROJECT_ID = "<project_id>"  # Replace with the unique Project ID
  DATA_TITLE = "<data_unit_title>" # Replace with the title of the data unit 
  LABEL_SPACE = "<label_space_id>" # Replace with the unique ID of the label space

  # --- 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",
  )

  # Get Project
  project: Project = user_client.get_project(PROJECT_ID)

  # Get all Label Rows for the data unit
  rows = project.list_label_rows_v2(data_title_eq=DATA_TITLE)
  # Assume we want the first Label Row
  lr = rows[0]
  lr.initialise_labels()

  # Find audio region object "Rick James" in the Ontology.
  ontology_structure = project.ontology_structure
  ontology_object: Object = ontology_structure.get_child_by_title(title="Rick James", type_=Object)

  # Find classification "Contains Lyrics?" in the Ontology
  classification: Classification = ontology_structure.get_child_by_title(title="Contains Lyrics?", type_=Classification)

  # Find classification answer "Yes" in the Ontology
  classification_answer = classification.get_child_by_title(
      title="Yes", type_=Option
  )

  # Get Label Spaces
  label_space = lr.get_space(layout_key="music_1", type_="audio")
  label_space = lr.get_space(layout_key="music_2", type_="audio")

  # Create audio region instance
  audio_inst: ObjectInstance = ontology_object.create_instance()

  # Find the text attribute "Description" in the Ontology object and set the answer
  attribute = ontology_object.get_child_by_title("Description")
  bb_inst.set_answer(attribute=attribute, answer="Very Funky")

  # Create classification instance
  classification_inst: ClassificationInstance = classification.create_instance()

  # Set classification answer
  classification_inst.set_answer(
      answer=classification_answer
      )

  # Add the audio region instance to both Label Spaces
  label_space_1.put_object_instance(
      object_instance=audio_inst,
      on_overlap="replace",
      ranges=Range(start=100, end=2000)
      )

  label_space_2.put_object_instance(
      object_instance=audio_inst,
      on_overlap="replace",
      ranges=Range(start=100, end=2000)
      )

  # Add the classification instance to both Label Spaces
  label_space_1.put_classification_instance(
      classification_instance=classification_inst
      )

  label_space_2.put_classification_instance(
  classification_instance=classification_inst
  )

  # Save Label Row
  lr.save()
  print(f"Saved label row for {lr.data_title}")
  ```

  ```python Text theme={"dark"}
  from encord import EncordUserClient, Project
  from encord.objects import Object, Classification, ClassificationInstance, ObjectInstance, LabelRowV2, Range
  from encord.objects.options import Option

  # User input
  SSH_PATH = "<private_key_path>"  # Replace with the file path to your SSH private key
  PROJECT_ID = "<project_id>"  # Replace with the unique Project ID
  DATA_TITLE = "<data_unit_title>" # Replace with the title of the data unit 
  LABEL_SPACE = "<label_space_id>" # Replace with the unique ID of the label space

  # --- 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",
  )

  # Get Project
  project: Project = user_client.get_project(PROJECT_ID)

  # Get all Label Rows for the data unit
  rows = project.list_label_rows_v2(data_title_eq=DATA_TITLE)
  # Assume we want the first Label Row
  lr = rows[0]
  lr.initialise_labels()

  # Find text region object "Quote" in the Ontology.
  ontology_structure = project.ontology_structure
  ontology_object: Object = ontology_structure.get_child_by_title(title="Quote", type_=Object)

  # Find classification "Easy to Read?" in the Ontology
  classification: Classification = ontology_structure.get_child_by_title(title="Easy to Read?", type_=Classification)

  # Find classification answer "Yes" in the Ontology
  classification_answer = classification.get_child_by_title(
      title="Yes", type_=Option
  )

  # Get Label Spaces
  label_space_1 = lr.get_space(layout_key="text_1", type_="text")
  label_space_2 = lr.get_space(layout_key="text_2", type_="text")

  # Create text region instance
  text_inst: ObjectInstance = ontology_object.create_instance()

  # Find the text attribute "Author" in the Ontology object and set the answer
  attribute = ontology_object.get_child_by_title("Author")
  bb_inst.set_answer(attribute=attribute, answer="Bertrand Russel")

  # Create classification instance
  classification_inst: ClassificationInstance = classification.create_instance()

  # Set classification answer
  classification_inst.set_answer(
      answer=classification_answer
  )

  # Add the text region instance to both Label Spaces
  label_space_1.put_object_instance(
      object_instance=text_inst,
      on_overlap="replace",
      ranges=Range(start=100, end=2000)
  )

  label_space_2.put_object_instance(
      object_instance=text_inst,
      on_overlap="replace",
      ranges=Range(start=100, end=2000)
  )

  # Add the classification instance to both Label Spaces
  label_space_1.put_classification_instance(
      classification_instance=classification_inst
  )

  label_space_2.put_classification_instance(
      classification_instance=classification_inst
  )

  # Save Label Row
  lr.save()
  print(f"Saved label row for {lr.data_title}")
  ```

  ```python HTML theme={"dark"}
  from encord import EncordUserClient, Project
  from encord.objects import Object, Classification, ClassificationInstance, ObjectInstance, LabelRowV2, HtmlRange, HtmlNode
  from encord.objects.options import Option

  # User input
  SSH_PATH = "<private_key_path>"  # Replace with the file path to your SSH private key
  PROJECT_ID = "<project_id>"  # Replace with the unique Project ID
  DATA_TITLE = "<data_unit_title>" # Replace with the title of the data unit 
  LABEL_SPACE = "<label_space_id>" # Replace with the unique ID of the label space

  # --- 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",
  )

  # Get Project
  project: Project = user_client.get_project(PROJECT_ID)

  # Get all Label Rows for the data unit
  rows = project.list_label_rows_v2(data_title_eq=DATA_TITLE)

  # Assume we want the first Label Row
  lr = rows[0]
  lr.initialise_labels()

  # Find text region object "Quote" in the Ontology.
  ontology_structure = project.ontology_structure
  ontology_object: Object = ontology_structure.get_child_by_title(title="Quote", type_=Object)

  # Find classification "Easy to Read?" in the Ontology
  classification: Classification = ontology_structure.get_child_by_title(title="Easy to Read?", type_=Classification)

  # Find classification answer "Yes" in the Ontology
  classification_answer = classification.get_child_by_title(
      title="Yes", type_=Option
  )

  # Get Label Spaces
  label_space_1 = lr.get_space(layout_key="website_1", type_="html")
  label_space_2 = lr.get_space(layout_key="website_2", type_="html")

  # Create text region instance
  text_inst: ObjectInstance = ontology_object.create_instance()

  # Find the text attribute "Author" in the Ontology object and set the answer
  attribute = ontology_object.get_child_by_title("Author")
  bb_inst.set_answer(attribute=attribute, answer="Bertrand Russel")

  # Create classification instance
  classification_inst: ClassificationInstance = classification.create_instance()

  # Set classification answer
  classification_inst.set_answer(
      answer=classification_answer
  )

  # Add the text region instance to both Label Spaces
  label_space_1.put_object_instance(
      object_instance=text_inst,
      on_overlap="replace",
      ranges= HtmlRange(start=HtmlNode(xpath="start", offset=0), end=HtmlNode(xpath="end", offset=1))
  )

  label_space_2.put_object_instance(
      object_instance=text_inst,
      on_overlap="replace",
      ranges= HtmlRange(start=HtmlNode(xpath="start", offset=0), end=HtmlNode(xpath="end", offset=1))
  )

  # Add the classification instance to both Label Spaces
  label_space_1.put_classification_instance(
      classification_instance=classification_inst
  )
  label_space_2.put_classification_instance(
      classification_instance=classification_inst
  )

  # Save Label Row
  lr.save()
  print(f"Saved label row for {lr.data_title}")
  ```

  ```python PDF theme={"dark"}
  from encord import EncordUserClient, Project
  from encord.objects import Object, Classification, ClassificationInstance, ObjectInstance, LabelRowV2
  from encord.objects.coordinates import BoundingBoxCoordinates
  from encord.objects.options import Option

  # User input
  SSH_PATH = "<private_key_path>"  # Replace with the file path to your SSH private key
  PROJECT_ID = "<project_id>"  # Replace with the unique Project ID
  DATA_TITLE = "<data_unit_title>" # Replace with the title of the data unit 
  LABEL_SPACE = "<label_space_id>" # Replace with the unique ID of the label space

  # --- 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",
  )

  # Get Project
  project: Project = user_client.get_project(PROJECT_ID)

  # Get all Label Rows for the data unit
  rows = project.list_label_rows_v2(data_title_eq=DATA_TITLE)

  # Assume we want the first Label Row
  lr = rows[0]
  lr.initialise_labels()

  # Find bounding box object "Region of Interest" in the Ontology.
  ontology_structure = project.ontology_structure
  box_ontology_object: Object = ontology_structure.get_child_by_title(title="Region of Interest", type_=Object)

  # Find classification "Readable?" in the Ontology
  classification: Classification = ontology_structure.get_child_by_title(title="Readable?", type_=Classification)

  # Find classification answer "Yes" in the Ontology
  classification_answer = classification.get_child_by_title(
      title="Yes", type_=Option
  )

  # Get Label Spaces
  label_space_1 = lr.get_space(layout_key="doc_1", type_="pdf")
  label_space_2 = lr.get_space(layout_key="doc_2", type_="pdf")

  # Create bounding box instance
  bb_inst: ObjectInstance = box_ontology_object.create_instance()

  # Find the text attribute "Language" in the Ontology object and set the answer
  attribute = box_ontology_object.get_child_by_title("Language")
  bb_inst.set_answer(attribute=attribute, answer="Russian")

  # Create classification instance
  classification_inst: ClassificationInstance = classification.create_instance()

  # Set classification answer
  classification_inst.set_answer(
      answer=classification_answer
  )

  # Add the bounding box instance to both Label Spaces. Frame refers to page number.
  label_space_1.put_object_instance(
      object_instance=bb_inst,
      on_overlap="replace",
      coordinates=BoundingBoxCoordinates(
          top_left_x=0.6,
          top_left_y=0.4,
          width=0.3,
          height=0.2
      ),
      frames=[0]
  )

  label_space_2.put_object_instance(
      object_instance=bb_inst,
      on_overlap="replace",
      coordinates=BoundingBoxCoordinates(
          top_left_x=0.6,
          top_left_y=0.4,
          width=0.3,
          height=0.2
      ),
      frames=[0]
  )

  # Add the classification instance to both Label Spaces
  label_space_1.put_classification_instance(
      classification_instance=classification_inst,
      frames=[0]
  )

  label_space_2.put_classification_instance(
      classification_instance=classification_inst,
      frames=[0]
  )

  # Save Label Row
  lr.save()
  print(f"Saved label row for {lr.data_title}")
  ```

  ```python DICOM / NIfTI theme={"dark"}
  from encord import EncordUserClient, Project
  from encord.objects import Object, Classification, ClassificationInstance, ObjectInstance, LabelRowV2
  from encord.objects.coordinates import BoundingBoxCoordinates
  from encord.objects.options import Option

  # User input
  SSH_PATH = "<private_key_path>"  # Replace with the file path to your SSH private key
  PROJECT_ID = "<project_id>"  # Replace with the unique Project ID
  DATA_TITLE = "<data_unit_title>" # Replace with the title of the data unit 
  LABEL_SPACE = "<label_space_id>" # Replace with the unique ID of the label space

  # --- 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",
  )

  # Get Project
  project: Project = user_client.get_project(PROJECT_ID)

  # Get all Label Rows for the data unit
  rows = project.list_label_rows_v2(data_title_eq=DATA_TITLE)
  # Assume we want the first Label Row
  lr = rows[0]
  lr.initialise_labels()

  # Find bounding box object "Region of Interest" in the Ontology.
  ontology_structure = project.ontology_structure
  box_ontology_object: Object = ontology_structure.get_child_by_title(title="Region of Interest", type_=Object)

  # Find classification "Valid Scan?" in the Ontology
  classification: Classification = ontology_structure.get_child_by_title(title="Valid Scan?", type_=Classification)

  # Find classification answer "Yes" in the Ontology
  classification_answer = classification.get_child_by_title(
      title="Yes", type_=Option
  )

  # Get Label Spaces
  label_space_1 = lr.get_space(layout_key="scan_1", type_="medical")
  label_space_2 = lr.get_space(layout_key="scan_2", type_="medical")

  # Create bounding box instance
  bb_inst: ObjectInstance = box_ontology_object.create_instance()

  # Find the text attribute "Abnormality description" in the Ontology object and set the answer
  attribute = box_ontology_object.get_child_by_title("Abnormality description")
  bb_inst.set_answer(attribute=attribute, answer="Nodule detected, approximately 3mm in diameter")

  # Create classification instance
  classification_inst: ClassificationInstance = classification.create_instance()

  # Set classification answer
  classification_inst.set_answer(
      answer=classification_answer
  )

  # Add the bounding box instance to both Label Spaces
  label_space_1.put_object_instance(
      object_instance=bb_inst,
      on_overlap="replace",
      coordinates=BoundingBoxCoordinates(
          top_left_x=0.6,
          top_left_y=0.4,
          width=0.3,
          height=0.2
      ),
      frames=[0]
  )

  label_space_2.put_object_instance(
      object_instance=bb_inst,
      on_overlap="replace",
      coordinates=BoundingBoxCoordinates(
          top_left_x=0.6,
          top_left_y=0.4,
          width=0.3,
          height=0.2
      ),
      frames=[0]
  )

  # Add the classification instance to both Label Spaces
  label_space_1.put_classification_instance(
      classification_instance=classification_inst,
      frames=[0]
  )

  label_space_2.put_classification_instance(
      classification_instance=classification_inst,
      frames=[0]
  )

  # Save Label Row
  lr.save()
  print(f"Saved label row for {lr.data_title}")
  ```

  ```python Multi Layer Data Group theme={"dark"}
  from encord import EncordUserClient, Project
  from encord.objects import Object, Classification, ClassificationInstance, ObjectInstance
  from encord.objects.coordinates import BoundingBoxCoordinates
  from encord.objects.options import Option

  # User input
  SSH_PATH = "<private_key_path>"       # Replace with the file path to your SSH private key
  PROJECT_ID = "<project_id>"           # Replace with the unique Project ID
  DATA_TITLE = "<data_unit_title>"      # Replace with the title of the data unit

  # --- 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",
  )

  # Get Project
  project: Project = user_client.get_project(PROJECT_ID)

  # Get all Label Rows for the data unit
  rows = project.list_label_rows_v2(data_title_eq=DATA_TITLE)

  # Assume we want the first Label Row
  lr = rows[0]
  lr.initialise_labels()

  # --- Ontology setup ---
  ontology_structure = project.ontology_structure

  # Find bounding box object "Cherry" in the Ontology
  box_ontology_object: Object = ontology_structure.get_child_by_title(title="Cherry", type_=Object)

  # Find classification "Day or Night" in the Ontology
  classification: Classification = ontology_structure.get_child_by_title(title="Day or Night", type_=Classification)

  # Find classification answer "Day" in the Ontology
  classification_answer = classification.get_child_by_title(title="Day", type_=Option)

  # --- Get Label Spaces for each image layer in the data group ---
  # Use layout_key to target individual image layers within the data group
  root_space = lr.get_space(id="root", type_="image")                    # Root space: applies to the data group as a whole
  label_space_1 = lr.get_space(layout_key="Fruit_1", type_="image")     # Layer 1
  label_space_2 = lr.get_space(layout_key="Fruit_2", type_="image")     # Layer 2
  label_space_3 = lr.get_space(layout_key="Fruit_3", type_="image")     # Layer 3

  # --- Create instances ---

  # Create bounding box instance
  bb_inst: ObjectInstance = box_ontology_object.create_instance()

  # Set a text attribute answer on the bounding box
  attribute = box_ontology_object.get_child_by_title("Ripeness description")
  bb_inst.set_answer(attribute=attribute, answer="Fully ripe, deep red color with no visible blemishes")

  # Create classification instance and set answer
  classification_inst: ClassificationInstance = classification.create_instance()
  classification_inst.set_answer(answer=classification_answer)

  # --- Add a root-level label that applies to the whole data group ---
  # Adding to root_space applies the classification to the entire data group.
  # No need to add it to individual layer spaces.
  root_space.put_classification_instance(
      classification_instance=classification_inst,
      frames=[0]
  )

  # --- Add bounding box labels to each individual image layer ---
  for space in [label_space_1, label_space_2, label_space_3]:
      space.put_object_instance(
          object_instance=bb_inst,
          on_overlap="replace",
          coordinates=BoundingBoxCoordinates(
              top_left_x=0.6,
              top_left_y=0.4,
              width=0.3,
              height=0.2
          ),
          frames=[0]
      )

  # Save the label row
  lr.save()
  print(f"Saved label row for {lr.data_title}")
  ```
</CodeGroup>

## Remove Labels

The following scripts remove an object from a Label Space.

Ensure that you replace:

* All variables in the `User input` section at the top of the script.
* The names of objects in your Ontology.
* The type and position of the label(s).

<CodeGroup>
  ```python Image theme={"dark"}
  from encord import EncordUserClient, Project
  from encord.objects import Object, Classification, ClassificationInstance, ObjectInstance, LabelRowV2
  from encord.objects.options import Option

  # User input
  SSH_PATH = "<private_key_path>"  # Replace with the file path to your SSH private key
  PROJECT_ID = "<project_id>"  # Replace with the unique Project ID
  DATA_TITLE = "<data_unit_title>" # Replace with the title of the data unit 
  LABEL_SPACE = "<label_space_id>" # Replace with the unique ID of the label space
  OBJECT_INSTANCE = "<object_hash>" # Replace with the object hash of the object you want to remove
  CLASSIFICATION_INSTANCE = "<classification_instance>" # Replace with the classification hash of the classification you want to remove

  # --- 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",
  )

  # Get Project
  project: Project = user_client.get_project(PROJECT_ID)

  # Get all Label Rows for the data unit
  rows = project.list_label_rows_v2(data_title_eq=DATA_TITLE)
  # Assume we want the first Label Row
  lr = rows[0]
  lr.initialise_labels()

  # Get Label Space
  label_space = lr.get_space(layout_key="Fruit", type_="image")

  # Print first object hash in each label space
  label_spaces = lr.get_spaces()

  for space in label_spaces:
      print(space.get_object_instances()[0].object_hash)


  # Remove object
  label_space.remove_object_instance(
  	object_hash=OBJECT_INSTANCE
  )

  # Remove classification
  label_space.remove_classification_instance(
  	classification_hash=CLASSIFICATION_INSTANCE
  )

  # Save label row
  lr.save()
  print(f"Saved label row for {lr.data_title}")
  ```

  ```python Image Sequence theme={"dark"}
  from encord import EncordUserClient, Project
  from encord.objects import Object, Classification, ClassificationInstance, ObjectInstance, LabelRowV2
  from encord.objects.options import Option

  # User input
  SSH_PATH = "<private_key_path>"  # Replace with the file path to your SSH private key
  PROJECT_ID = "<project_id>"  # Replace with the unique Project ID
  DATA_TITLE = "<data_unit_title>" # Replace with the title of the data unit 
  LABEL_SPACE = "<label_space_id>" # Replace with the unique ID of the label space
  OBJECT_INSTANCE = "<object_hash>" # Replace with the object hash of the object you want to remove
  CLASSIFICATION_INSTANCE = "<classification_instance>" # Replace with the classification hash of the classification you want to remove

  # --- 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",
  )

  # Get Project
  project: Project = user_client.get_project(PROJECT_ID)

  # Get all Label Rows for the data unit
  rows = project.list_label_rows_v2(data_title_eq=DATA_TITLE)
  # Assume we want the first Label Row
  lr = rows[0]
  lr.initialise_labels()

  # Get Label Space
  label_space = lr.get_space(layout_key="cctv", type_="image_sequence")

  # Print first object hash in each label space
  label_spaces = lr.get_spaces()

  for space in label_spaces:
      print(space.get_object_instances()[0].object_hash)

  # Remove object
  label_space.remove_object_instance(
  	object_hash=OBJECT_INSTANCE
  )

  # Remove classification
  label_space.remove_classification_instance(
  	classification_hash=CLASSIFICATION_INSTANCE
  )

  # Save label row
  lr.save()
  print(f"Saved label row for {lr.data_title}")
  ```

  ```python Video theme={"dark"}
  from encord import EncordUserClient, Project
  from encord.objects import Object, Classification, ClassificationInstance, ObjectInstance, LabelRowV2
  from encord.objects.options import Option

  # User input
  SSH_PATH = "<private_key_path>"  # Replace with the file path to your SSH private key
  PROJECT_ID = "<project_id>"  # Replace with the unique Project ID
  DATA_TITLE = "<data_unit_title>" # Replace with the title of the data unit 
  LABEL_SPACE = "<label_space_id>" # Replace with the unique ID of the label space
  OBJECT_INSTANCE = "<object_hash>" # Replace with the object hash of the object you want to remove
  CLASSIFICATION_INSTANCE = "<classification_instance>" # Replace with the classification hash of the classification you want to remove

  # --- 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",
  )

  # Get Project
  project: Project = user_client.get_project(PROJECT_ID)

  # Get all Label Rows for the data unit
  rows = project.list_label_rows_v2(data_title_eq=DATA_TITLE)
  # Assume we want the first Label Row
  lr = rows[0]
  lr.initialise_labels()

  # Get Label Space
  label_space = lr.get_space(layout_key="cctv", type_="video")

  # Print first object hash in each label space
  label_spaces = lr.get_spaces()

  for space in label_spaces:
      print(space.get_object_instances()[0].object_hash)

  # Remove object
  label_space.remove_object_instance(
  	object_hash=OBJECT_INSTANCE
  )

  # Remove classification
  label_space.remove_classification_instance(
  	classification_hash=CLASSIFICATION_INSTANCE
  )

  # Save label row
  lr.save()
  print(f"Saved label row for {lr.data_title}")
  ```

  ```python Audio theme={"dark"}
  from encord import EncordUserClient, Project
  from encord.objects import Object, Classification, ClassificationInstance, ObjectInstance, LabelRowV2
  from encord.objects.options import Option

  # User input
  SSH_PATH = "<private_key_path>"  # Replace with the file path to your SSH private key
  PROJECT_ID = "<project_id>"  # Replace with the unique Project ID
  DATA_TITLE = "<data_unit_title>" # Replace with the title of the data unit 
  LABEL_SPACE = "<label_space_id>" # Replace with the unique ID of the label space
  OBJECT_INSTANCE = "<object_hash>" # Replace with the object hash of the object you want to remove
  CLASSIFICATION_INSTANCE = "<classification_instance>" # Replace with the classification hash of the classification you want to remove

  # --- 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",
  )

  # Get Project
  project: Project = user_client.get_project(PROJECT_ID)

  # Get all Label Rows for the data unit
  rows = project.list_label_rows_v2(data_title_eq=DATA_TITLE)
  # Assume we want the first Label Row
  lr = rows[0]
  lr.initialise_labels()

  # Get Label Space
  label_space = lr.get_space(layout_key="mp3", type_="audio")

  # Print first object hash in each label space
  label_spaces = lr.get_spaces()

  for space in label_spaces:
      print(space.get_object_instances()[0].object_hash)

  # Remove object
  label_space.remove_object_instance(
  	object_hash=OBJECT_INSTANCE
  )

  # Remove classification
  label_space.remove_classification_instance(
  	classification_hash=CLASSIFICATION_INSTANCE
  )

  # Save label row
  lr.save()
  print(f"Saved label row for {lr.data_title}")
  ```

  ```python Text theme={"dark"}
  from encord import EncordUserClient, Project
  from encord.objects import Object, Classification, ClassificationInstance, ObjectInstance, LabelRowV2
  from encord.objects.options import Option

  # User input
  SSH_PATH = "<private_key_path>"  # Replace with the file path to your SSH private key
  PROJECT_ID = "<project_id>"  # Replace with the unique Project ID
  DATA_TITLE = "<data_unit_title>" # Replace with the title of the data unit 
  LABEL_SPACE = "<label_space_id>" # Replace with the unique ID of the label space
  OBJECT_INSTANCE = "<object_hash>" # Replace with the object hash of the object you want to remove
  CLASSIFICATION_INSTANCE = "<classification_instance>" # Replace with the classification hash of the classification you want to remove

  # --- 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",
  )

  # Get Project
  project: Project = user_client.get_project(PROJECT_ID)

  # Get all Label Rows for the data unit
  rows = project.list_label_rows_v2(data_title_eq=DATA_TITLE)
  # Assume we want the first Label Row
  lr = rows[0]
  lr.initialise_labels()

  # Get Label Space
  label_space = lr.get_space(layout_key="text", type_="text")

  # Print first object hash in each label space
  label_spaces = lr.get_spaces()

  for space in label_spaces:
      print(space.get_object_instances()[0].object_hash)

  # Remove object
  label_space.remove_object_instance(
  	object_hash=OBJECT_INSTANCE
  )

  # Remove classification
  label_space.remove_classification_instance(
  	classification_hash=CLASSIFICATION_INSTANCE
  )

  # Save label row
  lr.save()
  print(f"Saved label row for {lr.data_title}")
  ```

  ```python HTML  theme={"dark"}
  from encord import EncordUserClient, Project
  from encord.objects import Object, Classification, ClassificationInstance, ObjectInstance, LabelRowV2
  from encord.objects.options import Option

  # User input
  SSH_PATH = "<private_key_path>"  # Replace with the file path to your SSH private key
  PROJECT_ID = "<project_id>"  # Replace with the unique Project ID
  DATA_TITLE = "<data_unit_title>" # Replace with the title of the data unit 
  LABEL_SPACE = "<label_space_id>" # Replace with the unique ID of the label space
  OBJECT_INSTANCE = "<object_hash>" # Replace with the object hash of the object you want to remove
  CLASSIFICATION_INSTANCE = "<classification_instance>" # Replace with the classification hash of the classification you want to remove

  # --- 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",
  )

  # Get Project
  project: Project = user_client.get_project(PROJECT_ID)

  # Get all Label Rows for the data unit
  rows = project.list_label_rows_v2(data_title_eq=DATA_TITLE)
  # Assume we want the first Label Row
  lr = rows[0]
  lr.initialise_labels()

  # Get Label Space
  label_space = lr.get_space(layout_key="website", type_="html")

  # Print first object hash in each label space
  label_spaces = lr.get_spaces()

  for space in label_spaces:
      print(space.get_object_instances()[0].object_hash)

  # Remove object
  label_space.remove_object_instance(
  	object_hash=OBJECT_INSTANCE
  )

  # Remove classification
  label_space.remove_classification_instance(
  	classification_hash=CLASSIFICATION_INSTANCE
  )

  # Save label row
  lr.save()
  print(f"Saved label row for {lr.data_title}")
  ```

  ```python DICOM / NIfTI theme={"dark"}
  from encord import EncordUserClient, Project
  from encord.objects import Object, Classification, ClassificationInstance, ObjectInstance, LabelRowV2
  from encord.objects.options import Option

  # User input
  SSH_PATH = "<private_key_path>"  # Replace with the file path to your SSH private key
  PROJECT_ID = "<project_id>"  # Replace with the unique Project ID
  DATA_TITLE = "<data_unit_title>" # Replace with the title of the data unit 
  LABEL_SPACE = "<label_space_id>" # Replace with the unique ID of the label space
  OBJECT_INSTANCE = "<object_hash>" # Replace with the object hash of the object you want to remove
  CLASSIFICATION_INSTANCE = "<classification_instance>" # Replace with the classification hash of the classification you want to remove

  # --- 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",
  )

  # Get Project
  project: Project = user_client.get_project(PROJECT_ID)

  # Get all Label Rows for the data unit
  rows = project.list_label_rows_v2(data_title_eq=DATA_TITLE)
  # Assume we want the first Label Row
  lr = rows[0]
  lr.initialise_labels()

  # Get Label Space
  label_space = lr.get_space(layout_key="scan", type_="medical")

  # Print first object hash in each label space
  label_spaces = lr.get_spaces()

  for space in label_spaces:
      print(space.get_object_instances()[0].object_hash)

  # Remove object
  label_space.remove_object_instance(
  	object_hash=OBJECT_INSTANCE
  )

  # Remove classification
  label_space.remove_classification_instance(
  	classification_hash=CLASSIFICATION_INSTANCE
  )

  # Save label row
  lr.save()
  print(f"Saved label row for {lr.data_title}")
  ```

  ```python Multi-Layered Labels theme={"dark"}

  from encord import EncordUserClient, Project
  from encord.objects import Object, Classification, ClassificationInstance, ObjectInstance, LabelRowV2
  from encord.objects.coordinates import BoundingBoxCoordinates
  from encord.objects.options import Option

  # User input
  SSH_PATH = "<private_key_path>"  # Replace with the file path to your SSH private key
  PROJECT_ID = "<project_id>"  # Replace with the unique Project ID
  DATA_TITLE = "<data_unit_title>"  # Replace with the title of the data unit

  # --- 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",
  )

  # Get Project
  project: Project = user_client.get_project(PROJECT_ID)

  # Get all Label Rows for the data unit
  rows = project.list_label_rows_v2(data_title_eq=DATA_TITLE)

  # Assume we want the first Label Row
  lr = rows[0]
  lr.initialise_labels()

  # Find bounding box object "Cherry" in the Ontology
  ontology_structure = project.ontology_structure
  box_ontology_object: Object = ontology_structure.get_child_by_title(title="Cherry", type_=Object)

  # Find classification "Day or Night" in the Ontology
  classification: Classification = ontology_structure.get_child_by_title(title="Day or Night", type_=Classification)

  # Find classification answer "Day" in the Ontology
  classification_answer = classification.get_child_by_title(
      title="Day", type_=Option
  )

  # Get the root Label Space. The root space pertains to the Data Group as a whole, including multi-layered labels
  root_space = lr.get_space(id="root", type_="image")

  # Create bounding box instance
  bb_inst: ObjectInstance = box_ontology_object.create_instance()

  # Find the text attribute "Ripeness description" in the Ontology and set the answer
  attribute = box_ontology_object.get_child_by_title("Ripeness description")
  bb_inst.set_answer(attribute=attribute, answer="Fully ripe, deep red color with no visible blemishes")

  # Create classification instance
  classification_inst: ClassificationInstance = classification.create_instance()
  classification_inst.set_answer(
      answer=classification_answer
  )

  # Add the bounding box instance to the root Label Space
  root_space.put_object_instance(
      object_instance=bb_inst,
      on_overlap="replace",
      coordinates=BoundingBoxCoordinates(
          top_left_x=0.6,
          top_left_y=0.4,
          width=0.3,
          height=0.2
      ),
      frames=[0]
  )

  # Add the classification instance to the root Label Space
  root_space.put_classification_instance(
      classification_instance=classification_inst,
      frames=[0]
  )

  lr.save()
  print(f"Saved label row for {lr.data_title}")

  ```
</CodeGroup>

## Put It All Together

The following is an example demonstrating how to use Label Spaces.

We have Data Groups with five data units in the following layout:

<CodeGroup>
  ```pgsql Data units theme={"dark"}
  +-------------------------------------------+
  |              text file                    |
  +------------------+------------------------+
  |     video 1      |        video 2         |
  +------------------+------------------------+
  |     video 3      |        video 4         |
  +------------------+------------------------+

  ```

  ```pgsql layout_key theme={"dark"}
  +-------------------------------------------+
  |              instructions                 |
  +------------------+------------------------+
  |     top-left     |        top-right       |
  +------------------+------------------------+
  |     bottom-left  |        bottom-left     |
  +------------------+------------------------+
  ```
</CodeGroup>

### Create Example Data Groups

The following script creates the Data Groups and specifies the layout.

```python Create Data Group expandable theme={"dark"}
from uuid import UUID

from encord.constants.enums import DataType
from encord.objects.metadata import DataGroupMetadata
from encord.orm.storage import DataGroupCustom, StorageItemType
from encord.user_client import EncordUserClient

# --- Configuration ---
SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"  # Replace with the file path to your access key
FOLDER_ID = "00000000-0000-0000-0000-000000000000"  # Replace with the Folder ID
DATASET_ID = "00000000-0000-0000-0000-000000000000"  # Replace with the Dataset ID
PROJECT_ID = "00000000-0000-0000-0000-000000000000"  # Replace with the Project ID

# --- 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",
)

folder = user_client.get_storage_folder(FOLDER_ID)

# --- Reusable layout and settings ---
layout = {
    "direction": "column",
    "first": {"type": "data_unit", "key": "instructions"},
    "second": {
        "direction": "column",
        "first": {
            "direction": "row",
            "first": {"type": "data_unit", "key": "top-left"},
            "second": {"type": "data_unit", "key": "top-right"},
            "splitPercentage": 50,
        },
        "second": {
            "direction": "row",
            "first": {"type": "data_unit", "key": "bottom-left"},
            "second": {"type": "data_unit", "key": "bottom-right"},
            "splitPercentage": 50,
        },
        "splitPercentage": 50,
    },
    "splitPercentage": 20,
}
settings = {"tile_settings": {"instructions": {"is_read_only": True}}}

# --- Group definitions (name + UUIDs) ---
groups = [
    {
        "name": "group-001",
        "uuids": {
            "instructions": UUID("00000000-0000-0000-0000-000000000000"), # Replace with File ID of clustered_event_log_01.txt
            "top-left": UUID("11111111-1111-1111-1111-111111111111"), # Replace with File ID of 00001_normalized.mp4
            "top-right": UUID("22222222-2222-2222-2222-222222222222"), # Replace with File ID of 00002_normalized.mp4
            "bottom-left": UUID("33333333-3333-3333-3333-333333333333"), # Replace with File ID of 00009.mp4
            "bottom-right": UUID("44444444-4444-4444-4444-444444444444"), # Replace with File ID of 00011_normalized.mp4
        },
    },
    {
        "name": "group-002",
        "uuids": {
            "instructions": UUID("55555555-5555-5555-5555-555555555555"), # Replace with File ID of clustered_event_log_02.txt
            "top-left": UUID("66666666-6666-6666-6666-666666666666"), # Replace with File ID of 00012.mp4
            "top-right": UUID("77777777-7777-7777-7777-777777777777"), # Replace with File ID of 00020.mp4
            "bottom-left": UUID("88888888-8888-8888-8888-888888888888"), # Replace with File ID of 00030.mp4
            "bottom-right": UUID("99999999-9999-9999-9999-999999999999"), # Replace with File ID of 00033.mp4
        },
    },
    {
        "name": "group-003",
        "uuids": {
            "instructions": UUID("12312312-3123-1231-2312-312312312312"), # Replace with File ID of clustered_event_log_03.txt
            "top-left": UUID("23232323-2323-2323-2323-232323232323"), # Replace with File ID of 00034.mp4
            "top-right": UUID("31313131-3131-3131-3131-313131313131"), # Replace with File ID of 00035_normalized.mp4
            "bottom-left": UUID("45645645-6456-4564-5645-645645645645"), # Replace with File ID of 00038_normalized.mp4
            "bottom-right": UUID("56565656-6565-5656-6565-656565656565 "), # Replace with File ID of 00045.mp4
        },
    },
    # More groups...
]

# Create the data groups

for g in groups:
    group = folder.create_data_group(
        DataGroupCustom(
            name=g["name"],
            layout=layout,
            layout_contents=g["uuids"],
            settings=settings,
        )
    )
    print(f"✅ Created group '{g['name']}' with UUID {group}")

# Add all the data groups in a folder to a Dataset
group_items = folder.list_items(item_types=[StorageItemType.GROUP])
d = user_client.get_dataset(DATASET_ID)
d.link_items([item.uuid for item in group_items])

# Add the Dataset with the Data Groups to a Project

p = user_client.get_project(PROJECT_ID)
rows = p.list_label_rows_v2(include_children=True)

# Label Rows of Data Groups use DataGroupMetadata for the layout to Annotate and Review
for row in rows:
    if row.data_type == DataType.GROUP:
        row.initialise_labels()
        assert isinstance(row.metadata, DataGroupMetadata)
        print(row.metadata.children)
```

### Pre-label Data Groups

We want to pre-label the classifications for all videos with the **layout\_key** `top-left` in the Data Groups with **Yes**. This way annotators only need to update the classification for `top-left` videos where there the model predictions and summaries are incorrect.

Our example Project uses a Dataset that contains our Data Groups. The Ontology looks like this:

**Classifications**

* `Prediction correct?`
  * `YES!` (Radio button)
  * `No`  (Radio button)
    * `What's wrong?` (Text)

* `Summary correct?`
  * `YES!` (Radio button)
  * `No`  (Radio button)
    * `What's wrong?` (Text)

![Data Groups Ontology](https://storage.googleapis.com/docs-media.encord.com/E2E%20Artifacts/Screenshots/e2e-data-groups-ontology.png)

```python Import Classification values on top_left videos expandable theme={"dark"}

from __future__ import annotations

from encord import EncordUserClient, Project
from encord.objects import Classification, ClassificationInstance, LabelRowV2
from encord.objects.options import Option


# User input: Edit these values as you require

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


# Only apply to THIS label space
LABEL_SPACE = "top-left"

CLASSIFICATIONS = [
    "Prediction correct?",
    "Summary correct?",
]

ANSWER_TITLE = "YES!"

# Frames to apply the classification to
FRAMES = [0]  # change as needed


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


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

ontology = project.ontology_structure

# Fetch ALL label rows

all_rows: list[LabelRowV2] = project.list_label_rows_v2(include_children=True)

# Identify Data Group
data_group_parents = [row for row in all_rows if row.group_hash is None]
print(f"Found {len(data_group_parents)} data groups")


# Process each Data Group
for parent in data_group_parents:
    parent.initialise_labels()

    # Helpful: print what spaces actually exist on this group label row
    spaces = parent.get_spaces()
    print(f"Data group '{parent.data_title}' → {len(spaces)} spaces")
    print("  Available layout keys:", [s.metadata.layout_key for s in spaces])

    # Get the target label space from the PARENT row
    try:
        label_space = parent.get_space(layout_key=LABEL_SPACE, type_="video")
    except Exception as e:
        print(f"  ⚠ Could not find space '{LABEL_SPACE}' on group '{parent.data_title}': {e}")
        continue

    for classification_title in CLASSIFICATIONS:
        classification: Classification = ontology.get_child_by_title(
            title=classification_title,
            type_=Classification,
        )

        yes_option: Option = classification.get_child_by_title(
            title=ANSWER_TITLE,
            type_=Option,
        )

        classification_inst: ClassificationInstance = classification.create_instance()
        classification_inst.set_answer(yes_option)

        label_space.put_classification_instance(
            classification_instance=classification_inst
            )

    parent.save()
    print(f"  ✔ Labeled group row: {parent.data_title} (space: {LABEL_SPACE})")

```

## Accessing Storage Item Metadata With Label Spaces

Label spaces provide a direct link to their storage items using the `space_id` property. It maps to the `uuid` of the corresponding `StorageItem`.

<Note>
  `space.space_id` is equivalent to the `uuid` of the storage item. This holds for all label spaces, not just image Data Groups.
</Note>

This means you can use `get_spaces()` on a label row to traverse from a label space to its storage item and access all metadata such as image dimensions. The following example demonstrates this using a Data Group of plain images, fetching the height and width of each image through its label space:

```python Get image dimensions from storage item theme={"dark"}
from encord import EncordUserClient

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

# Instantiate Encord client
user_client = EncordUserClient.create_with_ssh_private_key(
    ssh_private_key_path=SSH_PATH
)

project = user_client.get_project(PROJECT_ID)

label_rows = project.list_label_rows_v2()
lr = label_rows[0]  # Replace with your target label row
lr.initialise_labels()

# Fetch all storage items
item_ids = [space.space_id for space in lr.get_spaces()]
items = user_client.get_storage_items(item_ids)

for item in items:
    print(f"Height is {item.height}")
    print(f"Width is {item.width}")
```
