Active and Index support filtering, creating Collections, and by extension, creating Datasets and Projects based on the custom metadata on your data.
Prerequisites
Before you can filter your data or create a Collection based on your data’s custom metadata, the custom metadata must exist in your Annotate Project. s
This content applies to custom metadata (
clientMetadata
), which is the metadata associated with individual data units. This is distinct from
videoMetadata
that is used to specify video parameters when using
Strict client-only access. It is also distinct from
patient metadata in DICOM files.
Custom metadata (clientMetadata
) is accessed by specifying the dataset using the <dataset_hash>. All Projects that have the specified Dataset attached contain custom metadata.
READ THIS FIRST
While not required, we strongly recommend importing a metadata schema before importing custom metadata into Encord. The process we recommend:
- Import a metadata schema.
- Import your custom metadata.
If a metadata schema already exists, you can import metadata. You can run a small piece of code to verify that a metadata schema exists.
Performing multiple schema imports overwrites the current schema with the new schema.
If you are not using Index or Active, you do not need to create a Custom Metadata Schema, because you will not be using custom metadata.
Before importing your custom metadata to Encord, we recommend that you import a metadata schema. Encord uses metadata schemas to validate custom metadata uploaded to Encord and to instruct Index and Active how to display your metadata.
To handle your custom metadata schema across multiple teams within the same organization, we recommend using namespacing for metadata keys in the schema. This ensures that different teams can define and manage their own metadata schema without conflicts. For example, team A could use video.description
, while team B could use audio.description
. Another example could be TeamName.MetadataKey
. This approach maintains clarity and avoids key collisions across departments.
Using a metadata schema provides several benefits:
- Validation: Ensures that all custom metadata conforms to predefined data types, reducing errors during data import and processing.
- Consistency: Maintains uniformity in data types across different datasets and projects, which simplifies data management and analysis.
- Filtering and Sorting: Enhances the ability to filter and sort data efficiently in the Encord platform, enabling more accurate and quick data retrieval.
Metadata Schema keys support letters (a-z, A-Z), numbers (0-9), and blank spaces ( ), hyphens (-), underscores (_), and periods (.). Metadata schema keys are case sensitive.
Use add_scalar
to add a scalar key to your metadata schema.
Scalar Key | Description | Display Benefits |
---|
boolean | Binary data type with values “true” or “false”. | Filtering by binary values |
datetime | ISO 8601 formatted date and time. | Filtering by time and date |
number | Numeric data type supporting float values. | Filtering by numeric values |
uuid | Customer specified unique identifier for a data unit. | Filtering by customer specified unique identifier |
varchar | Textual data type. Formally string . string can be used as an alias for varchar , but we STRONGLY RECOMMEND that you use varchar . | Filtering by string. |
text | Text data with unlimited length (example: transcripts for audio). Formally long_string . long_string can be used as an alias for text , but we STRONGLY RECOMMEND that you use text . | Storing and filtering large amounts of text. |
Use add_enum
and add_enum_options
to add an enum and enum options to your metadata schema.
Key | Description | Display Benefits |
---|
enum | Enumerated type with predefined set of values. | Facilitates categorical filtering and data validation |
Use add_embedding
to add an embedding to your metadata schema.
Key | Description | Display Benefits |
---|
embedding | 1 to 4096 for Index. 1 to 2000 for Active. | Filtering by embeddings, similarity search, 2D scatter plot visualization (Coming Soon) |
Incorrectly specifying a data type in the schema can cause errors when filtering your data in Index or Active. If you encounter errors while filtering, verify your schema is correct. If your schema has errors, correct the errors, re-import the schema, and then re-sync your Active Project.
from encord import EncordUserClient
SSH_PATH = "<file-path-to-ssh-private-key>"
user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
ssh_private_key_path=SSH_PATH
)
user_client.set_client_metadata_schema_from_dict({'metadata_1': 'data type', 'metadata_2': 'data type', 'metadata_3': 'data type'})
from encord import EncordUserClient
SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"
user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
ssh_private_key_path=SSH_PATH
)
user_client.set_client_metadata_schema_from_dict({'captured_at': 'datetime', 'city': 'datetime', 'dark': 'boolean'})
Verify your schema
After importing your schema to Encord we recommend that you verify that the import is successful. Run the following code to verify your metadata schema imported and that the schema is correct.
Verify your schema template
from encord import EncordUserClient
SSH_PATH = "<file-path-to-ssh-private-key>"
user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
ssh_private_key_path=SSH_PATH
)
schema = user_client.get_client_metadata_schema()
print(schema)
Verify your schema example
from encord import EncordUserClient
SSH_PATH = "/Users/chris-encord/ssh-private-key.txt"
user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
ssh_private_key_path=SSH_PATH
)
schema = user_client.get_client_metadata_schema()
print(schema)
Reserved Keywords
Reserved keywords are strings that are set aside for exclusive use. The following keywords are reserved:
KEYFRAMES
keyframes
is reserved for use with frames of interest in videos. Specifying keyframes
on specific frames ensures that those frames are imported into Index and Active. That means frames specified using keyframes
are available to filter your frames and for calculating embeddings on your data.
client_metadata = {
"keyframes": [<frame_number>, <frame_number>, <frame_number>, <frame_number>, <frame_number>]
}
client_metadata = {
"keyframes": [13, 17, 19, 23, 127, 149, 307, 557]
}
You can include keyframes
while importing your videos or after you import your videos.
Import keyframes
to specific data units in a folder
This code allows you to import keyframes
on specific videos in Index. This code DOES NOT OVERWRITE all existing custom metadata on a data unit. It does overwrite custom metadata with existing values and adds new custom metadata to the data unit.
from encord import EncordUserClient
SSH_PATH = "<private_key_path>"
user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
ssh_private_key_path=SSH_PATH,
)
updates = {
"<data-unit-id>": {"keyframes": [<frame_number>, <frame_number>, <frame_number>, <frame_number>, <frame_number>]},
"<data-unit-id>": {"keyframes": [<frame_number>, <frame_number>, <frame_number>, <frame_number>, <frame_number>]},
"<data-unit-id>": {"keyframes": [<frame_number>, <frame_number>, <frame_number>, <frame_number>, <frame_number>]},
"<data-unit-id>": {"keyframes": [<frame_number>, <frame_number>, <frame_number>, <frame_number>, <frame_number>]}
}
for item_uuid, metadata_update in updates.items():
item = user_client.get_storage_item(item_uuid=item_uuid)
curr_metadata = item.client_metadata.copy()
curr_metadata.update(metadata_update)
item.update(client_metadata=curr_metadata)
from encord import EncordUserClient
SSH_PATH = "/Users/chris-encord/sdk-ssh-private-key.txt"
user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
ssh_private_key_path=SSH_PATH,
)
updates = {
"8ad58157-ca74-4ae4-8f37-a0193430bcac": {"keyframes": [13, 17, 19, 23, 127, 149, 307, 557]},
"f165fe81-1956-4347-81ca-3a3b198f3f23": {"keyframes": [10, 110, 210, 320, 430]},
"9bd58157-ca74-4ae4-8f37-a0193431bcba": {"keyframes": [1087, 1549, 2029, 3527]},
"62daaa33-195e-4faf-be5b-8335a239beb6": {"keyframes": [1000, 2001, 3241, 4637, 5431]}
}
for item_uuid, metadata_update in updates.items():
item = user_client.get_storage_item(item_uuid=item_uuid)
curr_metadata = item.client_metadata.copy()
curr_metadata.update(metadata_update)
item.update(client_metadata=curr_metadata)
from encord import EncordUserClient
from encord.orm.storage import StorageFolder, StorageItem, StorageItemType, FoldersSortBy
SSH_PATH = "<file-path-to-ssh-private-key-file>"
FOLDER_HASH = "<unique-folder-id>"
user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
ssh_private_key_path=SSH_PATH,
)
folder = user_client.get_storage_folder(FOLDER_HASH)
items = folder.list_items()
for item in items:
print (item.uuid, item.client_metadata)
from encord import EncordUserClient
from encord.orm.storage import StorageFolder, StorageItem, StorageItemType, FoldersSortBy
SSH_PATH = "/Users/chris-encord/sdk-ssh-private-key.txt"
FOLDER_HASH = "2a838557-d6f4-4408-a980-64246dc5c56b"
user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
ssh_private_key_path=SSH_PATH,
)
folder = user_client.get_storage_folder(FOLDER_HASH)
items = folder.list_items()
for item in items:
print (item.uuid, item.client_metadata)
We strongly recommend that you upload your custom metadata to Folders, instead of importing using Datasets. Importing custom metadata to data in folders allows you to filter your data in Index by custom metadata.
After importing or updating custom metadata, verify that your custom metadata (list the data units with custom metadata) applied correctly. Do not simply add a print
command after importing or updating your custom metadata.
This code allows you to import custom metadata on specific data units in Index. This code OVERWRITES all existing custom metadata on a data unit.
from encord import EncordUserClient
from encord.orm.storage import StorageFolder, StorageItem, StorageItemType, FoldersSortBy
SSH_PATH = "<file-path-to-ssh-private-key-file>"
FOLDER_HASH = "<unique-folder-id>"
user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
ssh_private_key_path=SSH_PATH,
)
folder = user_client.get_storage_folder(FOLDER_HASH)
updates = {
}
for item_uuid, metadata in updates.items():
item = user_client.get_storage_item(item_uuid=item_uuid)
item.update(client_metadata=metadata)
from encord import EncordUserClient
from encord.orm.storage import StorageFolder, StorageItem, StorageItemType, FoldersSortBy
SSH_PATH = "/Users/chris-encord/sdk-ssh-private-key.txt"
FOLDER_HASH = "2a838557-d6f4-4408-a980-64246dc5c56b"
user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
ssh_private_key_path=SSH_PATH,
)
folder = user_client.get_storage_folder(FOLDER_HASH)
updates = {
"8ad58157-ca74-4ae4-8f37-a0193430bcac": {"dark": True},
"f165fe81-1956-4347-81ca-3a3b198f3f23": {"light": False},
"9bd58157-ca74-4ae4-8f37-a0193431bcba": {"count": "100"},
"62daaa33-195e-4faf-be5b-8335a239beb6": {"taken_at": "2024-02-24"}
}
for item_uuid, metadata in updates.items():
item = user_client.get_storage_item(item_uuid=item_uuid)
item.update(client_metadata=metadata)
This code allows you to update ALL custom metadata on ALL data units in a Folder in Index. This code OVERWRITES all existing custom metadata on a data unit.
from encord import EncordUserClient
from encord.orm.storage import StorageFolder, StorageItem, StorageItemType, FoldersSortBy
SSH_PATH = "<file-path-to-ssh-private-key-file>"
FOLDER_HASH = "<unique-folder-id>"
user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
ssh_private_key_path=SSH_PATH,
)
folder = user_client.get_storage_folder(FOLDER_HASH)
items = folder.list_items()
for item in items:
item.update(client_metadata={"metadata": "value", "metadata": "value"})
from encord import EncordUserClient
from encord.orm.storage import StorageFolder, StorageItem, StorageItemType, FoldersSortBy
SSH_PATH = "/Users/chris-encord/sdk-ssh-private-key.txt"
FOLDER_HASH = "2a838557-d6f4-4408-a980-64246dc5c56b"
user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
ssh_private_key_path=SSH_PATH,
)
folder = user_client.get_storage_folder(FOLDER_HASH)
items = folder.list_items()
for item in items:
item.update(client_metadata={"dark": True, "captured_at": "2024-02-24"})
This code allows you to update custom metadata on specific data units in Index. This code DOES NOT OVERWRITE all existing custom metadata on a data unit. It does overwrite custom metadata with existing values and adds new custom metadata to the data unit.
from encord import EncordUserClient
SSH_PATH = "<private_key_path>"
user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
ssh_private_key_path=SSH_PATH,
)
updates = {
}
for item_uuid, metadata_update in updates.items():
item = user_client.get_storage_item(item_uuid=item_uuid)
curr_metadata = item.client_metadata.copy()
curr_metadata.update(metadata_update)
item.update(client_metadata=curr_metadata)
from encord import EncordUserClient
SSH_PATH = "/Users/chris-encord/sdk-ssh-private-key.txt"
user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
ssh_private_key_path=SSH_PATH,
)
updates = {
"8ad58157-ca74-4ae4-8f37-a0193430bcac": {"dark": True},
"f165fe81-1956-4347-81ca-3a3b198f3f23": {"light": False},
"9bd58157-ca74-4ae4-8f37-a0193431bcba": {"count": "100"},
"62daaa33-195e-4faf-be5b-8335a239beb6": {"taken_at": "2024-02-24"}
}
for item_uuid, metadata_update in updates.items():
item = user_client.get_storage_item(item_uuid=item_uuid)
curr_metadata = item.client_metadata.copy()
curr_metadata.update(metadata_update)
item.update(client_metadata=curr_metadata)
This code allows you to update custom metadata on all data units in a Folder in Index. This code OVERWRITES all existing custom metadata on a data unit.
Using bundle
allows you to update up to 1000 label rows at a time.
from encord import EncordUserClient
from encord.http.bundle import Bundle
from encord.orm.storage import StorageFolder, StorageItem, StorageItemType, FoldersSortBy
SSH_PATH = "<ssh-private-key>"
FOLDER_HASH = "<unique-folder-id>"
user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
ssh_private_key_path=SSH_PATH,
)
folder = user_client.get_storage_folder(FOLDER_HASH)
items = folder.list_items()
with Bundle() as bundle:
for item in items:
item.update(client_metadata={"metadata-1": "value", "metadata-2": False}, bundle=bundle)
This code allows you to update custom metadata on specific data units in a Folder in Index. This code DOES NOT OVERWRITE existing custom metadata on a data unit. It does overwrite custom metadata with existing values and adds new custom metadata to the data unit.
Using bundle
allows you to update up to 1000 label rows at a time.
from encord import EncordUserClient
from encord.http.bundle import Bundle
from encord.orm.storage import StorageFolder, StorageItem, StorageItemType, FoldersSortBy
SSH_PATH = "<ssh-private-key>"
FOLDER_HASH = "<unique-folder-id>"
user_client: EncordUserClient = EncordUserClient.create_with_ssh_private_key(
ssh_private_key_path=SSH_PATH,
)
folder = user_client.get_storage_folder(FOLDER_HASH)
updates = {
}
with Bundle() as bundle:
for storage_item in folder.list_items():
update = updates[storage_item.uuid]
storage_item.update(client_metadata=update, bundle=bundle)
We strongly recommend that you upload your custom metadata to Folders, instead of importing using Datasets. Importing custom metadata to data in Folders allows you to filter your data in Index by custom metadata.
The following code lists the custom metadata of all data units in the specified Dataset. The code prints the custom metadata along with the data unit’s index within the dataset.
from encord import EncordUserClient
from encord.client import DatasetAccessSettings
client = EncordUserClient.create_with_ssh_private_key(
ssh_private_key_path="<private_key_path>"
)
dataset = client.get_dataset("<dataset_hash>")
dataset.set_access_settings(DatasetAccessSettings(fetch_client_metadata=True))
for data_unit, data_row in enumerate(dataset.data_rows):
print(f"{data_row.client_metadata} - Data Unit: {data_unit}")
Before importing custom metadata to Encord, first import a metadata schema.
We strongly recommend that you import your custom metadata to Folders, instead of importing to Datasets. Importing custom metadata to data in folders allows you to filter your data in Index by custom metadata.
You can import custom metadata (clientMetadata
) to specific data units in the Dataset.
from encord import EncordUserClient
from encord.client import DatasetAccessSettings
client = EncordUserClient.create_with_ssh_private_key(
ssh_private_key_path="<private_key_path>"
)
dataset = client.get_dataset("<dataset_hash>")
dataset.set_access_settings(DatasetAccessSettings(fetch_client_metadata=True))
data_row = dataset.data_rows[<data unit number>]
data_row.client_metadata= {"my": "metadata"}
data_row.save()
print(data_row.client_metadata)
The following code adds the same custom metadata (clientMetadata
) to each data unit in the specified dataset. The code prints the custom metadata along with the data units index within the dataset, so that you can verify that the custom metadata was set correctly.
from encord import EncordUserClient
from encord.client import DatasetAccessSettings
client = EncordUserClient.create_with_ssh_private_key(
ssh_private_key_path="<private_key_path>"
)
dataset = client.get_dataset("<dataset_hash>")
dataset.set_access_settings(DatasetAccessSettings(fetch_client_metadata=True))
for data_unit, data_row in enumerate(dataset.data_rows):
data_row.client_metadata = {"my": "metadata"}
data_row.save()
print(f"{data_row.client_metadata} - Data Unit: {data_unit}")
Once your custom metadata is included in your Annotate Project (Folder or Dataset), you can create Collections based on your custom metadata and then send those Collections to Annotate.
-
Import your Project that has custom metadata.
-
Click the Project once import completes.
The Project opens with the Explorer page displaying.
-
Filter the Project Data, Labels, or Predictions in the Explorer using a Custom Metadata filter.
-
Continue searching, sorting, and filtering your data/labels/predictions until you have the subset of the data you need.
-
Select one or more of the images in the Explorer workspace.
A ribbon appears at the top of the Explorer workspace.
-
Click Select all to select all the images.
-
Click Add to a Collection.
-
Click New Collection.
-
Specify a meaningful title and description for the Collection.
The title specified here is applied as a tag/label to every selected image.
-
Send the Collection to Annotate.