---
title: "Instance"
description: "A cell placed at a specific location with optional transformations."
canonical_url: "https://www.rosette.dev/docs/api-reference/Instance"
markdown_url: "https://www.rosette.dev/docs/api-reference/Instance.md"
source_url: "https://github.com/PreFab-Photonics/rosette/blob/f086d7670645fd36c05362d696d442a2b2e74850/www/content/docs/api-reference/Instance.mdx"
docs_channel: "main"
docs_revision: "f086d7670645fd36c05362d696d442a2b2e74850"
---

# Instance

A cell placed at a specific location with optional transformations.

`Instance` is Rosette's only public abstraction for placing a `Cell`. It keeps
the cell definition and transform together, supports direct transformed-port
queries, and can represent either one placement or a compact GDS array.

Placement transforms must be finite and invertible, and uniform scale factors
must be finite and nonzero. Array dimensions are restricted to `[1, 32767]` in
Python and GDS; spacing values and displacement vectors must be finite. Zero
and negative finite spacings remain valid. Invalid builder inputs raise
`ValueError`; because instances are immutable, the original instance is left
unchanged.

```python
gc_in = gc_cell.at(0, 0)  # Returns Instance
port = gc_in.port("opt")  # Port transformed into world space
```

Instances can be added directly to cells and support transform chaining:

```python
gc = gc_cell.at(100, 50)
top.add_ref(gc)
```



> **Warning: Transform chaining order**
>
> Each chained call wraps the *outside* of the accumulated transform.
> The *first* call in the chain is applied first to the geometry.
>
> ```python
> # .at(10, 0).rotate(90) -> translate first, THEN rotate around origin
> # Point (0,0) becomes (10,0) then rotates to (0,10) -- NOT at (10,0)!
>
> # To rotate a component then place it at a specific position,
> # rotate first, then translate:
> inst = cell.at(0, 0).rotate(90).translate(25, 50)
> ```



## Attributes



### `cell`

```python
cell: Cell
```

The underlying cell definition.





### `transform`

```python
transform: Transform
```

The current transform applied to this instance.





### `array_shape`

```python
array_shape: tuple[int, int]
```

Grid dimensions `(columns, rows)` of this instance. Returns
`(1, 1)` for non-arrayed instances so the result is always
meaningful without checking whether `array()` was called.



## Methods



### `__init__`

```python
__init__(cell, transform=None) -> None
```

Create an Instance from a Cell and optional transform.

Typically you don't call this directly. Use `cell.at(x, y)` instead.



- **`cell`** (`Cell`)

  The cell definition.





- **`transform`** (`Transform | None`, default `None`)

  Optional transform. Defaults to identity. Before insertion into a parent cell,
  the transform is validated as finite, invertible, and representable as a GDS
  translation, rotation, reflection, and uniform nonzero scale.





**Returns:** `None`





### `translate`

```python
translate(dx, dy) -> Instance
```

Translate this instance in its parent's coordinate frame.

Returns a new Instance. Instances are immutable.



- **`dx`** (`float`)

  Finite X offset.





- **`dy`** (`float`)

  Finite Y offset.





**Returns:** `Instance`

A new Instance with updated transform.





### `rotate`

```python
rotate(angle_deg) -> Instance
```

Rotate by angle (in degrees, counter-clockwise).



- **`angle_deg`** (`float`)

  Rotation angle in degrees.





**Returns:** `Instance`

A new Instance with updated transform.





### `mirror_x`

```python
mirror_x() -> Instance
```

Mirror across X axis (flips Y coordinates).



**Returns:** `Instance`

A new Instance with updated transform.





### `mirror_y`

```python
mirror_y() -> Instance
```

Mirror across Y axis (flips X coordinates).



**Returns:** `Instance`

A new Instance with updated transform.





### `scale`

```python
scale(s) -> Instance
```

Scale uniformly.



- **`s`** (`float`)

  Finite, nonzero scale factor. Negative scale is valid.





**Returns:** `Instance`

A new Instance with updated transform.





### `array`

```python
array(columns, rows, col_spacing, row_spacing) -> Instance
```

Set array repetition (columns × rows rectangular grid with given pitch).

Creates a GDS AREF: a single compact array reference instead of
many individual references. In the viewer, the entire array is
selected and moved as one object.

For hex packings or any skewed / non-orthogonal grid, use
`array_vectors` instead.



> **Example**
>
> ```python
> # 10×5 array with 20 µm column pitch and 15 µm row pitch
> arr = unit_cell.at(0, 0).array(10, 5, 20.0, 15.0)
> top.add_ref(arr)
> ```





- **`columns`** (`int`)

  Number of columns (1 to 32767).





- **`rows`** (`int`)

  Number of rows (1 to 32767).





- **`col_spacing`** (`float`)

  Column pitch: center-to-center distance between adjacent copies
  along local +X, in µm. Must be finite; negative values place copies along
  local −X, and zero is valid.





- **`row_spacing`** (`float`)

  Row pitch: center-to-center distance between adjacent copies
  along local +Y, in µm. Must be finite; negative values place copies along
  local −Y, and zero is valid.





**Returns:** `Instance`

A new Instance with array repetition set.





### `array_vectors`

```python
array_vectors(columns, rows, col_vector, row_vector) -> Instance
```

Set array repetition from arbitrary column and row displacement
vectors.

Lower-level constructor supporting non-orthogonal lattices: hex
packings, skewed test arrays, etc. Vectors are defined in the
instance's local (pre-transform) coordinate space, in µm.



> **Example**
>
> ```python
> import math
> from rosette import Vector2
>
> # Hex packing (flat-top): adjacent rows staggered by pitch/2.
> pitch = 10.0
> arr = unit_cell.at(0, 0).array_vectors(
>     6, 4,
>     Vector2(pitch, 0.0),
>     Vector2(pitch / 2.0, pitch * math.sqrt(3.0) / 2.0),
> )
> top.add_ref(arr)
> ```





- **`columns`** (`int`)

  Number of columns (1 to 32767).





- **`rows`** (`int`)

  Number of rows (1 to 32767).





- **`col_vector`** (`Vector2`)

  Column displacement: the offset between copy `(c, r)` and
  `(c+1, r)`, in µm. Both components must be finite.





- **`row_vector`** (`Vector2`)

  Row displacement: the offset between copy `(c, r)` and
  `(c, r+1)`, in µm. Both components must be finite.





**Returns:** `Instance`

A new Instance with array repetition set.





### `port`

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

Get a transformed port from this instance.

The instance already knows its cell definition. Both position and direction
are fully transformed (translation, rotation, mirroring).

For arrayed instances, this returns the anchor copy's port. Use `copy()` or
`copies()` for per-copy ports.



> **Example**
>
> ```python
> gc = gc_cell.at(100, 50)
> opt_port = gc.port("opt")  # Transformed port position & direction
>
> # 180-degree rotation flips both position and direction:
> flipped = gc_cell.at(0, 0).rotate(180).translate(50, 0)
> p = flipped.port("opt")   # direction is now (-1, 0)
>
> # Arrayed: address a specific copy through ArrayCopy.
> bank = ring_cell.at(0, 0).array(8, 1, 30.0, 0.0)
> p = bank.copy(3, 0).port("in")
> ```





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

  Name of the port to retrieve.





**Returns:** `Port`

The anchor copy's port with position and direction transformed into world
space.





### `copy`

```python
copy(col, row) -> ArrayCopy
```

Return the array copy at `(col, row)` for direct per-copy queries.



- **`col`** (`int`)

  Zero-based grid column.





- **`row`** (`int`)

  Zero-based grid row.





**Returns:** `ArrayCopy`

A validated [`ArrayCopy`](/docs/api-reference/ArrayCopy) view. Invalid coordinates raise
`IndexError`; non-integer coordinates raise `TypeError`.





### `copies`

```python
copies() -> Iterator[ArrayCopy]
```

Iterate over the individual copies in this instance's array.

Yields one [`ArrayCopy`](/docs/api-reference/ArrayCopy) per grid position, in
column-major order (`col` varies fastest). Each yielded object
exposes `col`, `row`, a world-space `transform`, and a `port(name)`
convenience. These are read-only observational views, not independent
placements: add this `Instance` to the parent cell, not its copies. Iteration
does not mutate this instance or add any extra GDS references.

For a non-arrayed instance this yields exactly one copy at
`(col=0, row=0)`, so code written against `copies()` works
uniformly regardless of whether `array()` was called.



> **Example**
>
> ```python
> bank = ring_cell.at(0, 0).array(8, 1, 30.0, 0.0)
> top.add_ref(bank)                        # one AREF
>
> for copy in bank.copies():
>     top.add_text(
>         f"R{copy.col}",
>         copy.port("in").position,
>         layer=Layer(10, 0),
>     )
> ```





**Returns:** `Iterator[ArrayCopy]`

Iterator yielding one ArrayCopy per grid position.