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

# Create Ontologies

## Ontology SDK Basics

An Ontology, or labeling protocol, defines the concepts, relationships, and representations in your data. Ontologies are essential for creating object and frame labels by defining what is being labeled.

<Tip>Before you can apply [Classifications](/platform-documentation/Annotate/annotate-ontologies/annotate-ontologies#classifications) to a [Collection](/platform-documentation/Curate/curation-basics#collections) in Encord Active, the [Classifications](/platform-documentation/Annotate/annotate-ontologies/annotate-ontologies#classifications) have to exist in an Ontology in Encord.</Tip>

Encord supports Classifications with nested attributes up to 7 levels deep using Radio buttons (`RadioAttribute`). Checklists and text fields stop the nesting of attributes.

<CodeGroup>
  ```| Attributes nested 7 levels deep theme={"dark"}

   - Classification
      - Radio button
        - Radio button
          - Radio button
            - Radio button
             - Radio button
               - Radio button
                 - Radio button or Checklist or Text box

  ```

  ```| Attributes nested 3 levels deep theme={"dark"}

   - Classification
      - Radio button
        - Radio button
          - Checklist

  ```

  ```| Attributes nested 4 levels deep theme={"dark"}

   - Classification
      - Radio button
        - Radio button
          - Radio button
            - Text box

  ```
</CodeGroup>

## Annotation Ontologies

**Ontology with Annotation:** Creates an Ontology (title="My test Ontology") with a single Bounding Box Object ("Cute cat") in the structure.

**Workflow Project with Ontology and Annotations:** Creates a Workflow Project ("Cats annotation project") with a dataset ("MY\_CAT\_DATASET") and an Ontology.

<CodeGroup>
  ```python Ontology with Annotation theme={"dark"}

  import logging
  import time
  from tqdm import tqdm
  from encord import EncordUserClient
  from encord.objects import Shape, Object, Option, OntologyStructure
  from encord.objects.coordinates import BoundingBoxCoordinates
  from encord.objects.attributes import RadioAttribute, ChecklistAttribute


  user_client = EncordUserClient.create_with_ssh_private_key(
      ssh_private_key_path='/Users/encord/.ssh/id_ed25519'
      )


  ontology_structure = OntologyStructure()
  ontology_structure.add_object("Cute Cat", shape=Shape.BOUNDING_BOX)

  cat_ontology = user_client.create_ontology(title="My test Ontology", structure=ontology_structure)

  ```

  ```python Workflow Project with Ontology and Annotations theme={"dark"}

  import logging
  import time
  from tqdm import tqdm
  from encord import EncordUserClient
  from encord.objects import Shape, Object, Option, OntologyStructure
  from encord.objects.coordinates import BoundingBoxCoordinates
  from encord.objects.attributes import RadioAttribute, ChecklistAttribute

  requests_settings = RequestsSettings(
      max_retries=10,
      read_timeout=1800,
      write_timeout=1800,
  )

  user_client = EncordUserClient.create_with_ssh_private_key(
      ssh_private_key_path='/Users/encord/.ssh/id_ed25519'
      )

  # Now let's create a project for a cat dataset and provide annotations
  MY_CAT_DATASET = '614bbb51-333a-48d0-9dc5-1e92873a5a44'

  ONTOLOGY_HASH = 'd274a855-06cb-4f50-afac-eef176841b4c'

  WORKFLOW_HASH = 'd330ff92-c397-4914-b056-ed6453f1af3c'

  project_hash = user_client.create_project("Cats annotation project", ontology_hash=ONTOLOGY_HASH, dataset_hashes=[MY_CAT_DATASET], workflow_template_hash=WORKFLOW_HASH)

  project = user_client.get_project(project_hash=project_hash)

  label_row = project.list_label_rows_v2()[0]
  label_row.initialise_labels()

  # Use the cat_object from the other example, and this is how you find it
  cat_object = project.ontology_structure.get_child_by_title("Cute Cat", type_=Object)

  # Create instance of the object - a particular cat we want to label
  cat_object_instance = cat_object.create_instance()

  # Creating bounding box coordinates for a cat on a specific frame of specific media.
  bounding_box_coordinates = BoundingBoxCoordinates(height=0.8, width=0.8, top_left_x=0.1, top_left_y=0.1)

  # Setting these coordinates on a particular frame.
  # Images have only one frame, so it doesn't need to be specified here
  cat_object_instance.set_for_frames(bounding_box_coordinates)

  # Attaching object instance to a particular label row
  label_row.add_object_instance(cat_object_instance)

  # Uploading created frame
  label_row.save()

  ```
</CodeGroup>

## Classification Ontologies

<Info>
  * **Standard Classifications** are applied to individual frames.
  * **Global Classifications** are applied to a whole file.
</Info>

Use the following example as a guide to creating your Ontology with Classifications using the SDK.

**Radio button:** Creates an Ontology with 2 radio button lists.

**Checklist:** Creates an Ontology with 3 options in a checklist.

**Text field:** Creates an Ontology with a single text field.

**Number:** Creates an Ontology with a single numerical input field.

**Nested attributes:** Creates an Ontology with 2 levels of nesting.

<Tabs>
  <Tab title="Standard Classifications">
    <CodeGroup>
      ```python Radio Button theme={"dark"}
      from encord import EncordUserClient
      from encord.objects import OntologyStructure
      from encord.objects.attributes import RadioAttribute

      user_client = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path='/Users/encord/.ssh/id_ed25519'
          )

      # Create a new ontology with Classifications
      ontology_structure = OntologyStructure()

      # Adding a Classification of type radio button
      classification = ontology_structure.add_classification()

      cat_colour = classification.add_attribute(RadioAttribute, "colour", required=True)
      cat_colour.add_option("white")
      cat_colour.add_option("black")

      # Create a new ontology with Classifications
      ontology = user_client.create_ontology("Radio Button Ontology", structure=ontology_structure)
      print(f"created ontology {ontology.ontology_hash}")
      ```

      ```python Checklist theme={"dark"}
      from encord import EncordUserClient
      from encord.objects import OntologyStructure
      from encord.objects.attributes import ChecklistAttribute

      user_client = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path='/Users/encord/.ssh/id_ed25519'
          )

      # Create a new ontology with Classifications
      ontology_structure = OntologyStructure()

      # Adding classification of a type checklist
      new_classification = ontology_structure.add_classification()

      new_checklist_attribute = new_classification.add_attribute(ChecklistAttribute, "Location")

      # Adding options for the classification
      new_checklist_attribute.add_option("Here")
      new_checklist_attribute.add_option("There")
      new_checklist_attribute.add_option("Everywhere")

      # Create a new ontology with Classifications
      ontology = user_client.create_ontology("Checklist Ontology", structure=ontology_structure)
      print(f"created ontology {ontology.ontology_hash}")
      ```

      ```python Number theme={"dark"}
      from encord import EncordUserClient
      from encord.objects import OntologyStructure
      from encord.objects.attributes import NumericAttribute

      user_client = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path='/Users/encord/.ssh/id_ed25519'
          )

      # Create a new Ontology with Classifications
      ontology_structure = OntologyStructure()

      # Adding a Number Classification
      new_classification = ontology_structure.add_classification()

      score_attribute = new_classification.add_attribute(NumericAttribute, "Score", required=True)

      # Create a new ontology with Classifications
      ontology = user_client.create_ontology(title="Ontology with numeric attributes", structure=ontology_structure)
      print(f"created ontology {ontology.ontology_hash}")

      ```

      ```python Text Field theme={"dark"}
      from encord import EncordUserClient
      from encord.objects import Shape, Object, Option, OntologyStructure
      from encord.objects.coordinates import BoundingBoxCoordinates
      from encord.objects.attributes import ChecklistAttribute

      user_client = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path='/Users/encord/.ssh/id_ed25519'
          )

      # Create a new ontology with Classifications
      ontology_structure = OntologyStructure()

      # Adding a Classification of type text field
      new_classification = ontology_structure.add_classification()

      new_text_attribute = new_classification.add_attribute(TextAttribute, "Describe location")

      # Create a new ontology with Classifications
      ontology = user_client.create_ontology("Text Field Ontology", structure=ontology_structure)
      print(f"created ontology {ontology.ontology_hash}")
      ```

      ```python Nested Attributes theme={"dark"}
      from encord import EncordUserClient
      from encord.objects import Option, OntologyStructure, attributes
      from encord.objects.attributes import ChecklistAttribute, RadioAttribute, OntologyNestedElement

      requests_settings = RequestsSettings(
          max_retries=10,
          read_timeout=1800,
          write_timeout=1800,
      )

      user_client = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path='/Users/encord/.ssh/id_ed25519'
          )

      # Create a new ontology with Classifications
      ontology_structure = OntologyStructure()


      new_classification = ontology_structure.add_classification()
      new_radio_attribute = new_classification.add_attribute(RadioAttribute, "Green Eggs and Ham?")
      yes_option = new_radio_attribute.add_option("Yes")
      no_option = new_radio_attribute.add_option("No")


      # Provides 1st level nested attribute. RadioAttribute allows further nesting (up to 7 levels deep)
      nested_attribute_yes = yes_option.add_nested_attribute(RadioAttribute, "Where?") 
      # <---- and here
      here_yes_option = nested_attribute_yes.add_option("Here")
      there_yes_option = nested_attribute_yes.add_option("There")
      everywhere_yes_option = nested_attribute_yes.add_option("Everywhere")


      nested_attribute_no = no_option.add_nested_attribute(RadioAttribute, "Where?") 
      # <---- and here
      here_no_option = nested_attribute_no.add_option("Here")
      there_no_option = nested_attribute_no.add_option("There")
      everywhere_no_option = nested_attribute_no.add_option("Everywhere")

      # Provides 2nd level nested attribute. ChecklistAttribute and TextAttribute prevent further nesting.
      nested_attribute_yes_here = here_yes_option.add_nested_attribute(ChecklistAttribute, "Specific location?")
      box_option = nested_attribute_yes_here.add_option("In a box")
      house_option = nested_attribute_yes_here.add_option("In a house")
      car_option = nested_attribute_yes_here.add_option("In a car")

      nested_attribute_yes_there = there_yes_option.add_nested_attribute(ChecklistAttribute, "Specific location?")
      box_option = nested_attribute_yes_there.add_option("In a box")
      house_option = nested_attribute_yes_there.add_option("In a house")
      car_option = nested_attribute_yes_there.add_option("In a car")

      nested_attribute_yes_everywhere = everywhere_yes_option.add_nested_attribute(ChecklistAttribute, "Specific location?")
      box_option = nested_attribute_yes_everywhere.add_option("In a box")
      house_option = nested_attribute_yes_everywhere.add_option("In a house")
      car_option = nested_attribute_yes_everywhere.add_option("In a car")


      nested_attribute_no_here = here_no_option.add_nested_attribute(ChecklistAttribute, "Specific location?")
      box_option = nested_attribute_no_here.add_option("In a box")
      house_option = nested_attribute_no_here.add_option("In a house")
      car_option = nested_attribute_no_here.add_option("In a car")

      nested_attribute_no_there = there_no_option.add_nested_attribute(ChecklistAttribute, "Specific location?")
      box_option = nested_attribute_no_there.add_option("In a box")
      house_option = nested_attribute_no_there.add_option("In a house")
      car_option = nested_attribute_no_there.add_option("In a car")

      nested_attribute_no_everywhere = everywhere_no_option.add_nested_attribute(ChecklistAttribute, "Specific location?")
      box_option = nested_attribute_no_everywhere.add_option("In a box")
      house_option = nested_attribute_no_everywhere.add_option("In a house")
      car_option = nested_attribute_no_everywhere.add_option("In a car")

      # Create a new Ontology with Classifications
      ontology = user_client.create_ontology("Nested Attributes", structure=ontology_structure)
      print(f"created ontology {ontology.ontology_hash}")
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Global Classifications">
    <CodeGroup>
      ```python Radio Button theme={"dark"}
      from encord import EncordUserClient
      from encord.objects import OntologyStructure
      from encord.objects.attributes import RadioAttribute
      from encord.objects.classification import OntologyClassificationLevel

      user_client = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path='/Users/encord/.ssh/id_ed25519'
          )

      # Create a new ontology with Classifications
      ontology_structure = OntologyStructure()

      # Adding a global Classification of type radio button
      classification = ontology_structure.add_classification(level=OntologyClassificationLevel.GLOBAL)

      cat_colour = classification.add_attribute(RadioAttribute, "colour", required=True)
      cat_colour.add_option("white")
      cat_colour.add_option("black")

      # Create a new ontology with Classifications
      ontology = user_client.create_ontology("Radio Button Ontology", structure=ontology_structure)
      print(f"created ontology {ontology.ontology_hash}")
      ```

      ```python Checklist theme={"dark"}
      from encord import EncordUserClient
      from encord.objects import OntologyStructure
      from encord.objects.attributes import ChecklistAttribute
      from encord.objects.classification import OntologyClassificationLevel

      user_client = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path='/Users/encord/.ssh/id_ed25519'
          )

      # Create a new ontology with Classifications
      ontology_structure = OntologyStructure()

      # Adding a global checklist classification
      new_classification = ontology_structure.add_classification(level=OntologyClassificationLevel.GLOBAL)

      new_checklist_attribute = new_classification.add_attribute(ChecklistAttribute, "Location")

      # Adding options for the classification
      new_checklist_attribute.add_option("Here")
      new_checklist_attribute.add_option("There")
      new_checklist_attribute.add_option("Everywhere")

      # Create a new Ontology with global checklist Classification
      ontology = user_client.create_ontology("Checklist Ontology", structure=ontology_structure)
      print(f"created ontology {ontology.ontology_hash}")
      ```

      ```python Number theme={"dark"}
      from encord import EncordUserClient
      from encord.objects import OntologyStructure
      from encord.objects.attributes import NumericAttribute
      from encord.objects.classification import OntologyClassificationLevel

      user_client = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path='/Users/encord/.ssh/id_ed25519'
          )

      # Create a new Ontology with Classifications
      ontology_structure = OntologyStructure()

      # Adding a Number Classification
      new_classification = ontology_structure.add_classification(level=OntologyClassificationLevel.GLOBAL)

      score_attribute = new_classification.add_attribute(NumericAttribute, "Score", required=True)

      # Create a new ontology with global number Classification
      ontology = user_client.create_ontology(title="Ontology with numeric attributes", structure=ontology_structure)
      print(f"created ontology {ontology.ontology_hash}")

      ```

      ```python Text Field theme={"dark"}
      from encord import EncordUserClient
      from encord.objects import Shape, Object, Option, OntologyStructure
      from encord.objects.coordinates import BoundingBoxCoordinates
      from encord.objects.attributes import ChecklistAttribute
      from encord.objects.classification import OntologyClassificationLevel

      user_client = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path='/Users/encord/.ssh/id_ed25519'
          )

      # Create a new Ontology with Classifications
      ontology_structure = OntologyStructure()

      # Adding a Classification of type text field
      new_classification = ontology_structure.add_classification(level=OntologyClassificationLevel.GLOBAL)

      new_text_attribute = new_classification.add_attribute(TextAttribute, "Describe location")

      # Create a new Ontology with global text Classification
      ontology = user_client.create_ontology("Text Field Ontology", structure=ontology_structure)
      print(f"created ontology {ontology.ontology_hash}")
      ```

      ```python Nested Attributes theme={"dark"}
      from encord import EncordUserClient
      from encord.objects import Option, OntologyStructure, attributes
      from encord.objects.attributes import ChecklistAttribute, RadioAttribute, OntologyNestedElement

      requests_settings = RequestsSettings(
          max_retries=10,
          read_timeout=1800,
          write_timeout=1800,
      )

      user_client = EncordUserClient.create_with_ssh_private_key(
          ssh_private_key_path='/Users/encord/.ssh/id_ed25519'
          )

      # Create a new Ontology with global Classification
      ontology_structure = OntologyStructure()

      new_classification = ontology_structure.add_classification(level=OntologyClassificationLevel.GLOBAL)
      new_radio_attribute = new_classification.add_attribute(RadioAttribute, "Green Eggs and Ham?")
      yes_option = new_radio_attribute.add_option("Yes")
      no_option = new_radio_attribute.add_option("No")


      # Provides 1st level nested attribute. RadioAttribute allows further nesting (up to 7 levels deep)
      nested_attribute_yes = yes_option.add_nested_attribute(RadioAttribute, "Where?") 
      # <---- and here
      here_yes_option = nested_attribute_yes.add_option("Here")
      there_yes_option = nested_attribute_yes.add_option("There")
      everywhere_yes_option = nested_attribute_yes.add_option("Everywhere")


      nested_attribute_no = no_option.add_nested_attribute(RadioAttribute, "Where?") 
      # <---- and here
      here_no_option = nested_attribute_no.add_option("Here")
      there_no_option = nested_attribute_no.add_option("There")
      everywhere_no_option = nested_attribute_no.add_option("Everywhere")

      # Provides 2nd level nested attribute. ChecklistAttribute and TextAttribute prevent further nesting.
      nested_attribute_yes_here = here_yes_option.add_nested_attribute(ChecklistAttribute, "Specific location?")
      box_option = nested_attribute_yes_here.add_option("In a box")
      house_option = nested_attribute_yes_here.add_option("In a house")
      car_option = nested_attribute_yes_here.add_option("In a car")

      nested_attribute_yes_there = there_yes_option.add_nested_attribute(ChecklistAttribute, "Specific location?")
      box_option = nested_attribute_yes_there.add_option("In a box")
      house_option = nested_attribute_yes_there.add_option("In a house")
      car_option = nested_attribute_yes_there.add_option("In a car")

      nested_attribute_yes_everywhere = everywhere_yes_option.add_nested_attribute(ChecklistAttribute, "Specific location?")
      box_option = nested_attribute_yes_everywhere.add_option("In a box")
      house_option = nested_attribute_yes_everywhere.add_option("In a house")
      car_option = nested_attribute_yes_everywhere.add_option("In a car")


      nested_attribute_no_here = here_no_option.add_nested_attribute(ChecklistAttribute, "Specific location?")
      box_option = nested_attribute_no_here.add_option("In a box")
      house_option = nested_attribute_no_here.add_option("In a house")
      car_option = nested_attribute_no_here.add_option("In a car")

      nested_attribute_no_there = there_no_option.add_nested_attribute(ChecklistAttribute, "Specific location?")
      box_option = nested_attribute_no_there.add_option("In a box")
      house_option = nested_attribute_no_there.add_option("In a house")
      car_option = nested_attribute_no_there.add_option("In a car")

      nested_attribute_no_everywhere = everywhere_no_option.add_nested_attribute(ChecklistAttribute, "Specific location?")
      box_option = nested_attribute_no_everywhere.add_option("In a box")
      house_option = nested_attribute_no_everywhere.add_option("In a house")
      car_option = nested_attribute_no_everywhere.add_option("In a car")

      # Create a new Ontology with Classifications
      ontology = user_client.create_ontology("Nested Attributes", structure=ontology_structure)
      print(f"created ontology {ontology.ontology_hash}")
      ```
    </CodeGroup>
  </Tab>
</Tabs>

## Ontologies with Annotations and Classifications

This example explains how to create an Ontology with annotations and classifications.

Ensure you replace:

* `<file-path-to-ssh-private-key>` with the pull path to your private key.
* `My test Ontology` with the name of your Ontology.
* `Cute Cat` with the name of your Ontology class.
* As well as any other options relevant to your Ontology.

<CodeGroup>
  ```python Ontology with Annotations and Classifications theme={"dark"}
  from encord import EncordUserClient
  from encord.objects import Shape, Object, Option, OntologyStructure
  from encord.objects.coordinates import BoundingBoxCoordinates
  from encord.objects.attributes import RadioAttribute, ChecklistAttribute


  user_client = EncordUserClient.create_with_ssh_private_key(
      ssh_private_key_path='<file-path-to-ssh-private-key>'
      )


  ontology_structure = OntologyStructure()

  # Adding bounding box annotation
  ontology_structure.add_object("Cute Cat", shape=Shape.BOUNDING_BOX)


  # Adding a Classification of type radio button
  classification = ontology_structure.add_classification()
  cat_colour = classification.add_attribute(RadioAttribute, "colour", required=True)
  cat_colour.add_option("white")
  cat_colour.add_option("black")

  # Adding a Classification of type check box
  classification = ontology_structure.add_classification()
  cat_features = classification.add_attribute(ChecklistAttribute, "features")
  cat_features.add_option("soft")
  cat_features.add_option("fluffy")
  cat_features.add_option("friendly")

  cat_ontology = user_client.create_ontology(title="My test Ontology", structure=ontology_structure)

  ```
</CodeGroup>
