# Search and slices

> Find the moments that matter across all your recordings, then freeze them into a reproducible slice.

Source: https://rayform.world/docs/guides/search-and-slices
Last updated: 2026-10-18
Status: Rayform is in private preview. APIs, formats and the SDK described here may change before general availability.

Search runs over every processed segment in your organisation. Filters combine with AND; list values within one filter combine with OR.

## Filters

| Filter | Example | Matches |
| --- | --- | --- |
| `site` | `"lab-2"` | Segments recorded at the site |
| `event` | `["grasp", "place"]` | Segments containing any of the interaction types |
| `object` | `"mug"` | Segments where an entity of that category appears |
| `text` | `"robot hands a cup to a person"` | Semantic match on the segment description |
| `near` | `{"point": [1.2, 0.4, 0.9], "radius_m": 0.5}` | Segments whose extent touches the region, in the site frame |
| `context` | `{"lighting": "low"}` | Context labels |
| `recorded` | `{"from": "2026-10-01", "to": "2026-10-15"}` | Recording time |
| `quality_min` | `{"psnr": 28}` | Segments at or above a quality score |
| `has_channels` | `["joints/position", "cam0/depth"]` | Segments carrying every listed channel |

## Searching

```python
results = client.segments.search(
    site=["lab-2", "lab-3"],
    event="grasp",
    object="mug",
    context={"lighting": "low"},
    quality_min={"psnr": 28},
)
print(results.total, "segments")
for seg in results[:3]:
    print(seg.id, seg.session, [e.type for e in seg.events()])
```

The same search over HTTP:

```bash
curl -G https://api.rayform.world/v1/segments \
  -H "Authorization: Bearer $RAYFORM_API_KEY" \
  --data-urlencode "site=lab-2,lab-3" \
  --data-urlencode "event=grasp" \
  --data-urlencode "object=mug" \
  --data-urlencode "context.lighting=low" \
  --data-urlencode "quality_min.psnr=28"
```

## Freezing a slice

A search result changes as you upload more data. Freeze it before you train:

```python
slice_ = client.slices.create(
    segments=results,                # or a query: query={"event": "grasp", ...}
    name="mug grasps, low light",
)
print(slice_.id, slice_.segment_count)
```

```text
slc_7c1e04aa 412
```

A slice records the exact segment versions it contains. Keep its ID with your experiment; loading it again returns the same bytes even after the sessions are reprocessed.

## Train and evaluation splits

Hold out whole sites or days, not random frames, so the evaluation measures generalisation:

```python
train = client.slices.create(query={"site": ["lab-2", "lab-3"], "event": "grasp"}, name="train")
evaluate = client.slices.create(query={"site": "lab-4", "event": "grasp"}, name="eval, unseen site")
```
