Biosensor
A lightweight Python package with an attached local viewer that converts raw electrochemical instrument exports into one tidy dataframe schema, and lets you visually verify the parse before trusting the output.
Targets solo researchers and small labs working on immunosensor and biosensor cyclic voltammetry (CV) / DPV / SWV data who need a fast, local path from raw instrument export to usable data, without adopting an institutional ELN.
Supported formats (v1)
- CH Instruments text export
- Metrohm Nova (Autolab) text/CSV export
- PalmSens
.pssession(best-effort; seesrc/biosensor/readers/palmsens.py) - Generic delimited CSV: a named header, metadata lines before the header, or headerless two-column numeric (potential, current)
Format detection is content-based (file signature and header content), not filename-extension based.
Install
The library, from PyPI:
pip install biosensor
The viewer, launchers, and sample_data/ ship in the repository, not the
wheel. For those and the test suite, clone and install in place:
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
Library usage
from biosensor import load, batch_load, to_dataframe
result = load("cv01.txt")
df = to_dataframe(result.measurement)
print(result.qc.sanity_status) # "ok" | "flagged" | "failed"
batch = batch_load("data/2026-08-05-run/")
df = batch.to_dataframe() # all files, one tidy frame
qc_df = batch.qc_dataframe() # per-file sanity status
Every reader converts its instrument-specific format into a Measurement
(potential, current, scan rate, cycle number, technique, sample ID, analyte
concentration, and a flexible technique_params dict for things like SWV
frequency or DPV pulse width). QC state (sanity_status, review notes)
lives in a separate QCRecord so the sanity heuristic can evolve without
touching the measurement schema.
Viewer
Double-click the launcher for your platform (launcher.command on macOS,
launcher.sh on Linux, launcher.bat on Windows). Each sets up the venv on
first run, then starts the server and opens the browser:
./launcher.command # macOS
./launcher.sh # Linux
launcher.bat # Windows
# or manually: source .venv/bin/activate && python viewer/app.py
Opens at http://127.0.0.1:5050. Three panes: file list on the left (live
filter, ok/flagged/failed tabs), the center with three tabs (the CV curve in
Plotly with zoom/pan; a Dataframe tab with row search, previewing up to 2,000
rows in the page while CSV export covers the full file; and an Overlay tab), and
a parse record on the right (quality check, instrument metadata,
sample/concentration mapping). The Overlay tab draws every loaded file of the
same sample on one plot, colored and ordered by concentration, for the
dose-response view. Load a single file or an entire folder, correct a wrong
column mapping in-place (see a live preview before applying), override the
quality flag manually, and export any file or the whole batch as CSV. The open
file is kept in the URL, so a reload reopens it. Light/dark theme toggle in
Settings. htmx, Plotly, and the IBM Plex fonts are vendored under
viewer/static/vendor/, so the viewer runs fully offline with no CDN
dependency. (Fonts are IBM Plex, under the SIL Open Font License 1.1; see
viewer/static/vendor/fonts/OFL.txt.)
Visual design follows the Tree Design System, with design tokens under
viewer/static/tokens/.
The viewer is local, single-user, in-memory only; state resets on restart. This is intentional (see Non-goals below).
Tracing
Action-level tracing via traceact
(file parse, batch upload, mapping correction, CSV export) writes to
data/traces/traces.jsonl for local debugging. It isn't required to run the
app, and it's gitignored.
Sanity-check heuristic (v1)
A simple curve-shape check, not anything trained: flags constant/flat current or potential (near-certain wrong column mapping), non-finite values, too few points, a single-direction sweep with no return cycle, and the absence of any peak/inflection in the current trace. Manual override is always available in the viewer.
Security
The viewer accepts arbitrary uploaded files and treats them as untrusted input:
- Format detection inspects file content, never trusts the extension alone
- Per-file byte and data-row limits bound parsing cost (see
readers/base.py) - Any parse failure, including malformed or adversarial files, degrades to a per-file error, never a server crash
- Filenames, sample IDs, and technique strings derived from file content are sanitized before display and CSV export (including a CSV-formula injection guard)
- No macro or script execution in any format reader
Non-goals (v1)
Peak fitting, baseline correction, calibration curves, ML modeling, multi-user access, authentication, or cloud deployment. Four format readers is the v1 target, not exhaustive vendor coverage.
Sample data
sample_data/ has a synthetic 27-file batch (all four formats) for
exercising the viewer by hand: an IL-6 immunosensor concentration series
(CH Instruments, with sample and concentration carried in each file's contents,
peak height scaling with concentration, which the Overlay tab draws as a
dose-response fan), ferricyanide and blank references, Metrohm Nova DPV/CV,
PalmSens sessions, a well-formed generic CSV, and two files that deliberately
fail to parse (to exercise the batch error path). Point "Load a folder" at it. Regenerate with:
source .venv/bin/activate
python scripts/generate_sample_data.py
Tests
source .venv/bin/activate
pytest
Fixtures in tests/fixtures/ are synthetic (generated, not instrument
exports) but shaped like each format's structure, including one
unrecognizable file to exercise the error path.
Documentation
- USAGE.md: the full manual (API, schema, formats, errors)
- ARCHITECTURE.md: how the library and viewer fit together
- CHANGELOG.md: dated changes per version
Project layout
src/biosensor/ # the library: schema, readers, core API, QC heuristic
viewer/ # Flask + HTMX + Plotly local viewer
tests/ # pytest suite + synthetic fixtures
Author
By Mo Shehu
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file biosensor-1.2.0.tar.gz.
File metadata
- Download URL: biosensor-1.2.0.tar.gz
- Upload date:
- Size: 33.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2462090542fba0c4011d2fcd8459137338db76774dca276ff893291d7cfe4fd9
|
|
| MD5 |
e4de1411d7f1630e53e4b22c7496234b
|
|
| BLAKE2b-256 |
b9de20f11133843cc7423b99a4ff21e70eac3d92a6fa926aeb90156e9d98599b
|
Provenance
The following attestation bundles were made for biosensor-1.2.0.tar.gz:
Publisher:
publish.yml on shehuphd/biosensor
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
biosensor-1.2.0.tar.gz -
Subject digest:
2462090542fba0c4011d2fcd8459137338db76774dca276ff893291d7cfe4fd9 - Sigstore transparency entry: 2451832186
- Sigstore integration time:
-
Permalink:
shehuphd/biosensor@c09e37a16953d40ff6f1f228ce2602317d4b0011 -
Branch / Tag:
refs/tags/v1.2.0 - Owner: https://github.com/shehuphd
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c09e37a16953d40ff6f1f228ce2602317d4b0011 -
Trigger Event:
release
-
Statement type:
File details
Details for the file biosensor-1.2.0-py3-none-any.whl.
File metadata
- Download URL: biosensor-1.2.0-py3-none-any.whl
- Upload date:
- Size: 24.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e31b07ed5b1c88ebd9ccbc7ad740ed5fe58be4428ce673cd977518a02fe75efc
|
|
| MD5 |
98faa1723b689eb7d6f12fe5ed271611
|
|
| BLAKE2b-256 |
835d26d71820d169a2674d203c0693b222dddb2a6a8e15a2f687f4aa5f416cc9
|
Provenance
The following attestation bundles were made for biosensor-1.2.0-py3-none-any.whl:
Publisher:
publish.yml on shehuphd/biosensor
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
biosensor-1.2.0-py3-none-any.whl -
Subject digest:
e31b07ed5b1c88ebd9ccbc7ad740ed5fe58be4428ce673cd977518a02fe75efc - Sigstore transparency entry: 2451832701
- Sigstore integration time:
-
Permalink:
shehuphd/biosensor@c09e37a16953d40ff6f1f228ce2602317d4b0011 -
Branch / Tag:
refs/tags/v1.2.0 - Owner: https://github.com/shehuphd
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@c09e37a16953d40ff6f1f228ce2602317d4b0011 -
Trigger Event:
release
-
Statement type: