s6.utils package¶
Submodules¶
s6.utils.bounding_box_selector module¶
- class s6.utils.bounding_box_selector.BoundingBoxSelector(color=(0, 255, 0), border_width=2, show_text=True)¶
Bases:
objectInteractive bounding box selector using OpenCV window.
Example
selector = BoundingBoxSelector(color=(0,255,0), border_width=2, show_text=True) bbox2d = selector.select(image)
- Parameters:
color – BGR tuple for rectangle color.
border_width – Thickness of the rectangle border.
show_text – Whether to display x,y,w,h text on the rectangle.
- select(image: ndarray, window_name: str = 'Select BoundingBox') BoundingBox2D¶
Show image in a window and let user draw a bounding box by dragging the mouse. Press Enter to confirm selection and close the window.
- Parameters:
image – The image array to select bounding box from.
window_name – The name of the OpenCV window.
- Returns:
The selected bounding box.
- Return type:
s6.utils.camera_identifier module¶
Rule‑based camera identifier using simple IR marker rectangular ROIs.
Provides CameraIDIdentifier to determine camera IDs by checking
predefined regions for bright markers in grayscale frames. A small OpenCV UI
in main() helps author a JSON config of ROIs and a detection threshold.
The expected input frames are 8‑bit single‑channel images with intensity
values in [0, 255]. Regions are rectangles and may be marked
as negative (region must not contain a marker).
- class s6.utils.camera_identifier.CameraIDIdentifier(rule_config, threshold=250)¶
Bases:
objectIdentify camera IDs by testing configured regions for bright markers.
The identifier loads a
rule_configmapping camera IDs to a list of region specs. Each spec describes a rectangle withbbox=(x1, y1, x2, y2), plus an optionalnegateflag: -negate=False→ region must contain a marker (mean > threshold) -negate=True→ region must not contain a marker (mean <= threshold)- Parameters:
rule_config (dict[int, list[dict]]) – Mapping from camera ID to a list of region specs. See above for keys.
threshold (float, default 250) – Mean intensity threshold in
[0, 255]used to decide if a marker is present inside a region.
- static from_json(config_path: str = 'configs/camera_ident.config.json') CameraIDIdentifier¶
Create an identifier from a JSON configuration file.
- Parameters:
config_path (str, default "configs/camera_ident.config.json") – Path to the JSON config. Must contain
thresholdandrule_configkeys.- Returns:
Instance configured with the given rules and threshold.
- Return type:
- Raises:
FileNotFoundError – If the file does not exist.
json.JSONDecodeError – If the file is not valid JSON.
- static load_default() CameraIDIdentifier¶
Load the default config from
configs/camera_ident.config.json.
- order(images: list[ndarray], erase_marker_region: bool = False) dict¶
Identify camera IDs and return a mapping from ID to image.
The input order is left unchanged. For each image, the first camera ID whose region specs are satisfied is assigned. If
erase_marker_regionis True, positive regions for matched specs are zeroed in‑place.- Parameters:
images (list[ndarray]) – Grayscale frames of shape
(H, W).erase_marker_region (bool, default False) – If True, zero out detected positive regions for matched IDs.
- Returns:
Mapping of camera ID to its corresponding image.
- Return type:
dict[int, ndarray]
- s6.utils.camera_identifier.main()¶
Interactive ROI authoring tool for camera identification.
Connects to a running
s6.utils.streamer.VideoStreamClient, lets users draw rectangle ROIs per camera role via mouse, and writesconfigs/camera_ident.config.jsonwiththresholdandrule_config. Use keys: ‘m’ toggle negate, ‘r’ cycle role, ‘d’ change displayed camera, ‘c’ clear ROIs, ENTER/SPACE to finish.
s6.utils.camera_identifier_aruco module¶
Camera ID identifier using ArUco marker presence within rectangular regions.
This module provides CameraIDIdentifierAruco, a drop-in alternative to
the intensity-ROI based s6.utils.camera_identifier.CameraIDIdentifier.
Instead of thresholding brightness, it detects ArUco markers from the
cv2.aruco.DICT_4X4_50 dictionary and decides camera IDs by checking whether
detected marker positions fall inside user-configured rectangular regions.
Each configured rectangular region can be positive (must contain at least one
detected ArUco center) or negative (must contain none) via negate. Cameras
without any defined regions are treated as fallbacks and are assigned after
region-constrained cameras are matched (useful when only some views contain
ArUco markers).
The expected input frames are 8-bit single-channel images (H, W). The interface
mirrors CameraIDIdentifier: from_json, load_default and order.
- class s6.utils.camera_identifier_aruco.CameraIDIdentifierAruco(rule_config: Dict[Any, List[Dict[str, Any]]], dictionary_id: int | None = None)¶
Bases:
objectIdentify camera IDs using ArUco detections within configured regions.
- Parameters:
rule_config (dict[str | int, list[dict]]) – Mapping from camera ID (e.g., “R”, “B”, “L” or integer) to a list of rectangular region specs of the form {“type”: “rect”, “bbox”: (x1, y1, x2, y2), “negate”: bool}.
dictionary_id (int, default cv2.aruco.DICT_4X4_50) – ArUco dictionary used for detection.
- static from_json(config_path: str = 'configs/camera_ident.config.json', dictionary_id: int | None = None) CameraIDIdentifierAruco¶
Create an identifier from a JSON configuration file.
The JSON is expected to contain a top-level
rule_configmapping camera IDs to ROI specs (see class docstring). Anythresholdvalue present in the file is ignored.
- static load_default() CameraIDIdentifierAruco¶
Load default config from
configs/camera_ident.config.json.Reuses the same ROI config file as the intensity-based identifier. The
thresholdentry is ignored.
- order(images: List[ndarray]) Dict[Any, ndarray]¶
Identify camera IDs for
imagesand return mapping id -> image.Cameras with defined rectangular regions are matched first: all regions for a camera must contain at least one marker. Remaining images are then assigned to cameras without defined regions (fallbacks). If
erase_marker_regionis True, detected markers in matched regions are erased in-place by filling the marker polygon.
s6.utils.cleartext module¶
- class s6.utils.cleartext.ClearText(font='/Users/tim/Workspace/sense-core/src/s6/utils/fonts/arialbd.ttf', fontsize=24, fontsize_alt=16, **kwargs)¶
Bases:
object- DEFAULT_FONT = '/Users/tim/Workspace/sense-core/src/s6/utils/fonts/arialbd.ttf'¶
- text_block(image, position, text, bgra=(255, 255, 255, 255), alt=False, normalized_position=False, background=(255, 255, 255), blending_opacity=1.0)¶
s6.utils.datapipe module¶
Torch-compatible Dataset around StructuredDataset.
Provides datakey-based selection of nested fields and optional balancing across one or more StructuredDataset directories.
Example
Suppose you have a StructuredDataset stored in “./temp” with samples like:
{“image”: <np.ndarray>, “label”: 0} {“image”: <np.ndarray>, “label”: 1}
You can wrap it as a PyTorch Dataset:
from s6.utils.datapipe import StructuredDatasetTorch
from torch.utils.data import DataLoader
dataset = StructuredDatasetTorch(
"./temp", # path to one or more base dirs
datakeys=["image", "label"],
balance=False, # no balancing across dirs
shuffle=True, # shuffle entries
seed=42, # reproducible
)
loader = DataLoader(dataset, batch_size=8, shuffle=False)
for images, labels in loader:
# images: torch.Tensor of shape [8, ...]
# labels: torch.Tensor of shape [8]
...
- class s6.utils.datapipe.StructuredDatasetTorch(dataset_dirs: str | List[str], datakeys: List[str], balance: bool = True, shuffle: bool = True, seed: int | None = None)¶
Bases:
DatasetA torch.utils.data.Dataset wrapper over one or more StructuredDataset directories.
It extracts specific nested fields (via datakey strings) and returns them as torch.Tensor when possible, falling back to Python values otherwise.
Supports balancing across multiple StructuredDataset sources and initial shuffling.
Nested fields are specified with dot-list syntax, e.g.: ‘a.b[0].c’ → sample[‘a’][‘b’][0][‘c’] or getattr if it is a model.
- Parameters:
dataset_dirs (str or List[str]) – Path or list of paths to one or more StructuredDataset directories.
datakeys (List[str]) – List of datakey strings indicating which fields to extract per sample.
balance (bool, default=True) – If True and multiple dirs are given, undersample larger datasets to match the smallest one. If False, include all samples sequentially.
shuffle (bool, default=True) – If True, shuffle the index mapping once upon initialization.
seed (Optional[int], default=None) – Optional random seed for reproducible shuffling.
- Return type:
Single torch.Tensor if only one datakey is provided, else a tuple of Tensors/values.
Example
from s6.utils.datapipe import StructuredDatasetTorch
# Wrap a single StructuredDataset directory and extract ‘image’ & ‘label’ ds = StructuredDatasetTorch(
‘./temp’, datakeys=[‘image’, ‘label’], balance=False, shuffle=True, seed=0,
) # Now ds[i] → (image_tensor, label_tensor) img, lbl = ds[0] print(img.shape, lbl.item())
- property line_data: List[dict]¶
List of raw JSON records (unrestored) for all underlying StructuredDatasets.
s6.utils.datastore module¶
Directory‑backed storage for heterogeneous samples.
This module provides StructuredDataset, a minimal container that
stores one sample per line in data.jsonl under a given directory. Larger
2D/3D NumPy arrays can be saved as JPEG images on disk and referenced from the
JSON record, and Pydantic models are serialized with enough metadata to be
reconstructed on read.
Intended for quick experiments and logs — not a database. Uses Pillow for image I/O and dynamic imports to rebuild Pydantic models when possible.
- class s6.utils.datastore.StructuredDataset(base_dir: str, min_size: int = 32)¶
Bases:
objectSmall dataset that reads/writes heterogeneous samples in a folder.
Each call to
write()appends a JSON object todata.jsonl. NumPy arrays of shape(H, W[, C])withmin(H, W) >= min_sizeare stored as JPEGs; smaller arrays or higher‑dimensional arrays are embedded as JSON lists with shape hints. Pydantic models are stored with their module and class for later reconstruction.- Parameters:
base_dir (str) – Directory that holds
data.jsonland any image files.min_size (int, default 32) – Minimum height/width required to store arrays as images.
- jsonl_path¶
Full path to the backing JSON Lines file.
- Type:
str
- line_data¶
In‑memory cache of parsed JSON lines.
- Type:
list[dict]
- delete_one(idx: int) None¶
Delete a sample by index and remove any referenced images.
- Parameters:
idx (int) – Sample index; negative values are supported (
-1is the last).- Raises:
IndexError – If the dataset is empty or the index is out of range.
- property line_data: List[dict]¶
Read‑only list of in‑memory JSON records.
- write(data: Any)¶
Append a single sample to the dataset.
- Parameters:
data (Any) – Heterogeneous structure composed of dicts/lists/scalars, NumPy arrays, or Pydantic models. Arrays may be saved as images based on
min_size.
s6.utils.devices module¶
s6.utils.entrypoint_loader module¶
Dynamic entrypoint discovery and dispatch for Sense Core apps.
This utility discovers Python modules and shell scripts under a package root
and dispatches subcommands to either module.main() or an executable script.
It also provides --list to enumerate available commands or functions within
modules. The default root is s6.app.
- class s6.utils.entrypoint_loader.EntryPointLoader(module_prefix='s6.app', exclude_prefixes=None)¶
Bases:
objectDiscover and invoke subcommands under a package tree.
- Parameters:
module_prefix (str, default "s6.app") – Dotted package path that serves as the root for discovery.
exclude_prefixes (list[str] | None) – Optional list of filename prefixes to exclude when listing commands. The comparison is applied to the bare module name (without
.py).
- get_module_functions(module)¶
Return public callables defined on
module.- Parameters:
module (ModuleType) – Imported Python module.
- Returns:
Names of callables that do not start with
__.- Return type:
list[str]
- list_commands(directory)¶
List available commands and subdirectories under
directory.- Parameters:
directory (str) – Filesystem path to scan.
- Returns:
Two lists: module/script basenames and subdirectory names.
- Return type:
tuple[list[str], list[str]]
- load_module(module_name)¶
Dynamically import a module by name.
- Parameters:
module_name (str) – Fully-qualified Python module name.
- Returns:
The imported module object.
- Return type:
ModuleType
- run()¶
Parse CLI args and dispatch to a module or script.
s6.utils.filters module¶
Generic temporal smoothing filters.
This module provides a lightweight sliding-window smoother that accepts lists/tuples/arrays of arbitrary length and returns a moving-average value. An optional acceptance function allows rejecting outlier measurements before they are added to the window, which is useful for stabilizing detectors.
- class s6.utils.filters.TupleSmoother(window: int = 3, accept_fn: ~typing.Callable[[~numpy.ndarray, ~numpy.ndarray], bool] | None = None, dtype: ~numpy.dtype = <class 'numpy.float64'>)¶
Bases:
objectSliding-window smoother for numeric tuples/lists/arrays.
Accepts 1D numeric sequences (list/tuple/ndarray) of any length.
Maintains a fixed-size history of accepted measurements.
Returns the moving average over the history as the smoothed value.
Supports an optional
accept_fn(new, prev) -> boolpredicate to reject outliers before they are incorporated into the history.
- property has_value: bool¶
- property history: List[ndarray]¶
Return a list copy of internal history arrays (oldest..newest).
- reset() None¶
- update(value: Sequence[float]) Tuple[ndarray, bool]¶
Push a new measurement and return (smoothed_value, accepted).
The measurement is only appended to history if
accept_fnallows it (or if there is no prior history). The smoothed value is the moving average over the current history window.
- property value: ndarray | None¶
Return the current smoothed value (moving average) or None if empty.
- property window: int¶
s6.utils.infra module¶
Infrastructure gateway server for database and file operations.
Provides a Gateway class that encapsulates both the FastAPI application (with DB CRUD, aggregation, and file-proxy endpoints) and a matching Python client for easy use.
- class s6.utils.infra.Gateway(config: Any)¶
Bases:
object- property app: FastAPI¶
Build and return the FastAPI application with DB CRUD and file proxy routes.
- property client: GatewayClient¶
Return a Python client for this gateway using the same routes for DB and files.
- static connect(config: Any)¶
Context manager that launches a local Gateway server on an ephemeral port and yields a GatewayClient configured to localhost on that port.
- Usage:
- with Gateway.connect(config) as client:
# use client to call the local server
- class s6.utils.infra.GatewayClient(gateway: Gateway, base_url: str | None = None)¶
Bases:
object- aggregate(pipeline: list, collection: str | None = None)¶
Generator that streams documents from an aggregation pipeline via WebSocket on the (default) collection.
- create(payload: Dict[str, Any], collection: str | None = None) str¶
Insert a document into the (default) collection and return its ID.
- delete(doc_id: str, collection: str | None = None) None¶
Delete a single document by ID from the (default) collection.
- delete_file(filename: str) None¶
- delete_many(flt: Dict[str, Any], collection: str | None = None) int¶
Delete multiple documents in the (default) collection via a JSON filter. Returns the number of documents deleted.
- download(doc_id: str, collection: str | None = None) Any¶
Fetch and reconstruct a nested structure previously uploaded.
- download_file(filename: str) bytes¶
- get(doc_id: str, collection: str | None = None) Dict[str, Any]¶
Fetch a single document by ID from the (default) collection.
- post_file(filename: str, fobj: Any, content_type: str) Any¶
- query(flt: Dict[str, Any], collection: str | None = None) Any¶
Query documents in the (default) collection via a JSON filter.
- update(doc_id: str, payload: Dict[str, Any], collection: str | None = None) int¶
Update a document by ID in the (default) collection and return count.
- upload(obj: Dict[str, Any], collection: str | None = None, **kwargs) str¶
Serialize and upload a nested structure to the (default) collection. Returns the inserted document ID. Additional top-level kwargs are merged into the stored record.
- upload_file(filename: str, fobj: Any, content_type: str) Any¶
s6.utils.profiler module¶
Profiling utilities for Sense Core.
Collects lightweight timing information and exports it in two formats:
Chrome/Perfetto Trace Events (via
s6.schema.trace.TraceEvent) for interactive timeline inspection.A human‑readable “frames” export that groups nested traces per execution frame and is convenient for offline statistics.
The primary surface is Profiler, which offers context managers for
scoped timings (trace), a frame context (frame), a function decorator,
and exporters. See process_frames() for computing summary stats from the
frames export.
- class s6.utils.profiler.Profiler¶
Bases:
objectSimple profiler with nested scopes and frame grouping.
trace(name, remark=None)creates a timed scope; users can attach metadata while inside the scope.frame()groups all nested traces to represent a single execution cycle (e.g., a render or processing frame).trace_functiondecorates a callable to measure its runtime.exportwritesChrome Trace Events.export_metricswrites a combined JSON with session metadata, optional per-scope remarks, and a frames list suitable for offline analysis.
The profiler keeps a global event list and a per‑frame buffer when a frame context is active. Timestamps are relative to process start and exported in microseconds for Chrome traces and milliseconds in the human‑readable view.
- classmethod disable_logging()¶
Disable verbose debug logging for scope durations.
- classmethod enable_logging()¶
Enable verbose debug logging for scope durations.
- classmethod export(filename='trace.json')¶
Write Chrome Trace Events to
filename.- Parameters:
filename (str, default "trace.json") – Output path for the Chrome/Perfetto trace JSON.
- classmethod export_metrics(filename: str)¶
Export session‑level data and per‑frame traces as JSON.
The output contains: -
metadata: Session metadata dict attached viametadata(). -remarks: Optional mapping from full scope path to remark string. -frames: A list where each frame has keysframe_id,start_time_ms,end_time_ms,duration_ms, andtraces.- Parameters:
filename (str) – Path to the output file.
- classmethod frame()¶
Group nested traces into a single execution frame.
All trace events generated while inside the context are captured and exported in the human‑readable frames list by
Profiler.export_metrics().- Returns:
A context manager representing the active frame.
- Return type:
Profiler._Frame
- classmethod metadata(**kwargs)¶
Attach key–value metadata to the current session.
The data is included under the
metadatakey inProfiler.export_metrics()and intended for run configuration, environment info, or other contextual details.
- classmethod trace(name: str = '', remark: str = None)¶
Create a timed scope.
- Parameters:
name (str, default "") – Identifier for the trace scope.
remark (str | None, optional) – Optional descriptive label associated with this specific scope instance. Stored in the metrics export under a full scope path.
- Returns:
A context manager that records begin/end events and lets callers attach metadata via
Profiler._Timer.attach().- Return type:
Profiler._Timer
- classmethod trace_function(func)¶
Decorator that measures the runtime of
func.The function body executes inside
Profiler.trace()with the scope name set tofunc.__name__.- Parameters:
func (Callable) – Function to wrap.
- Returns:
A wrapped function with identical signature.
- Return type:
Callable
- s6.utils.profiler.compute_statistics(durations)¶
Aggregate descriptive statistics for each event.
For every event key, computes min/max/mean/median, standard deviation, variance, common percentiles, interquartile range, count/total, and the mean of the fastest/slowest 5% samples.
- Parameters:
durations (dict[str, list[float]]) – Mapping from event name to a list of durations in milliseconds.
- Returns:
A mapping from event name to a statistics dict containing keys such as
min_ms,max_ms,average_ms,median_ms,p5_ms,p25_ms,p75_ms,p95_ms,iqr_ms,best_5pct_avg_ms,worst_5pct_avg_ms,count, andtotal_ms.- Return type:
dict[str, dict[str, float | int | None]]
- s6.utils.profiler.get_percentile(sorted_values, p)¶
Compute a percentile with linear interpolation.
- Parameters:
sorted_values (list[float]) – Sequence sorted in non-decreasing order.
p (float) – Percentile in
[0, 100].
- Returns:
The interpolated percentile value, or
Noneif the input is empty.- Return type:
float | None
- s6.utils.profiler.main()¶
Example entry-point that prints per-scope timing stats.
Reads
frames.log.jsonlfrom the current working directory, computes statistics viaprocess_frames()andcompute_statistics(), and prints a human-readable report. Intended for ad‑hoc inspection.
- s6.utils.profiler.process_frames(filename)¶
Parse a frames metrics file and compute sub-trace durations.
Accepts either the combined JSON produced by
Profiler.export_metrics()(with a top-levelframeslist) or a legacy JSONL file with one frame per line. Durations are computed by matchingbegin/endevents of the same name and depth within each frame.- Parameters:
filename (str) – Path to the metrics file (combined JSON or legacy JSONL).
- Returns:
Mapping from event full path to a list of durations in milliseconds.
- Return type:
dict[str, list[float]]
s6.utils.r2 module¶
Thin Cloudflare R2 client (S3‑compatible).
Provides a minimal wrapper around boto3 for listing, uploading,
downloading, and deleting objects in Cloudflare R2 using the S3 API. It is
deliberately small and explicit, with sensible defaults and safeguards
against accidental overwrites.
Key concepts¶
Uses standard S3 credentials and custom
endpoint_urlfor R2.Environment variables can supply credentials/region when arguments are omitted:
R2_ACCESS_KEY_ID/AWS_ACCESS_KEY_ID,R2_SECRET_ACCESS_KEY/AWS_SECRET_ACCESS_KEY, and optionallyR2_REGION_NAME/AWS_REGION/AWS_DEFAULT_REGION.Upload helpers default to no‑overwrite behaviour; pass
overwrite=Truewhere supported to replace existing objects.
Motivation¶
Experiments often produce large datasets and intermediate artifacts that need to be shared between local development machines, remote teammates, and lab hardware. Cloudflare R2 provides inexpensive S3‑compatible object storage without egress fees. Wrapping it behind a tiny, documented interface lets the pipeline move data in and out of a relatively abstracted storage backend without depending on any vendor‑specific SDK beyond the ubiquitous S3 API.
This module aims to be:
- Minimal: only the operations we actually use (list, get/put, delete).
- Predictable: no silent overwrites by default; explicit overwrite=True
when you intend to replace data.
Portable: credentials via env or args; works with R2 and any S3‑compatible endpoint (e.g., MinIO) by changing
endpoint_url.
Design¶
The R2Client is a thin façade over a boto3 S3 client:
Construction resolves credentials/region from arguments or environment variables and creates a namespaced S3 client using a custom
endpoint_url.Listings use
ListObjectsV2with pagination (ContinuationToken) and optional delimiter semantics whenrecursive=False. Results are returned as a list ofR2Objectplus any child prefixes.Upload helpers intentionally refuse to overwrite existing keys unless you pass
overwrite=True(for directory uploads). Byte and file uploads raiseFileExistsErrorif the key is present.download_directoryrecreates the relative structure under a prefix._existsissues aHEADrequest and interprets common not‑found error codes; other errors are re‑raised to the caller.To keep documentation builds importable without cloud dependencies,
boto3imports are guarded. InstantiatingR2Clientfails fast with a clearImportErrorifboto3is unavailable.
- class s6.utils.r2.R2Client(access_key_id: str | None = None, secret_access_key: str | None = None, bucket_name: str = '', endpoint_url: str = '', region_name: str = 'auto', session: Session | None = None)¶
Bases:
objectMinimal S3‑compatible client for Cloudflare R2.
- Parameters:
access_key_id (str, optional) – Access key ID. When
None, resolved from environment variablesR2_ACCESS_KEY_IDorAWS_ACCESS_KEY_ID.secret_access_key (str, optional) – Secret access key. When
None, resolved fromR2_SECRET_ACCESS_KEYorAWS_SECRET_ACCESS_KEY.bucket_name (str, optional) – Target bucket name.
endpoint_url (str, optional) – R2 endpoint URL, e.g.
"https://<account>.r2.cloudflarestorage.com".region_name (str, optional) – Region name. If set to
"auto"(default), resolved fromR2_REGION_NAME/AWS_REGION/AWS_DEFAULT_REGIONwhen present.session (boto3.session.Session, optional) – Existing boto3 session to reuse. A new session is created by default.
Examples
Create a client and perform common operations:
client = R2Client( access_key_id="...", secret_access_key="...", bucket_name="my-bucket", endpoint_url="https://<account>.r2.cloudflarestorage.com", ) client.upload_file("local.txt", "folder/remote.txt") client.download_file("folder/remote.txt", "downloaded.txt") client.delete_object("folder/remote.txt") objects, prefixes = client.list(prefix="folder/", recursive=False)
- delete_object(key: str, missing_ok: bool = True) None¶
Delete an object.
- Parameters:
key (str) – Object key to delete.
missing_ok (bool, optional) – If
True(default), succeed even if the object is missing. IfFalse, raise an error when the object does not exist.
- Raises:
FileNotFoundError – If
missing_okisFalseand the object does not exist.
- download_directory(prefix: str, local_dir: str, *, max_workers: int = 8, progress: bool = False, overwrite: bool = False) None¶
Download all objects under a prefix into a local directory, optionally in parallel.
Preserves the relative structure underneath
prefix.- Parameters:
prefix (str) – Key prefix to download (e.g.,
"folder/sub/").local_dir (str) – Destination local directory. Created if missing.
- download_file(key: str, local_path: str, *, progress: bool = False) None¶
Download an object to a local file.
- Parameters:
key (str) – Object key in the bucket.
local_path (str) – Local filesystem path to write to.
- get_object_bytes(key: str) bytes¶
Download an object into memory (as bytes).
- Parameters:
key (str) – Object key.
- Returns:
Object data.
- Return type:
bytes
- list(prefix: str = '', recursive: bool = True) tuple[List[R2Object], List[str]]¶
List objects and pseudo‑directories under a prefix.
- Parameters:
prefix (str, optional) – Key prefix to list under, e.g.,
"folder/sub/".recursive (bool, optional) – If
True(default), returns all objects underprefix. IfFalse, treats"/"as a delimiter and returns only one level, also returning sub‑prefixes.
- Returns:
A pair
(objects, prefixes).objectscontains metadata for each object;prefixeslists child “directories” (only whenrecursive=False).- Return type:
(list[R2Object], list[str])
- upload_bytes(data: bytes, key: str) None¶
Upload raw bytes as an object without overwriting.
- Parameters:
data (bytes) – Bytes to upload.
key (str) – Destination object key.
- Raises:
FileExistsError – If an object already exists at
key.
- upload_directory(local_dir: str, prefix: str, *, overwrite: bool = False, max_workers: int = 8, progress: bool = False) None¶
Upload a directory tree under a prefix, optionally in parallel.
Preserves the relative path structure under
local_dir. Keys are normalised to use/separators.- Parameters:
local_dir (str) – Path to the local directory whose contents to upload.
prefix (str) – Destination key prefix (e.g.,
"folder/sub/").overwrite (bool, optional) – If
False(default), raiseFileExistsErrorwhen a destination key already exists. IfTrue, existing objects are replaced.Parameters (Additional)
---------------------
max_workers (int, optional) – Number of worker threads for parallel uploads (default
8).progress (bool, optional) – If
True, prints a simple aggregate progress indicator to stderr.
- Raises:
NotADirectoryError – If
local_diris not a directory.FileExistsError – If
overwriteisFalseand any destination key exists.
- upload_file(local_path: str, key: str, *, progress: bool = False) None¶
Upload a local file without overwriting existing objects.
- Parameters:
local_path (str) – Path to the local file.
key (str) – Destination object key in the bucket.
- Raises:
FileExistsError – If an object already exists at
key.
- class s6.utils.r2.R2Object(key: str, size: int, last_modified: Any, etag: str)¶
Bases:
objectLightweight object metadata returned by listings.
- key¶
Object key (path) within the bucket.
- Type:
str
- size¶
Object size in bytes.
- Type:
int
- last_modified¶
Timestamp of last modification (
datetimefromboto3). Typing kept generic to avoid a hard dependency in the public API.- Type:
Any
- etag¶
Entity tag (usually an MD5 for non‑multipart uploads).
- Type:
str
- etag: str¶
- key: str¶
- last_modified: Any¶
- size: int¶
s6.utils.stage_decorator module¶
Decorator for pipeline stage functions with context key requirements.
- exception s6.utils.stage_decorator.PipelineStageError¶
Bases:
ExceptionBase exception for pipeline stage validation errors.
- s6.utils.stage_decorator.pipeline_stage(require: List[str], produce: List[str]) Callable[[...], Any]¶
Decorator for pipeline stage functions that operate on a context object.
- Parameters:
require – List of dot-separated paths that must exist in context before running.
produce – List of dot-separated paths that must exist in context after running.
s6.utils.streamer module¶
Streaming utilities for multi-camera capture and transport.
This module includes:
- Frame — lightweight JPEG container with header + concatenated payloads.
- VideoStreamServer and FastAPIVideoStreamServer — capture
frames, stream over TCP, and expose simple HTTP endpoints for a composite PNG and capture specs.
LocalCameraStream— quick local iterator over camera devices.VideoStreamClient— TCP client that yields decodedFrame.take_snapshot()— convenience to fetch one composite image over HTTP.
- class s6.utils.streamer.FastAPIVideoStreamServer(device_ids: List[int], capture_width: int = 1280, capture_height: int = 960, capture_fps: int = 50, capture_auto_exposure: int = 1, capture_exposure: int = -9)¶
Bases:
VideoStreamServerVideo stream server exposing simple FastAPI endpoints.
Adds HTTP endpoints: -
GET /api/current_frame: PNG composite of the latest frames. -GET /api/spec: capture specification JSON.- async get_current_frame()¶
Return an image/png response with the latest composite frame.
- async get_spec()¶
Return a JSON response with the capture specifications.
- async run()¶
Start FastAPI in a thread and run the TCP streaming server.
- class s6.utils.streamer.Frame(*frames, timestamp)¶
Bases:
objectContainer for one or more encoded images with a timestamp.
Frames are serialized as a fixed-size header (see
Frame.Header) followed by the concatenated JPEG payloads for each image. Images are encoded with OpenCV’s JPEG encoder atJPEG_QUALITY.- frames¶
One or more images, typically grayscale
(H, W)arrays.- Type:
tuple[np.ndarray, …]
- timestamp¶
Capture time as a UNIX timestamp in seconds.
- Type:
float
- class Header(crc: int, timestamp: float, reserved: bytes, offsets: list)¶
Bases:
objectFixed-size header for
Frameencoding.Fields¶
- crcint
Placeholder for checksums (unused, defaults to 0).
- timestampfloat
Capture time (seconds since epoch).
- reservedbytes
8-byte reserved payload.
- offsetslist[int]
Byte sizes of each encoded image payload, up to 8 entries.
- crc: int¶
- classmethod decode(header: bytes) Header¶
Decode a header from bytes and strip padding zeros in offsets.
- encode() bytes¶
Encode the header to bytes, padding offsets to length 8.
- classmethod nominal_length() int¶
Return the encoded header length in bytes.
- offsets: list¶
- reserved: bytes¶
- timestamp: float¶
- JPEG_QUALITY = 80¶
- PAYLOAD_SIZE_ENCODING = 'q'¶
- static decode(byte_data: bytes) Frame¶
Decode a header+payload byte sequence into a
Frame.Notes
Images are decoded in grayscale mode (
cv2.IMREAD_GRAYSCALE).
- encode() bytes¶
Encode all images and return header+payload bytes.
- encode_image(image: ndarray, quality: int = 80) bytes¶
Encode a single image as JPEG and return raw bytes.
- class s6.utils.streamer.LocalCameraStream(device_ids: List[int], program=None)¶
Bases:
objectIterate over local cameras in a fixed order and yield
Frame.- Parameters:
device_ids (list[int]) – OS camera indices to open.
program (callable | None) – Optional function applied to each
cv2.VideoCaptureto set props.
- release()¶
Release all camera capture handles.
- class s6.utils.streamer.VideoStreamClient(host='localhost', port=8022)¶
Bases:
objectTCP client that receives encoded
Framemessages.- Parameters:
host (str, default "localhost") – Server hostname or IP.
port (int, default 8022) – Server TCP port.
- run()¶
Blocking demo loop that displays frames in an OpenCV window.
- socket_receiver()¶
Background loop that reads from the socket and enqueues frames.
- start()¶
Start the receiver thread and connect to the server.
- stop()¶
Stop the receiver thread and close the connection.
- class s6.utils.streamer.VideoStreamServer(device_ids: List[int], capture_width: int = 1280, capture_height: int = 960, capture_fps: int = 49, capture_auto_exposure: int = 1, capture_exposure: int = -9)¶
Bases:
objectCapture from multiple devices and stream frames over TCP.
- Parameters:
device_ids (list[int]) – OS camera indices to open.
capture_width (int) – Desired capture resolution.
capture_height (int) – Desired capture resolution.
capture_fps (int) – Target frames per second.
capture_auto_exposure (int) – OpenCV value for auto exposure mode.
capture_exposure (int) – OpenCV exposure value when auto exposure is disabled.
- async capture_frames()¶
Open devices, capture frames, update cache, and broadcast to clients.
- async handle_new_client(reader, writer)¶
Accept a TCP client and stream encoded frames via a queue.
- async monitor()¶
Periodically log the number of connected TCP clients.
- program_camera(cap: VideoCapture)¶
Apply capture properties to a
cv2.VideoCapturehandle.
- async run()¶
Override in subclasses to start servers and capture loop.
- s6.utils.streamer.take_snapshot(server_url='http://localhost:8000')¶
Fetch one composite frame and split it into per-camera images.
- Parameters:
server_url (str, default “http://localhost:8000”) – Base URL of a running
FastAPIVideoStreamServer.- Returns:
List of color images ordered across the horizontal composite.
- Return type:
list[np.ndarray]
- Raises:
Exception – If fetching or decoding fails.
s6.utils.sync_controller module¶
Client for an ESP32 PWM sync controller.
Provides SyncControllerClient to query and set duty cycles for three
outputs (d0, d1, d2) over a simple HTTP API exposed by an ESP32.
Endpoints¶
GET /status→{"d0": float, "d1": float, "d2": float}GET /set?d0=...&d1=...&d2=...→ updates duties and returns status
The client caches the last fetched status and refreshes on demand.
- class s6.utils.sync_controller.SyncControllerClient(base_url, timeout=5)¶
Bases:
objectSmall HTTP client for the ESP32 Sync Controller.
- Parameters:
base_url (str) – Base URL of the device, e.g.,
http://192.168.0.50.timeout (float, default 5) – Per‑request timeout in seconds.
- property d0¶
Current duty cycle for
d0in[0.0, 1.0].
- property d1¶
Current duty cycle for
d1in[0.0, 1.0].
- property d2¶
Current duty cycle for
d2in[0.0, 1.0].
- refresh()¶
Force a status refresh from the device.
- Raises:
requests.RequestException – If the HTTP request fails.
- set_d0(value)¶
Shortcut for
set_duty('d0', value).
- set_d1(value)¶
Shortcut for
set_duty('d1', value).
- set_d2(value)¶
Shortcut for
set_duty('d2', value).
- set_duty(pin, value)¶
Set a single duty cycle while preserving the others.
- Parameters:
pin ({'d0', 'd1', 'd2'}) – Which output to update.
value (float) – Duty cycle in
[0.0, 1.0].
- Returns:
JSON response returned by the device after updating.
- Return type:
dict
- Raises:
ValueError – If
pinis invalid orvalueis out of range.requests.RequestException – If the HTTP call fails or returns a non‑2xx status.
- property status¶
Return cached status, fetching from the device if needed.
- Returns:
Mapping with keys
"d0","d1","d2"and float values in[0.0, 1.0].- Return type:
dict
s6.utils.tensor_registry module¶
Registry and decorator for custom torch.Tensor conversion.
Provides a decorator to register classes that implement a to_torch() method, and a utility to check registration status.
- s6.utils.tensor_registry.is_torch_convertible_type(obj_or_cls)¶
Return True if the given object or class has been registered for torch conversion.
- s6.utils.tensor_registry.register_torch_converter(cls)¶
Class decorator to register a custom type for automatic torch conversion.
The class must implement a to_torch(self) -> torch.Tensor method.
Usage:
@register_torch_converter class Vector2D:
- def __init__(self, x, y):
self.x = x self.y = y
- def to_torch(self):
import torch return torch.tensor([self.x, self.y], dtype=torch.float)
s6.utils.test_camera_identifier module¶
- class s6.utils.test_camera_identifier.TestCameraIDIdentifier(methodName='runTest')¶
Bases:
TestCase- setUp()¶
Hook method for setting up the test fixture before exercising it.
- test_call_identify_and_reorder()¶
- test_check_region_has_marker()¶
- test_erase_marker_region_rect()¶
- test_from_json_and_not_found()¶
- test_region_has_marker_rect()¶
- test_region_has_marker_rect_empty()¶
- test_region_matches_spec()¶
s6.utils.test_datapipe module¶
- class s6.utils.test_datapipe.TestStructuredDatasetTorch(methodName='runTest')¶
Bases:
TestCase- setUp()¶
Hook method for setting up the test fixture before exercising it.
- tearDown()¶
Hook method for deconstructing the test fixture after testing it.
- test_balance_two_directories()¶
- test_invalid_datakey_raises()¶
- test_multiple_keys_extraction_and_tensor()¶
- test_non_numeric_keeps_value()¶
- test_shuffle_reproducible()¶
- test_single_key_extraction_tensor()¶
s6.utils.test_datastore module¶
- class s6.utils.test_datastore.TestStructuredDataset(methodName='runTest')¶
Bases:
TestCase- setUp()¶
Hook method for setting up the test fixture before exercising it.
- tearDown()¶
Hook method for deconstructing the test fixture after testing it.
- test_delete_one_basic()¶
- test_delete_one_image_cleanup()¶
- test_getitem_and_len()¶
- test_multiple_writes_and_counter()¶
- test_write_and_iterate_large_array()¶
- test_write_and_iterate_simple()¶
- test_write_and_iterate_small_array()¶
- test_write_and_restore_pydantic_model()¶
s6.utils.test_entrypoint_loader module¶
- class s6.utils.test_entrypoint_loader.TestEntryPointLoader(methodName='runTest')¶
Bases:
TestCase- test_build_parser_parses_list_and_commands()¶
- test_exec_script_calls_execv()¶
- test_exec_script_no_shebang()¶
- test_get_module_functions_returns_callables()¶
- test_handle_list_error()¶
- test_handle_list_nested_module()¶
- test_handle_list_shell_script()¶
- test_handle_list_top_level()¶
- test_init_sets_base_dir()¶
- test_invoke_module_with_and_without_main()¶
- test_list_commands_excludes_specified_prefixes()¶
- test_list_commands_filters_files_and_dirs()¶
- test_load_module()¶
- test_resolve_command_path_module_and_script_and_errors()¶
- test_run_dispatches_correctly()¶
- test_run_with_no_commands_prints_help()¶
s6.utils.test_infra module¶
- class s6.utils.test_infra.DummyStorageClient¶
Bases:
GatewayClientDummy client for testing storage-related upload/download and serialization.
- create(record: Dict[str, Any], collection: str | None = None) str¶
Insert a document into the (default) collection and return its ID.
- download_file(filename)¶
- get(doc_id: str, collection: str | None = None) Dict[str, Any]¶
Fetch a single document by ID from the (default) collection.
- upload_file(filename, fobj, content_type)¶
- class s6.utils.test_infra.TestGatewayClient(methodName='runTest')¶
Bases:
TestCase- make_response(status=200, json_data=None, content=b'data')¶
- setUp()¶
Hook method for setting up the test fixture before exercising it.
- test_create()¶
- test_delete()¶
- test_delete_file()¶
- test_delete_many()¶
- test_download_file()¶
- test_get()¶
- test_post_file()¶
- test_query()¶
- test_update()¶
- test_upload_file()¶
- class s6.utils.test_infra.TestGatewayClientSerializeDeserialize(methodName='runTest')¶
Bases:
TestCase- setUp()¶
Hook method for setting up the test fixture before exercising it.
- test_deserialize_list_dict()¶
- test_deserialize_model()¶
- test_deserialize_numpy()¶
- test_deserialize_primitive()¶
- test_serialize_list_dict()¶
- test_serialize_model()¶
- test_serialize_numpy()¶
- test_serialize_primitive()¶
s6.utils.test_profiler module¶
- class s6.utils.test_profiler.TestProfiler(methodName='runTest')¶
Bases:
TestCase- tearDown()¶
Hook method for deconstructing the test fixture after testing it.
- test_enable_disable_logging()¶
Verify that Profiler.enable_logging() and disable_logging() correctly update the verbosity flag.
- test_export_metrics_file()¶
Test that export_metrics() writes a combined JSON file containing session metadata, remarks, and frame trace data.
- test_export_trace_file()¶
- Test the export() method to ensure:
A JSON file is written containing a “traceEvents” list and “displayTimeUnit”.
A log message is produced that includes the file name.
- test_frame_context(mock_perf)¶
- Test the frame() context manager:
Ensures that a frame records its start and end times.
Checks that trace events generated within the frame are captured.
Verifies that the frame is appended to the internal frames list.
- test_metadata_collection()¶
Test that metadata() correctly accumulates session metadata.
- test_timer_debug_log()¶
Test that when logging is set to DEBUG level, the timer context generates a debug log.
- test_timer_events(mock_perf)¶
- Test that using the Profiler.trace() context manager produces:
A “begin” event with phase “B” when entering.
An “end” event with phase “E” when exiting,
and that metadata and timing are recorded correctly.
- test_trace_remark_mapping_nested_and_export()¶
Test nested remark mappings and their inclusion in export_metadata.
- test_trace_remark_mapping_simple()¶
Test that providing a remark to Profiler.trace populates _remark_mapping with the correct full scope path and remark.
s6.utils.test_r2 module¶
- class s6.utils.test_r2.FakeS3Client¶
Bases:
object- delete_object(Bucket, Key, **kwargs)¶
- download_file(bucket, key, filename, *args, **kwargs)¶
- head_object(Bucket, Key, **kwargs)¶
- put_object(Bucket, Key, Body, **kwargs)¶
- upload_file(filename, bucket, key, *args, **kwargs)¶
- class s6.utils.test_r2.TestR2Client(methodName='runTest')¶
Bases:
TestCase- setUp()¶
Hook method for setting up the test fixture before exercising it.
- tearDown()¶
Hook method for deconstructing the test fixture after testing it.
- test_download_directory_creates_files()¶
- test_init_fallbacks_to_aws_env_credentials()¶
- test_init_reads_r2_env_credentials()¶
- test_upload_directory_no_overwrite_raises()¶
- test_upload_directory_with_overwrite_uploads_all()¶
- test_upload_file_and_bytes_no_overwrite()¶
s6.utils.test_stage_decorator module¶
- s6.utils.test_stage_decorator.test_get_path_nested_dict_list()¶
- s6.utils.test_stage_decorator.test_pipeline_stage_invalid_index()¶
- s6.utils.test_stage_decorator.test_pipeline_stage_missing_produce()¶
- s6.utils.test_stage_decorator.test_pipeline_stage_missing_require()¶
- s6.utils.test_stage_decorator.test_pipeline_stage_success()¶
- s6.utils.test_stage_decorator.test_pipeline_stage_template_key_missing_produce()¶
- s6.utils.test_stage_decorator.test_pipeline_stage_template_key_missing_require()¶
- s6.utils.test_stage_decorator.test_pipeline_stage_template_key_success()¶
s6.utils.test_streamer module¶
- class s6.utils.test_streamer.FakeSocket(message)¶
Bases:
object- close()¶
- connect(addr)¶
- recv(bufsize)¶
- class s6.utils.test_streamer.TestFrameEncodeDecode(methodName='runTest')¶
Bases:
TestCase- setUp()¶
Hook method for setting up the test fixture before exercising it.
- tearDown()¶
Hook method for deconstructing the test fixture after testing it.
- test_multi_frame_roundtrip()¶
- test_single_frame_roundtrip()¶
- class s6.utils.test_streamer.TestFrameHeader(methodName='runTest')¶
Bases:
TestCase- test_header_encode_decode()¶
- class s6.utils.test_streamer.TestLocalCameraStream(methodName='runTest')¶
Bases:
TestCase- test_iterate_and_release(mock_vcap)¶
s6.utils.test_sync_controller module¶
- class s6.utils.test_sync_controller.FakeResponse(status=200, json_data=None)¶
Bases:
objectMinimal fake response for testing SyncControllerClient.
- json()¶
- raise_for_status()¶
- class s6.utils.test_sync_controller.TestConvenienceSetters(methodName='runTest')¶
Bases:
TestCase- setUp()¶
Hook method for setting up the test fixture before exercising it.
- test_set_d0(mock_set)¶
- test_set_d1(mock_set)¶
- test_set_d2(mock_set)¶
- class s6.utils.test_sync_controller.TestFetchStatus(methodName='runTest')¶
Bases:
TestCase- setUp()¶
Hook method for setting up the test fixture before exercising it.
- test_fetch_status_defaults_missing_keys(mock_get)¶
- test_fetch_status_success(mock_get)¶
- class s6.utils.test_sync_controller.TestItemAccess(methodName='runTest')¶
Bases:
TestCase- setUp()¶
Hook method for setting up the test fixture before exercising it.
- test_getitem_invalid()¶
- test_getitem_valid()¶
- test_properties_return_current_status()¶
- test_setitem_calls_set_duty(mock_set)¶
- test_setitem_invalid()¶
- class s6.utils.test_sync_controller.TestSetDuty(methodName='runTest')¶
Bases:
TestCase- setUp()¶
Hook method for setting up the test fixture before exercising it.
- test_set_duty_calls_api_and_updates_status(mock_get)¶
- test_set_duty_invalid_pin()¶
- test_set_duty_invalid_value()¶
s6.utils.test_waypoint_utils module¶
- class s6.utils.test_waypoint_utils.TestWaypointUtils(methodName='runTest')¶
Bases:
TestCase- setUp()¶
Hook method for setting up the test fixture before exercising it.
- tearDown()¶
Hook method for deconstructing the test fixture after testing it.
- test_parse_file_dispatch_jsonl()¶
- test_parse_file_dispatch_txt()¶
- test_parse_file_unsupported_extension()¶
- test_parse_jsonl_basic()¶
- test_parse_jsonl_invalid_json()¶
- test_parse_jsonl_invalid_values()¶
- test_parse_jsonl_missing_keys()¶
- test_parse_txt_basic()¶
- test_parse_txt_invalid_line()¶
s6.utils.waypoint_utils module¶
Waypoint parsing and two-axis path generation utilities.
This module provides:
WaypointUtilsto parse waypoints from simple text or JSONL files.PathDriverto drive two robotic axes via the REST API client (s6.robotic.client.RoboticClient) and generate common motion patterns (grid, square spiral, circular spiral, random micro-steps).
All distances and offsets are expressed in axis distance units (e.g., mm)
as used by s6.robotic.stepper. Generators yield
s6.schema.primitives.Vector2D where indicated.
- class s6.utils.waypoint_utils.PathDriver(rpc_host: str = '10.20.0.2', rpc_port: int = 8000)¶
Bases:
objectHigh-level two-axis driver for grid/spiral/random patterns.
Uses
s6.robotic.client.RoboticClientto send motion commands to the running REST API. Maintains a simple internal target position used as the origin for relative patterns.- circular_spiral(step_size: float = 0.1, max_radius: float | None = None, dtheta: float = 0.05)¶
Yield an outward circular (Archimedean) spiral.
- Parameters:
step_size (float, default 0.1) – Radial growth per revolution (
binr = b * theta).max_radius (float, optional) – Maximum radius at which to stop emission.
dtheta (float, default 0.05) – Angular increment in radians per step.
- Yields:
Vector2D – Each visited coordinate along the spiral.
- property current: Tuple[float, float]¶
Return the current target coordinates
(x, y)in axis units.
- grid(nx: int, ny: int, dx: float, dy: float)¶
Yield a grid sweep of
nx × nypoints, spaced bydx, dy.Starting at the current position, this generates a serpentine scan over a rectangle centered at the origin of the grid. Motion commands are relative; axes are not zeroed.
- Parameters:
nx (int) – Number of samples along x and y.
ny (int) – Number of samples along x and y.
dx (float) – Spacing between adjacent samples in axis units.
dy (float) – Spacing between adjacent samples in axis units.
- Yields:
Vector2D – Each visited coordinate in grid order.
- list_waypoints()¶
Fetch the list of named waypoints from the server.
- Returns:
Each item contains keys
nameandpositions.- Return type:
list of dict
- move(x: float, y: float) None¶
Move to an absolute position by zeroing then applying offsets.
- Parameters:
x (float) – Target coordinates in axis distance units. Values are rounded to integers for the underlying client calls.
y (float) – Target coordinates in axis distance units. Values are rounded to integers for the underlying client calls.
- random(r: float, repeat: int, waypoint: str | None = None, max_step_size: Vector2D | Tuple[float, float] | None = (0.5, 0.5))¶
Randomly explore a disc of radius
raround a named waypoint.The driver first moves to
waypoint. For each trial, it samples a random offset inside the disc and either moves in micro-steps (bounded bymax_step_sizeper axis) or performs a single jump. It then returns to the waypoint before the next trial.- Parameters:
r (float) – Disc radius in axis units.
repeat (int) – Number of random targets to sample.
waypoint (str, optional) – Name of a waypoint to use as the center. Must exist on the server.
max_step_size (Vector2D or (float, float), default (0.5, 0.5)) – Maximum per-step delta along
xandywhen micro-stepping. IfNone, performs a single jump to each target.
- Yields:
Vector2D – When micro-stepping, yields the cumulative offset from center after each micro-step (forward and return). When jumping, yields the full random offset.
- Raises:
ValueError – If the waypoint is not found on the server.
- spiral(step_size: float = 1.0, max_radius: float | None = None)¶
Yield an outward square spiral from the current position.
- Parameters:
step_size (float, default 1.0) – Distance per step along each leg.
max_radius (float, optional) – If provided, stop once the Euclidean distance from the start exceeds this radius.
- Yields:
Vector2D – Each visited coordinate.
- to_waypoint(name: str) None¶
Move to a named waypoint defined in configuration.
- Parameters:
name (str) – Waypoint identifier. The internal
currentis not modified.
- zero() None¶
Zero both axes and reset the internal position to
(0, 0).
- class s6.utils.waypoint_utils.WaypointUtils¶
Bases:
objectParse waypoint files in plain-text or JSONL formats.
Each waypoint is a pair
(x, y)representing a 2D offset/position.- classmethod parse_file(file_path: str) List[Tuple[float, float]]¶
Parse a waypoint file by extension.
- Parameters:
file_path (str) – Path to a file ending with
.txtor.jsonl.- Returns:
Sequence of
(x, y)pairs.- Return type:
list of tuple[float, float]
- Raises:
ValueError – If the file extension is not supported.
- classmethod parse_jsonl(file_path: str) List[Tuple[float, float]]¶
Parse a JSONL file of objects with
{"x": ..., "y": ...}.Empty lines are ignored. Each line must parse to a JSON object with numeric
xandyfields.- Parameters:
file_path (str) – Path to a JSON lines file.
- Returns:
Sequence of
(x, y)pairs.- Return type:
list of tuple[float, float]
- Raises:
ValueError – If a line cannot be parsed as JSON or lacks required fields.
- classmethod parse_txt(file_path: str) List[Tuple[float, float]]¶
Parse a whitespace/comma-delimited text file of
x ypairs.Each non-empty, non-comment line contains two numbers separated by whitespace or a comma. Lines beginning with
#and empty lines are ignored.- Parameters:
file_path (str) – Path to a text file.
- Returns:
Sequence of
(x, y)pairs.- Return type:
list of tuple[float, float]
- Raises:
ValueError – If a line has invalid format or non-numeric values.