# Channels

> Learn the fundamentals of creating, retrieving, renaming, and deleting channels.

A [channel](https://docs.synnaxlabs.com/reference/concepts/channels) is a collection of time-ordered data. Channels store sensor readings, actuator commands, post-processed results, logs, or any other time-ordered data.

[Calculated channels](https://docs.synnaxlabs.com/reference/client/calculated-channels) are computed from other channels.

## Channel parameters

| Parameter                 | Type       | Default  | Description                                                                                                                           |
| ------------------------- | ---------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `name`                    | string     | Required | A human-readable name for the channel. This name is not guaranteed to be unique.                                                      |
| `data_type`               | `DataType` | Required | The data type of the samples stored in the channel (e.g., `DataType.FLOAT32`, `DataType.TIMESTAMP`).                                  |
| `is_index`                | boolean    | `False`  | Set to `True` if the channel is an index channel, `False` otherwise. Index channels must have a data type of `DataType.TIMESTAMP`.    |
| `index`                   | number     | `0`      | The key of the index channel that this channel is associated with. Not required for index channels.                                   |
| `virtual`                 | boolean    | `False`  | Set to `True` if the channel is virtual. Virtual channels do not store data in the database and are used for streaming purposes only. |
| `retrieve_if_name_exists` | boolean    | `False`  | If `True`, retrieves the channel if one with the same name already exists instead of creating a duplicate.                            |

## Create channels

Use the `create` method to create one channel or many channels. Creating many channels in a single call is more efficient than creating them individually. The call is atomic, so Synnax creates all of the channels or none of them.

> You must create an index channel before the non-virtual data channels that use it.

**Console**

Create a channel from the [channels toolbar](https://docs.synnaxlabs.com/reference/console/ui-overview#channels), or with the “Create channel” command in the [command palette](https://docs.synnaxlabs.com/reference/console/ui-overview#search-and-command-palette).

[](https://synnax.nyc3.cdn.digitaloceanspaces.com/docs/client/channels/create-dark.mp4#t=0.001)

**Python**

```python
import numpy as np, synnax as sy

time_index = client.channels.create(
    name="time",
    data_type=sy.DataType.TIMESTAMP,
    is_index=True,
)

sensor_one = sy.Channel(
    name="sensor_one",
    data_type=sy.DataType.FLOAT32, # Use Synnax datatypes
    index=time_index.key,
)

sensor_two = sy.Channel(
    name="sensor_two",
    data_type=np.float32, # Or numpy
    index=time_index.key,
)

sensor_three = sy.Channel(
    name="sensor_three",
    data_type="float32", # Or strings
    index=time_index.key,
)

data_channels = client.channels.create(
    [sensor_one, sensor_two, sensor_three],
    retrieve_if_name_exists=True, # Optional
)
```

> `retrieve_if_name_exists` returns the existing channel if the name already exists.

**TypeScript**

```typescript
import { Channel } from "@synnaxlabs/client";

const timeIndexChannel = await client.channels.create({
  name: "time",
  dataType: DataType.TIMESTAMP,
  isIndex: true,
});

const sensorOne = new Channel({
  name: "sensor_one",
  dataType: DataType.FLOAT32,
  index: timeIndexChannel.key,
});

const sensorTwo = new Channel({
  name: "sensor_two",
  dataType: DataType.FLOAT32,
  index: timeIndexChannel.key,
});

const sensorThree = new Channel({
  name: "sensor_three",
  dataType: DataType.FLOAT32,
  index: timeIndexChannel.key,
});

const sensors = await client.channels.create(
  [sensorOne, sensorTwo, sensorThree],
  { retrieveIfNameExists: true }, // optional
);
```

> `retrieveIfNameExists` returns the existing channel if the name already exists.

## Retrieve channels

To retrieve channel(s), pass the channel name(s) or key(s) to the `retrieve` method. Retrieving by key is faster than retrieving by name, and is recommended whenever possible.

**Python**

```python
# One channel, by key or by name
my_sensor = client.channels.retrieve(my_sensor.key)
my_sensor = client.channels.retrieve("my_sensor")

# Many channels, by key or by name
my_channels = client.channels.retrieve([sensor_one.key, sensor_two.key])
my_channels = client.channels.retrieve(["sensor_one", "sensor_two"])

# This won't work!
my_channels = client.channels.retrieve(["sensor_one", sensor_two.key])
```

**TypeScript**

```typescript
// One channel, by key or by name
const tempChannel = await client.channels.retrieve(tempChannel.key);
const tempChannel = await client.channels.retrieve("my_temp_sensor");

// Many channels, by key or by name
const my_channels = await client.channels.retrieve([sensorOne.key, sensorTwo.key]);
const my_channels = await client.channels.retrieve(["sensor_one", "sensor_two"]);

// This won't work!
const my_channels = await client.channels.retrieve(["sensor_one", sensor_two.key]);
```

If you pass one key or name, the client raises a `NotFoundError` when no channel matches and a `MultipleFoundError` when more than one channel matches. If you pass a list, the client raises no error and leaves missing channels out of the results.

> Channels can also be retrieved using [ranges](https://docs.synnaxlabs.com/reference/client/ranges#read-from-a-range).

### Regular expressions

Channels can be retrieved using regular expression patterns. The Core treats any name starting with `^` or ending with `$` as a regex pattern.

**Python**

```python
# Returns list[sy.Channel]
sensor_channels = client.channels.retrieve(["^sensor.*"])
```

**TypeScript**

```typescript
// Returns Channel[]
const sensorChannels = await client.channels.retrieve(["^sensor.*"]);
```

If you expect multiple channels to match the pattern, you must pass in a list to the `retrieve` method, otherwise the client will raise a `MultipleFoundError`.

## Rename channels

**Console**

[](https://synnax.nyc3.cdn.digitaloceanspaces.com/docs/client/channels/rename-dark.mp4#t=0.001)

**Python**

Rename channels by key with `channels.rename`, or call `rename` on a channel object.

```python
# Rename an already existing channel
data_channel.rename("new_name")

# Renaming single channel
client.channels.rename(data_channel.key, "new_name")

# Renaming multiple channels
client.channels.rename([channel_one.key, channel_two.key], ["name_one", "name_two"])
```

**TypeScript**

Rename channels by key with `channels.rename`.

```typescript
// Renaming single channel
await client.channels.rename(dataChannel.key, "new_name");

// Renaming multiple channels
await client.channels.rename(
  [channelOne.key, channelTwo.key],
  ["name_one", "name_two"],
);
```

## Delete channels

> Deleting a channel will also delete all of the data stored for that channel in a Synnax Core. This is a permanent operation that cannot be undone. Be careful!

**Console**

[](https://synnax.nyc3.cdn.digitaloceanspaces.com/docs/client/channels/delete-dark.mp4#t=0.001)

**Python**

Use the `channels.delete` method. `delete` does not raise an error if a channel is not found, so it is safe to call again. Deleting by name deletes **all** channels with that name.

```python
# Delete by name
client.channels.delete("my_sensor")

# Delete multiple by name
client.channels.delete(["sensor_one", "sensor_two"])

# Delete by key
client.channels.delete(sensor_three.key)

# Delete multiple by key
client.channels.delete([sensor_one.key, sensor_two.key, sensor_three.key])
```

**TypeScript**

Use the `channels.delete` method. `delete` does not raise an error if a channel is not found, so it is safe to call again. Deleting by name deletes **all** channels with that name.

```typescript
// Delete by name
await client.channels.delete("my_sensor");

// Delete multiple by name
await client.channels.delete(["sensor_one", "sensor_two"]);

// Delete by key
await client.channels.delete(sensor_three.key);

// Delete multiple by key
await client.channels.delete([sensor_one.key, sensor_two.key, sensor_three.key]);
```

## Channel aliases

Ranges allow you to define [aliases](https://docs.synnaxlabs.com/reference/concepts/ranges#channel-aliases) for channels that only apply within that range’s context. This is useful when you want to give a channel a more descriptive name for a specific test or operation.

**Console**

[](https://synnax.nyc3.cdn.digitaloceanspaces.com/docs/client/channels/alias-dark.mp4#t=0.001)

The alias is only shown while its range is active, and only in your own Console.

**Python**

```python
burst_test = client.ranges.retrieve(name="Oct 10 Burst Test")

# Set an alias for a channel
burst_test.set_alias("daq_analog_input_1", "tank_pressure")

# Access the channel using its alias
burst_test.tank_pressure

# List all aliases on the range
aliases = burst_test.list_aliases()

# Delete an alias
burst_test.delete_alias(channel_key)
```

**TypeScript**

```typescript
const burstTest = await client.ranges.retrieve("Oct 10 Burst Test");

// Set an alias for a channel
await burstTest.setAlias("daq_analog_input_1", "tank_pressure");

// Resolve an alias back to its channel key
const channelKey = await burstTest.resolveAlias("tank_pressure");

// List all aliases on the range
const aliases = await burstTest.listAliases();

// Delete an alias
await burstTest.deleteAlias(channelKey);
```

> Aliases are only valid within the context of a particular range. If you try to access an aliased channel outside of the range, Synnax will not be able to find it.
