Profiling, analytics, and PDF reporting for the runtime performance of quantum circuit simulators.
Project description
QS_Charter
Profiling, analytics, and bundled-PDF reporting for the runtime performance of quantum circuit simulators.
QS_Charter does not simulate circuits, modify simulators, or visualize circuit diagrams. It measures how a simulator performs — wall time, CPU, memory, and (if available) GPU usage — while it runs, and turns a sweep of runs into scaling-trend analysis, crossover detection, anomaly flags, and a bundled PDF report.
It works with any simulator, with no per-library adapters, because of two design choices:
- You wrap your own call to your simulator inside
qs_charter.track(...). QS_Charter never imports or calls into the simulator itself. - Measurement is out-of-process / OS-level sampling (via
psutil, pluspynvml/nvidia-smifor GPU), not in-Python profiling — so it works correctly whether the simulator is pure Python, a C++/Rust/Julia extension, or running on a GPU.
Install
pip install qs-charter
# optional extras
pip install qs-charter[gpu] # GPU sampling via pynvml (falls back to nvidia-smi either way)
pip install qs-charter[parquet] # bulk export to Parquet
pip install qs-charter[dev] # pytest, etc., for running the test suite
Quickstart
import qs_charter as mq
# 1. Track each run. QS_Charter starts a background sampling thread, lets your
# code run completely unmodified, and stops sampling when the block exits.
with mq.track(label="qiskit_aer", meta={"qubits": 20, "depth": 50,
"backend_type": "statevector"},
save_dir="./runs"):
result = simulator.run(circuit)
# ... repeat across a sweep of qubit counts and/or simulators ...
# 2. Reload every run from disk. This step needs zero simulator-specific
# context -- it works on a machine with no simulator installed at all.
records = mq.load_all("./runs/")
# 3. Build the report: scaling fits, crossover detection, anomaly flags,
# charts, and deterministic template-based narrative text, all in one call.
report = mq.report(records, compare_by="label")
# 4. Render the bundled PDF (title page, executive summary, one section per
# metric, cross-simulator comparison table, appendix of raw stats).
report.save_pdf("benchmark_report.pdf")
Run python examples/sweep_example.py for a complete, runnable end-to-end demo (using a mock simulator, so no real quantum simulator is required) that produces a sample PDF report.
The track() -> load_all() -> report() -> save_pdf() workflow
track() — collect
with mq.track(label, meta=None, interval=0.075, save_dir=None) as t:
...your simulator call...
t.record # the resulting RunRecord, available after the `with` block exits
- Also works as a decorator:
@mq.track(label="my_sim", meta={"qubits": 24}). metais a free-form dict: putqubits,depth,gate_count,simulator_name,backend_type("statevector"|"tensor_network"| anything else), or any custom field you want available later in analysis/reporting.save_dir, if given, auto-saves the run as a JSON file there, ready forload_all().- If an exception escapes the
withblock, the run is still recorded, withmetadata["failed"] = Trueand anerrormessage — these show up as critical anomalies in the report rather than crashing your sweep. - GPU sampling degrades gracefully: with no GPU (or no
pynvml/nvidia-smi), every GPU field is simplyNone, never an error.
load_all() — reload (replay, no simulator required)
records = mq.load_all("./runs/") # every *.json in a directory
records = mq.load("./runs/one_run.json") # a single file
The on-disk JSON is the full-fidelity record (metadata, time-series, summary, and any
backend-specific extensions). Bulk CSV/Parquet export is also available via
mq.save(records, "runs.csv"), but those formats drop the time-series and are meant for
external tools (pandas, Excel), not round-tripping.
report() — analyze + build
report = mq.report(
records,
compare_by="label", # or e.g. "metadata.backend_type"
metrics=["summary.wall_time", "summary.peak_mem_rss", "summary.mean_cpu_pct"],
x_field="metadata.qubits",
title="My Benchmark Report",
)
report.executive_summary # str
report.findings # dict of scaling_fits / crossovers / anomalies (JSON-able)
Under the hood this runs qs_charter.analysis (scaling-trend fits, crossover detection,
anomaly flags — all structured data, not strings), then qs_charter.visualize (matplotlib
charts), then qs_charter.report.narrative (deterministic templates turning the structured
findings into captions and an executive summary).
save_pdf() / exports — output
report.save_pdf("benchmark_report.pdf") # the bundled PDF
report.export_data("./export", fmt="json") # raw RunRecords (json/csv/parquet)
report.export_charts("./charts") # every chart as a standalone PNG
Architecture
| Module | Responsibility |
|---|---|
qs_charter.collection |
track() — background OS-level sampling context manager / decorator |
qs_charter.schema |
RunRecord / Sample — the canonical, JSON-serializable data model |
qs_charter.analysis |
Scaling-trend fits, crossover detection, anomaly flags — structured findings only |
qs_charter.visualize |
matplotlib charts (scaling curves, comparison overlays, time-series, summary tables) |
qs_charter.report |
Ties analysis + visualize + narrative together into a Report (PDF + data exports) |
RunRecord is the single contract between these modules — analysis, visualize, and
report never talk to each other directly, and none of them know anything about
simulators. This is what makes "replay" workflows possible: capture once (with the
simulator installed), analyze/report anywhere (without it).
A note on the PDF report's text
Every caption, interpretation, and the executive summary are produced by
deterministic string templates in qs_charter.report.narrative, fed only by the
structured output of qs_charter.analysis. There is no LLM, no external API call, and no
network access involved at any point — the same input data always produces byte-identical
report text. See qs_charter/report/narrative.py if you want to extend the template set.
The default PDF backend (qs_charter.report.pdf_backend.ReportLabRenderer) is pure Python
(reportlab), specifically to avoid system-level dependencies (Cairo/Pango, etc.) that
complicate pip install on Windows. It sits behind the qs_charter.report.base.PDFRenderer
interface, so an HTML/CSS-based backend could be added later as an optional extra without
restructuring anything upstream.
Running the tests
pip install -e .[dev]
pytest tests/
tests/test_schema.py covers RunRecord/Sample serialization round-tripping (JSON and
CSV). tests/test_analysis.py covers the scaling-trend curve-fitting classification
(exponential/polynomial/linear/constant, on closed-form synthetic data with known
answers) and crossover detection. tests/test_report.py covers narrative determinism and
an end-to-end PDF build.
Non-goals (v1)
- No circuit diagram visualization.
- No built-in adapters for specific simulator libraries — agnosticism comes from the
track()wrapper pattern, not per-library integration. - No LLM or external API dependency for report generation, ever — captions/write-ups are template-based only.
- No GUI/dashboard — output is files (PDF, JSON, PNG) for notebooks or disk.
License
QS_Charter is licensed under the Business Source License 1.1 with a custom Additional Use Grant:
- Free for any non-commercial use -- personal projects, academic research, non-profit use, evaluation, etc.
- Commercial use requires a separate license. If you want to use QS_Charter commercially, contact oscinspire@gmail.com to arrange a commercial license agreement.
- Each version of the Licensed Work converts to the Apache License, Version 2.0 four years after that version is published.
See the LICENSE file for the full terms. This isn't legal advice -- if the
licensing terms matter for your use case, have it reviewed by a lawyer.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
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 qs_charter-0.1.0-py3-none-any.whl.
File metadata
- Download URL: qs_charter-0.1.0-py3-none-any.whl
- Upload date:
- Size: 38.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8cea48fc40487d74ee78058ecf81deb5cff84b72df59a40cce37d644a0bc0e52
|
|
| MD5 |
9d5a3ef388c98ba2642e48370a5d8ced
|
|
| BLAKE2b-256 |
2b65bfd7f6ec8e0ab4d25286779462f70b2038b96c4faa1d6ad9d763fe5b914a
|