Ranges
Organizing telemetry data with time-based ranges and metadata.
Ranges are named time intervals that organize telemetry into tests, runs, and events, and carry metadata about them.
Range Parameters
TypeScript does not support conditional range creation.
Create a Range
Console
Python
TypeScript
Create a range via the toolbar, Command Palette, or a plot region.
To create a range, use the client.ranges.create method:
import synnax as sy
# Create a range with a specific time interval
start = sy.TimeStamp("2023-02-12 12:30:00")
end = sy.TimeStamp("2023-02-12 14:30:00")
my_range = client.ranges.create(
name="My Range",
time_range=sy.TimeRange(start=start, end=end),
retrieve_if_name_exists=True, # Return the existing range instead of a duplicate
)
# Or use the convenience span_range method
start = sy.TimeStamp.now()
my_range = client.ranges.create(
name="My Range",
time_range=start.span_range(sy.TimeSpan.HOUR * 2),
)To create a range, use the client.ranges.create method:
import { TimeRange, TimeSpan, TimeStamp } from "@synnaxlabs/client";
// Create a range with a specific time interval
const start = new TimeStamp("2023-02-12 12:30:00");
const end = new TimeStamp("2023-02-12 14:30:00");
const range = await client.ranges.create({
name: "My Range",
timeRange: new TimeRange(start, end),
// No retrieveIfNameExists option in TypeScript
});
// Or use the convenience span method
const start = TimeStamp.now();
const range = await client.ranges.create({
name: "My Range",
timeRange: start.span(TimeSpan.hours(2)),
});Create Child Ranges
Child ranges segment a range into smaller intervals.
Console
Python
TypeScript
Set the parent range field in the creation dialog, or click Add Child Range in the
range overview page.
The most convenient way is the create_child_range shorthand on a parent Range:
child_range = parent_range.create_child_range(
name="My Child Range",
time_range=sy.TimeRange(start=start, end=end),
)You can also pass the parent Range directly to client.ranges.create via the parent
keyword. This form works for one or many children:
child_range = client.ranges.create(
name="My Child Range",
time_range=sy.TimeRange(start=start, end=end),
parent=parent_range,
)Or set parent on the Range itself when constructing it — useful when batching:
client.ranges.create([
sy.Range(name="Child A", time_range=tr_a, parent=parent_range),
sy.Range(name="Child B", time_range=tr_b, parent=parent_range),
])Pass the parent Range directly on the child being created. This form works for one or
many children:
const childRange = await client.ranges.create({
name: "My Child Range",
timeRange: new TimeRange(start, end),
parent: parentRange,
});Or set parent on each range when batching:
await client.ranges.create([
{ name: "Child A", timeRange: trA, parent: parentRange },
{ name: "Child B", timeRange: trB, parent: parentRange },
]);Retrieve Ranges
Single
Retrieve a range by its name or key. Synnax will raise a NotFoundError if the range
does not exist, and a MultipleFoundError if multiple ranges with the given name exist.
Python
TypeScript
# By name
my_range = client.ranges.retrieve(name="My Range")
# By key
my_range = client.ranges.retrieve(key=my_range.key)// By name
const myRange = await client.ranges.retrieve("My Range");
// By key
const myRange = await client.ranges.retrieve(myRange.key);Multiple
Retrieve multiple ranges by passing a list of names or keys. When retrieving multiple ranges, Synnax will not raise an error if a range cannot be found. Instead, the missing range will be omitted from the returned list.
Python
TypeScript
# By name
my_ranges = client.ranges.retrieve(names=["My Range", "My Other Range"])
# By key
my_ranges = client.ranges.retrieve(keys=[my_range.key, my_other_range.key])
# By search term
ranges = client.ranges.search("Hotfire")// By name
const myRanges = await client.ranges.retrieve(["My Range", "My Other Range"]);
// By key
const myRanges = await client.ranges.retrieve([myRange.key, myOtherRange.key]);
// By search term
const ranges = await client.ranges.retrieve({ searchTerm: "Hotfire" });Child
If a range has child ranges, you can retrieve them directly from the parent range.
Python
TypeScript
child_ranges = my_range.childrenconst childRanges = await myRange.retrieveChildren();Parent
Navigate up the hierarchy by retrieving a child range’s parent.
Python
TypeScript
Retrieving a parent range is not directly supported in Python.
const parentRange = await myRange.retrieveParent();Update a Range
To update an existing range, use the same client.ranges.create method but specify the
key of the range to update. This allows modification of the range’s name, time range,
or color.
Python
TypeScript
import synnax as sy
# First, retrieve the range you want to update
my_range = client.ranges.retrieve(name="My Range")
# Update the range by providing its key and new values
updated_range = client.ranges.create(
key=my_range.key, # Specify the key to update existing range
name="My Updated Range", # New name
time_range=sy.TimeRange(
start=sy.TimeStamp("2023-02-12 13:00:00"),
end=sy.TimeStamp("2023-02-12 15:00:00"),
),
color="#00FF00", # New color
)import { TimeRange, TimeStamp } from "@synnaxlabs/client";
// First, retrieve the range you want to update
const myRange = await client.ranges.retrieve("My Range");
// Update the range by providing its key and new values
const updatedRange = await client.ranges.create({
key: myRange.key, // Specify the key to update existing range
name: "My Updated Range", // New name
timeRange: new TimeRange(
new TimeStamp("2023-02-12 13:00:00"),
new TimeStamp("2023-02-12 15:00:00"),
),
color: "#00FF00", // New color
});When updating a range, you must provide the key parameter. If you provide a key that
doesn’t exist, Synnax will create a new range with that key instead of raising an error.
Updating a range will completely replace its properties. Make sure to include all the properties you want to keep, not just the ones you want to change.
Metadata
Ranges can store metadata as key-value pairs. This is useful for attaching information like test configuration parameters, numeric results, or part numbers.
All metadata values are stored as strings. It’s up to you to correctly cast the values to the appropriate type.
Set
Console
Python
TypeScript
my_range = client.ranges.retrieve(name="My Range")
# Set a single key/value pair
my_range.meta_data.set("part_number", "12345")
# Another way to set a single key/value pair
my_range.meta_data["part_number"] = "12345"
# Set multiple key/value pairs
my_range.meta_data.set({
"part_number": "12345",
"test_configuration": "Test 1",
"test_result": "123.45",
})const myRange = await client.ranges.retrieve("My Range");
// Set a single key/value pair
await myRange.kv.set("part_number", "12345");
// TypeScript only supports the set() method
// (no bracket syntax)
// Set multiple key/value pairs
await myRange.kv.set({
part_number: "12345",
test_configuration: "Test 1",
test_result: "123.45",
});Get
Python
TypeScript
my_range = client.ranges.retrieve(name="My Range")
# Retrieve a single key
part_number = my_range.meta_data["part_number"] # Or use .get("key")
# Retrieve multiple keys
metadata = my_range.meta_data.get(["part_number", "test_configuration"])
# List all metadata
all_metadata = my_range.meta_data.get([])const myRange = await client.ranges.retrieve("My Range");
// Retrieve a single key
const partNumber = await myRange.kv.get("part_number");
// Retrieve multiple keys
const metadata = await myRange.kv.get(["part_number", "test_configuration"]);
// List all metadata
const allMetadata = await myRange.kv.list();Delete
Python
TypeScript
my_range = client.ranges.retrieve(name="My Range")
# Delete a single key
del my_range.meta_data["part_number"] # Or use .delete("key")
# Delete multiple keys
my_range.meta_data.delete(["part_number", "test_configuration"])const myRange = await client.ranges.retrieve("My Range");
// Delete a single key
await myRange.kv.delete("part_number");
// Delete multiple keys
await myRange.kv.delete(["part_number", "test_configuration"]);Labels
Labels categorize and filter ranges.
Console
Python
TypeScript
my_range = client.ranges.retrieve(name="My Range")
# List the labels on the range
for label in my_range.labels:
print(label.name)const myRange = await client.ranges.retrieve("My Range");
// Create a label
const label = await client.labels.create({ name: "Hotfire", color: "#FF0000" });
// Add the label to the range
await myRange.addLabel(label.key);
// List the labels on the range
const labels = await myRange.retrieveLabels();
// Remove the label from the range
await myRange.removeLabel(label.key);Read from a Range
Ranges provide a convenient way to read data without specifying exact time boundaries. Once you have a range, you can read channel data directly from it.
Python
TypeScript
my_range = client.ranges.retrieve("My Interesting Test")
# Read data from a single channel
data = my_range.my_precise_tc.read()
# Read data from multiple channels
frame = my_range.read(["my_precise_tc", "my_precise_pt"])
# Python allows direct use of channel names as properties
celsius = my_range.my_precise_tc - 273.15const myRange = await client.ranges.retrieve("My Interesting Test");
// Read data from a single channel
const data = await myRange.read("my_precise_tc");
// Read data from multiple channels
const frame = await myRange.read(["my_precise_tc", "my_precise_pt"]);
// Convert from Kelvin to Celsius
const celsius = data.map((v) => v - 273.15);Read by Alias
Once you’ve set an alias, you can access the channel using that alias.
Python
TypeScript
Python allows you to access aliased channels directly as properties:
burst_test = client.ranges.retrieve(name="Oct 10 Burst Test")
# Access by alias as a property
data = burst_test.tank_pressure
# Or use dictionary syntax
data = burst_test["tank_pressure"]
# Regex returns a list of matching channels
tank_channels = burst_test["^tank"]TypeScript requires resolving the alias to a channel key first:
const burstTest = await client.ranges.retrieve("Oct 10 Burst Test");
// Resolve alias to channel key, then read
const channelKey = await burstTest.resolveAlias("tank_pressure");
// Then read by channel key
const data = await burstTest.read(channelKey);
// Or read directly by original channel name
const data2 = await burstTest.read("daq_analog_input_1");Write to a Range
Writing to a range removes the burden of needing to correctly align the timestamps for different channels. The write will assume that the timestamp of the first sample is the start of the range.
Python
TypeScript
my_range = client.ranges.retrieve("My Interesting Test")
temperatures = [55, 55.1, 55.7, 57.2, 58.1, 58.9, 59.1, 59.2, 59.3]
pressures = [100, 100.1, 100.7, 102.2, 103.1, 103.9, 104.1, 104.2, 104.3]
my_range.write({
"my_precise_tc": temperatures,
"my_precise_pt": pressures,
})Delete a Range
Console
Python
TypeScript
Delete a range by passing its key to the client.ranges.delete method.
# Delete a single range
client.ranges.delete(my_range.key)
# Delete multiple ranges
client.ranges.delete([my_range.key, my_other_range.key])Delete a range by passing its key to the client.ranges.delete method.
// Delete a single range
await client.ranges.delete(myRange.key);
// Delete multiple ranges
await client.ranges.delete([myRange.key, myOtherRange.key]);