Metadata-Version: 2.1
Name: qs-charter
Version: 0.1.0
Summary: Profiling, analytics, and PDF reporting for the runtime performance of quantum circuit simulators.
Author: QS_Charter Contributors
License: BUSL-1.1
Project-URL: Homepage, https://github.com/example/qs_charter
Project-URL: Issues, https://github.com/example/qs_charter/issues
Keywords: quantum computing,benchmarking,profiling,performance,simulator
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Science/Research
Classifier: License :: Other/Proprietary License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Scientific/Engineering :: Physics
Classifier: Topic :: System :: Benchmark
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: matplotlib >=3.6
Requires-Dist: numpy >=1.23
Requires-Dist: psutil >=5.9
Requires-Dist: reportlab >=4.0
Provides-Extra: dev
Requires-Dist: pandas >=1.5 ; extra == 'dev'
Requires-Dist: pytest >=7.0 ; extra == 'dev'
Provides-Extra: gpu
Requires-Dist: pynvml >=11.5 ; extra == 'gpu'
Provides-Extra: html
Requires-Dist: weasyprint >=60.0 ; extra == 'html'
Provides-Extra: parquet
Requires-Dist: pandas >=1.5 ; extra == 'parquet'
Requires-Dist: pyarrow >=12.0 ; extra == 'parquet'

# 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:

1. You wrap *your own call* to your simulator inside `qs_charter.track(...)`. QS_Charter never imports or calls into the simulator itself.
2. Measurement is **out-of-process / OS-level sampling** (via `psutil`, plus `pynvml`/`nvidia-smi` for 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

```bash
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

```python
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

```python
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})`.
- `meta` is a free-form dict: put `qubits`, `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 for `load_all()`.
- If an exception escapes the `with` block, the run is still recorded, with
  `metadata["failed"] = True` and an `error` message — 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 simply `None`, never an error.

### `load_all()` — reload (replay, no simulator required)

```python
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

```python
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

```python
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

```bash
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](./LICENSE) 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`](./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.
