Skip to main content

No project description provided

Project description

csv-session-logger

A small session-based CSV logger for robotics sims and bench tests, one file per run, channels aligned on wall-clock time.

Install

pip install csv-session-logger

Requires Python 3.10+.

Quick Start

from csv_session_logger import Logger

log = Logger(session="bench_test", output_dir="logs/", fill="none")
log.register("voltage", unit="V")
log.register("current", unit="A")

log.log("voltage", 12.1)
log.log("current", 0.45)

path = log.save()
print(path)

Channels must be registered before logging. I made that explicit so you decide upfront what goes in the CSV instead of accumulating mystery columns mid-run.

log() vs log_many()

Both append scalar samples to the buffer. The difference is timing.

  • **log(key, value)**: one channel, one call. Each call records its own t_wall via time.time(). If you log x and then y separately, they land on slightly different timestamps. That is fine when channels are independent or arrive asynchronously (e.g. a slow sensor vs a fast control loop).
  • **log_many({...})**: several channels in one call. All keys in the dict share a single t_wall timestamp, taken once at the start of the call. I use this when values belong to the same timestep and should line up in the CSV without NaN gaps, typical in a simulation loop or a synchronized sensor snapshot.

Simulation time is not special. If you want t_sim, register it like any other channel and include it in log_many():

log.register(["t_sim", "x", "x_dot"], ["s", "m", "m/s"])
log.log_many({"t_sim": t, "x": x, "x_dot": x_dot})

Fill strategies

When channels are logged at different t_wall times, save() merges them onto one time index. Missing entries become NaN before the fill step runs.

fill Behavior
"none" Leave NaN as-is. Use when you want to see exactly which channel was missing at each timestamp.
"ffill" Forward-fill with the last known value per column. Leading NaN (before the first sample) stay NaN.
"mean" Linear interpolation between neighbours (pandas.interpolate()). Good for plotting continuous signals when samples are slightly misaligned.

Pick the strategy at Logger(...) construction, it applies on every save().

Output format

The CSV index is t_wall (Unix seconds, float). Column headers use "key [unit]" when a unit was registered, otherwise plain key. Values are written with 8 decimal places.

Example (from a spring-mass-damper run):

t_wall,t_sim [s],x [m],x_dot [m/s],x_ref [m],error [m],F [N]
1781263948.99401498,0.00000000,0.00000000,0.00000000,0.00000000,0.00000000,0.00000000
1781263948.99402165,0.01000000,0.00000000,0.00000000,0.00000000,0.00000000,0.00000000

Auto-generated filenames look like {session}_{YYYY-MM-DD_HH-MM-SS}.csv. Pass save(filename="my_run.csv") to override.

CLI

Entry point: csl

csl info <csv>

Print channel names and duration (last t_wall minus first).

csl info logs/spring_mass_damper_2026-06-12_00-23-22.csv

csl plot <csv>

Quick matplotlib plots. Time axis is t_wall relative to the first row (starts at 0).

# All channels, stacked subplots
csl plot logs/spring_mass_damper_2026-06-12_00-23-22.csv

# Subset by column name (-t / --time)
csl plot logs/spring_mass_damper_2026-06-12_00-23-22.csv -t "x [m]" "F [N]"

# XY plot: first column is X, rest are Y (-x / --xy)
csl plot logs/spring_mass_damper_2026-06-12_00-23-22.csv -x "t_sim [s]" "x [m]" "error [m]"

-t and -x cannot be used together.

Full example: spring-mass-damper

Second-order plant with a P controller, Euler integration. Same as examples/sim_example.py:

import numpy as np
from csv_session_logger import Logger

m, c, k, Kp = 1.0, 0.5, 2.0, 10.0
dt, t_end = 0.01, 20.0
n_steps = int(t_end / dt)

def x_ref(t: float) -> float:
    return 0.0 if t < 2.0 else 1.0

x, x_dot = 0.0, 0.0

log = Logger(session="spring_mass_damper", output_dir="logs/", fill="none")
log.register(["t_sim", "x", "x_dot", "x_ref", "error", "F"],
             ["s", "m", "m/s", "m", "m", "N"])

t = 0.0
for _ in range(n_steps):
    ref = x_ref(t)
    error = ref - x
    F = Kp * error

    x_ddot = (F - c * x_dot - k * x) / m
    x_dot += x_ddot * dt
    x += x_dot * dt

    log.log_many({
        "t_sim": t, "x": x, "x_dot": x_dot,
        "x_ref": ref, "error": error, "F": F,
    })
    t += dt

path = log.save()
log.summary()

Run it: python examples/sim_example.py, then csl plot logs/spring_mass_damper_*.csv.

Why not rosbag / wandb / mlflow?

I haven't used these in practice, but for this use case I wanted something minimal: register a few channels, log scalars in a loop, get one CSV. No server, no extra setup, just a file I can open with pandas or csl plot.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

csv_session_logger-0.1.0.tar.gz (9.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

csv_session_logger-0.1.0-py3-none-any.whl (7.9 kB view details)

Uploaded Python 3

File details

Details for the file csv_session_logger-0.1.0.tar.gz.

File metadata

  • Download URL: csv_session_logger-0.1.0.tar.gz
  • Upload date:
  • Size: 9.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for csv_session_logger-0.1.0.tar.gz
Algorithm Hash digest
SHA256 20f099ecd6174c02aa02496c8bd6969bc525e5078aea919fa1955aaf235d4046
MD5 1105e3a69e2e43344cdc9650a1c5310a
BLAKE2b-256 9bd1461c200bc59e0d9e4fae00afd6e25225e5c1b40448cf3da74e264cc5b29b

See more details on using hashes here.

File details

Details for the file csv_session_logger-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for csv_session_logger-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f7568a2ee5b379feac46ba92dc256add68b0df35ff411a412882948bbd8c3af0
MD5 34e2f2b8a9fd325c94254e34df833b41
BLAKE2b-256 87913d056aa955e98c73139844589874edc9164fe2824e4d3c27964ccf8d02a4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page