---
title: "Cell"
description: "A cell containing geometry, hierarchy, and ports."
canonical_url: "https://www.rosette.dev/docs/api-reference/Cell"
markdown_url: "https://www.rosette.dev/docs/api-reference/Cell.md"
source_url: "https://github.com/PreFab-Photonics/rosette/blob/f086d7670645fd36c05362d696d442a2b2e74850/www/content/docs/api-reference/Cell.mdx"
docs_channel: "main"
docs_revision: "f086d7670645fd36c05362d696d442a2b2e74850"
---

# Cell

A cell containing geometry, hierarchy, and ports.

Cells are the primary container for layout geometry. Each cell has a unique
name and holds polygons, paths, text labels, ports, and references to other
cells. Use `cell.at(x, y)` to create positioned instances for ergonomic
placement and port queries. Routing diagnostics and DRC policy are not Cell
metadata; they are owned by their respective feature APIs.

Python cell mutations validate their complete input before committing. Invalid
geometry, references, text, or ports raise `ValueError` and leave the cell
unchanged.

```python
cell = Cell("my_design")
cell.add_polygon(Polygon.rect(Point.origin(), 10, 5), Layer(1, 0))
cell.add_port(Port("in", Point(0, 2.5), Vector2(-1, 0), width=0.5))

# Position and add to a parent cell
top = Cell("top")
top.add_ref(cell.at(100, 50))
```

## Attributes



### `name`

```python
name: str
```

Cell name (unique within a design).



## Methods



### `__init__`

```python
__init__(name) -> None
```

Create a new empty cell.



- **`name`** (`str`)

  Name of the cell. Must be unique within a design, non-empty, at most 32
  characters, and contain only printable ASCII (no spaces or Unicode).





**Returns:** `None`



### Geometry



### `add_polygon`

```python
add_polygon(polygon, layer) -> None
```

Add a polygon to the cell.



- **`polygon`** (`Polygon`)

  The polygon to add.





- **`layer`** (`Layer | int | tuple[int, int]`)

  Target layer. Accepts a `Layer` object, a single int (datatype defaults to 0),
  or a `(number, datatype)` tuple.





**Returns:** `None`





### `add_path`

```python
add_path(points, width, layer, cap=None) -> None
```

Add a path (centerline with width) to the cell.

Paths are an alternative to polygons for representing waveguides and
similar structures. They store a centerline and width, which can be
more compact than storing the full polygon outline.



> **Example**
>
> ```python
> cell = Cell("waveguide")
> cell.add_path(
>     [Point(0, 0), Point(100, 0), Point(100, 50)],
>     width=0.5,
>     layer=1,
>     cap=PathCap.ROUND
> )
> ```





- **`points`** (`list[Point]`)

  At least two finite Point objects along the path centerline.





- **`width`** (`float`)

  Finite, nonzero width of the path. Negative widths are absolute: they are not
  scaled with a reference magnification.





- **`layer`** (`Layer | int | tuple[int, int]`)

  Target layer.





- **`cap`** (`PathCap | None`, default `None`)

  Path endpoint geometry. Defaults to `PathCap.FLUSH`.





**Returns:** `None`



Raises `ValueError` without modifying the cell if the centerline or width is
invalid.





### `add_text`

```python
add_text(text, position, layer, height=1.0) -> None
```

Add a text label to the cell.

Text labels are useful for debugging and documentation but are
typically not fabricated.



> **Example**
>
> ```python
> cell.add_text("Input", Point(0, 5), layer=10)
> cell.add_text("Big Label", Point(0, 10), layer=10, height=5.0)
> ```





- **`text`** (`str`)

  The text string.





- **`position`** (`Point`)

  Finite position of the text.





- **`layer`** (`Layer | int | tuple[int, int]`)

  Target layer.





- **`height`** (`float`, default `1.0`)

  Positive finite text height in user units.





**Returns:** `None`



Raises `ValueError` without modifying the cell if the position or height is
invalid.



### Port operations



### `add_port`

```python
add_port(port) -> None
```

Add a validated port to the cell. Port names must be unique within a cell.



- **`port`** (`Port`)

  The port to add.





**Returns:** `None`



Raises `ValueError` without modifying the cell if the port is invalid or its
name is already present.





### `port`

```python
port(name) -> Port
```

Get a port by name.



- **`name`** (`str`)

  Name of the port to retrieve.





**Returns:** `Port`

The port object.





### `ports`

```python
ports() -> list[Port]
```

Get all ports defined on this cell.



**Returns:** `list[Port]`

List of all ports.



### Counts



### `polygon_count`

```python
polygon_count() -> int
```

Number of polygons in the cell (not counting child cells).



**Returns:** `int`





### `polygons`

```python
polygons() -> list[tuple[Polygon, Layer]]
```

Get all polygons (and their layers) stored directly on this cell.

Does not descend into referenced cells; only returns polygons added via
`add_polygon`. Cell references and paths are excluded.



**Returns:** `list[tuple[Polygon, Layer]]`

List of `(polygon, layer)` tuples, in insertion order.





### `path_count`

```python
path_count() -> int
```

Number of paths in the cell.



**Returns:** `int`





### `text_count`

```python
text_count() -> int
```

Number of text labels in the cell.



**Returns:** `int`





### `ref_count`

```python
ref_count() -> int
```

Number of cell references.



**Returns:** `int`





### `cell_ref_names`

```python
cell_ref_names() -> list[str]
```

Get the sorted unique names of cells referenced directly by this cell.



**Returns:** `list[str]`



### Bounding box



### `bbox`

```python
bbox() -> BBox | None
```

Calculate the bounding box of the geometry directly in this cell.

Includes polygons and paths. Does **not** resolve cell references. If this
cell contains SREFs or AREFs, their contribution is ignored.
Use [`Library.cell_bbox(name)`](/docs/api-reference/Library#cell_bbox) for the fully
resolved bounding box of a cell inside a library.

Returns `None` if the cell has no direct geometry.



**Returns:** `BBox | None`



### Placement



### `at`

```python
at(x, y) -> Instance
```

Create a positioned instance of this cell.

This is the public way to place cells in a design. The returned `Instance`
keeps the cell and transform together, allowing direct transformed-port
queries.



> **Example**
>
> ```python
> from rosette.components import grating_coupler
>
> gc_cell = grating_coupler(layer=layers.silicon.layer)
> gc_in = gc_cell.at(0, 0)
> gc_out = gc_cell.at(0, 127)
>
> # Get ports directly from instances
> port_in = gc_in.port("opt")
> port_out = gc_out.port("opt")
> ```





- **`x`** (`float`)

  Finite X coordinate.





- **`y`** (`float`)

  Finite Y coordinate.





**Returns:** `Instance`

An Instance positioned at (x, y).





### `add_ref`

```python
add_ref(ref) -> None
```

Add a resolved instance to this cell.

Use `cell.at(x, y)` to create the required `Instance`, including explicit
`cell.at(0, 0)` placement at the origin. The child cell is automatically
tracked so that `write_gds()` can collect the full hierarchy without a manual
cell list.

The reference transform must be finite, invertible, and representable as a
GDS placement (translation, rotation, reflection, and uniform nonzero scale).
Validation happens before the parent reference list or tracked child set is
updated.



> **Example**
>
> ```python
> top.add_ref(gc_cell.at(0, 0))        # Instance at position
> top.add_ref(route.to_cell("wg").at(0, 0))
> ```





- **`ref`** (`Instance`)

  A resolved `Instance` to place with its transform.





**Returns:** `None`



Raises `TypeError` when `ref` is not an `Instance`, or `ValueError` when the
placement is invalid, without modifying the parent.