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 built this during my bachelor's thesis when I needed a fast, lightweight way to log scalar data and hadn't worked with rosbag, wandb, or mlflow before. Rather than learning one of those, I wrote a minimal tool to register a few channels, log scalars in a loop and get a CSV.

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.2.tar.gz (9.4 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.2-py3-none-any.whl (8.0 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: csv_session_logger-0.1.2.tar.gz
  • Upload date:
  • Size: 9.4 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.2.tar.gz
Algorithm Hash digest
SHA256 d1bd100a0909f00d1d069bdae7f079116ffb9979223a2803415f7ec7730d5864
MD5 870028638ca03ac6023ee139b1f2df80
BLAKE2b-256 29fb17d73b6039ac3324e6455f40f5eed28f70bc83afa26fd3174c18beb878fe

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for csv_session_logger-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 f67e64d873968b557be3a1251935ff6a28da7efa7f9b01cf70576fa6b6c05f13
MD5 89f2aea3e25fed38ec31be283d2fd824
BLAKE2b-256 2e6a2f864c76262759ac6ee4f86307c77984d9249f394ac000ff4cbdd3de5f81

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