signal-digitizer
Turn a scanned strip-chart / grid-plot PDF (e.g. an ECG trace, an old lab recorder printout) into a calibrated 1D signal.
Pipeline: rasterize page → estimate & correct skew → detect grid lines (Canny + Hough) → calibrate axes from grid spacing → extract ink trace → optional adaptive noise cancellation (LMS/NLMS) → calibrated (x, y) signal.
This is a plain library that depends on the official pymupdf package from
PyPI — it does not fork, patch, or vendor PyMuPDF in any way, so it installs
cleanly alongside any other project using pymupdf.
Install
pip install signal-digitizer
(For local development, from this directory: pip install -e .)
Usage
import signal_digitizer as sd
x, y = sd.digitize(
"chart.pdf",
page_number=0,
unit_per_vgap=1.0,
unit_per_hgap=1.0,
)
# With adaptive noise cancellation (self-referencing Adaptive Line Enhancer)
x, y = sd.digitize("chart.pdf", use_anc=True, anc_mu=0.05, anc_filter_order=8)
# Validate against a ground-truth signal
result = sd.validate_signal(y, reference_signal)
print(result) # {"pearson_r": ..., "rmse": ..., "meets_target": ...}
Working from an already-open pymupdf document
import pymupdf
import signal_digitizer as sd
doc = pymupdf.open("chart.pdf")
x, y = sd.digitize_page(doc[0], dpi=300, unit_per_vgap=1.0, unit_per_hgap=1.0)
From a numpy image you've already rasterized
x, y = sd.digitize_image(image_array, unit_per_vgap=1.0, unit_per_hgap=1.0)
CLI
signal-digitizer chart.pdf --page 0 -o signal.csv
# with adaptive noise cancellation
signal-digitizer chart.pdf --page 0 --use-anc --anc-mu 0.05 --anc-filter-order 8 -o signal.csv
API
digitize(pdf_path, ...)— full pipeline from a PDF file pathdigitize_page(page, ...)— full pipeline from an openpymupdf.Pagedigitize_image(image, ...)— full pipeline from a numpy RGB imagerender_page,render_pymupdf_page— rasterization onlyestimate_skew_deg,deskew— skew correctiondetect_grid,GridLines— grid-line detectioncalibrate_from_grid,AxisCalibration— pixel → data-unit calibrationextract_trace_pixels,to_signal— ink trace extractionAdaptiveNoiseCanceller,denoise_adaptive,build_self_reference— LMS/NLMS denoisingvalidate_signal— Pearson-r / RMSE comparison against a reference signal
Key digitize() parameters
| Parameter | Default | Meaning |
|---|---|---|
dpi |
300 | Rasterization resolution |
unit_per_vgap / unit_per_hgap |
1.0 | Data units per grid cell (x / y) |
ink_thresh |
128 | Grayscale threshold below which a pixel counts as trace ink |
smooth_window |
None |
Moving-average window applied after extraction |
correct_skew |
True |
Estimate & correct page rotation before grid detection |
use_anc |
False |
Apply adaptive LMS/NLMS denoising to the trace |
anc_algorithm |
"nlms" |
"nlms" (recommended) or "lms" |
anc_filter_order |
8 | Number of adaptive filter taps |
anc_mu |
0.05 | Adaptation step size |
License
MIT. See LICENSE.
Metadata
Release files for signal-digitizer 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| signal_digitizer-0.1.2.tar.gz | 12.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| signal_digitizer-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 25.0 kB
Release files / signal_digitizer-0.1.2.tar.gz
| Download URL | signal_digitizer-0.1.2.tar.gz |
|---|---|
| Size | 12.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e46f9885a1d045e50d08d2acb3dd27b2956a92f2a7369a4fbcd3034e40ba1375
|
|
BLAKE2b-256 checksum How to use checksums |
57db7d6a10f90a3233bcd161dc8aa5dd274afd6468957e3d7c811b8463fac995
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|
Release files / signal_digitizer-0.1.2-py3-none-any.whl
| Download URL | signal_digitizer-0.1.2-py3-none-any.whl |
|---|---|
| Size | 12.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e391dedacc3c52d75954fde8bb050055941c9df40caba0ddbcca36c8a710db61
|
|
BLAKE2b-256 checksum How to use checksums |
abb046048ee6ee6ef259f2f2de0032395797fd493ee55596cb50b2bac536fa54
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.11.16
|