Skip to main content

pqx — a terminal explorer for Parquet files

pqx is an interactive, keyboard-driven terminal UI for looking inside Parquet files: browse rows, filter with SQL, profile columns, draw sky maps and density plots, and export subsets. It is built for large LSST catalogs (SSSource, SSObject, DiaSource, …) but works with any single Parquet file.

Nothing is loaded in full. The grid pulls small windows of rows, and every aggregate (counts, statistics, histograms, sky maps) runs inside DuckDB. A multi-GB file opens instantly, and jumping to row 3,000,000,000 costs one row-group read.

pip install -e .          # or: pip install -e ".[dev]" for tests
pqx catalog.parquet
pqx sssource.parquet --where "ssObjectId = 9000123"
python -m pqx.demo demo.parquet --rows 1000000   # a synthetic LSST-like file to play with

What you get

Tab
Data A fast, scrollable grid over the entire file. Headers show type and unit, and values use astronomy-aware formatting. d opens a detail panel with every column of the current row at full precision, plus derived readings: MJD → UTC date, RA/Dec → sexagesimal, errors in mas, flux → AB mag.
Schema Every column with its type, unit, description (from Parquet field metadata, including Felis-style "[unit] description"), null count, min/max from row-group statistics, compressed size, compression ratio and encodings.
Stats Pick a column to see count, nulls, NaNs, distinct values, min/max, mean/std and quantiles, with a histogram for numeric and time columns or a top-values bar chart for categorical ones.
Plot Sky (Mollweide) maps of any lon/lat pair, with RA/Dec auto-detected, and density scatter plots of any two numeric columns, both drawn in text with sub-character resolution and log-density colour.
Metadata File overview, row-group table and key-value metadata, with JSON shown pretty-printed.

The filter bar (press /) takes either

  • a SQL WHERE expression: mag < 21 and band = 'r', ssObjectId is not null, ra between 10 and 20; or
  • a full query over the table t: select band, count(*), avg(mag) from t group by 1.

The filter applies everywhere: grid, stats, plots and export. Column names auto-complete (→ accepts), ↑/↓ recall history, and errors appear inline without losing the current view.

Keys

key action
/ · x / Ctrl+X edit filter · clear filter (Ctrl+X also works while typing in the filter box)
arrows, PgUp/PgDn, Ctrl+Home/End move; the row window slides seamlessly
g go to row: 1234, 1.5M, 50%, -1
s sort by the cursor column (asc → desc → off); clicking a header does the same
= narrow the filter to rows equal to the cursor cell
d / Enter row detail panel
c · - · p choose columns · hide column · pin columns
Home / End first / last column; ‹ › beside the header mark hidden columns (click to page)
f · y · i raw/smart formatting · copy cell · stats for column
1–5 · Ctrl+← Ctrl+→ go to a tab · previous / next tab. The strip in the panel border reads 1 Data ─ 2 Schema ─ … ^← ^→; names underline under the mouse and switch on click
e export the current view (filter + sort + visible columns) to Parquet/CSV/JSON
m toggle sampling for stats and plots
l L [ ] Stats: log counts, log values, fewer/more bins
click · enter Plot: open a settings field's drop-down (type to narrow the column list)
tab · ← → Plot: move between settings fields · step the field's value
r Plot: rotate the sky-map centre between RA 0° and 180°
Esc cancel running queries / leave the filter bar
? · q help · quit

Look

pqx draws with your terminal's own background and 16-colour palette, so it matches whatever scheme you use, and it looks the same with or without 24-bit colour. Panels are thin boxes, the focused one in the accent colour. Colour is kept for things that mean something: the file name and other object names are cyan, and status lines use ✓ (green) for done, ! (yellow) for warnings such as sampling, ✗ (red) for errors, and ⠸ while running. The style follows acid's CLI design language.

option env
--accent blue|cyan|magenta|green|yellow PQX_ACCENT focus colour (default blue)
--dim faint|bright-black PQX_DIM secondary text: the faint attribute (default), or ANSI bright black for terminals that ignore faint
--border NAME PQX_BORDER unfocused panel border, an ANSI colour name (default bright_black)
--theme NAME use a Textual theme instead of the terminal's colours

Sky maps and density plots default to magma; the colormaps (magma, viridis, inferno, plasma, gray) are emitted as exact xterm-256 colours, and terminal draws density with your palette alone (faint, accent, bold).

Large files

  • Seeking. When no filter or sort is active, a window is fetched with DuckDB's file_row_number pushdown. Only the row group(s) holding the window are read, so paging is O(1) in file size (about 20 ms per window on a 30M-row / 850 MB file).
  • Filtered and sorted views use LIMIT/OFFSET over the query. The total row count is computed in the background, and the grid is usable before it arrives.
  • Cancellation. A new filter, stats request or plot interrupts the now-stale DuckDB query instead of letting it run to completion. Esc cancels everything that's running.
  • Sampling (m, --sample) makes stats and plots read about 2M rows from up to 16 evenly spaced row groups and skip the rest. It turns on automatically for files over 200M rows or 8 GiB, and is worth enabling whenever the storage is slow (network file systems, cold caches). Sampled results are marked as such.
  • --threads N caps DuckDB's parallelism on shared machines.

Sky maps

The Mollweide renderer is a port of the one in acid (acid/io/skymap_art.py), adapted to work from an equirectangular count grid, which DuckDB bins in a single GROUP BY, instead of a HEALPix map:

  • each character cell is inverse-projected, so rendering cost doesn't depend on row count;
  • area is carried by glyph shape: 2×2 quadrant sub-cells light up when at least half of a sub-cell is covered, so partial coverage draws as partially filled glyphs;
  • density is carried by colour: log surface density in deg⁻² through a selectable colormap (magma by default; viridis, inferno, plasma, gray, or terminal), with a colorbar legend;
  • the limb and graticule are a braille outline, and RA increases to the left.

Versions

The version comes from git tags via setuptools-scm, as in acid: a tagged commit vX.Y.Z is version X.Y.Z, and anything after it is a dev version such as 0.2.dev3+g1a2b3c4. pqx --version prints it.

To release, publish a GitHub Release; creating it also creates the tag:

gh release create v0.2.0 --generate-notes

That runs .github/workflows/publish.yml, which builds the package with uv build and uploads it to PyPI with trusted publishing (OIDC, no stored token). The same tag runs the full test matrix in CI. One-time setup on PyPI: add a trusted publisher for project pqx: owner mjuric, repository pqx, workflow publish.yml, environment pypi.

Development

python -m venv .venv && .venv/bin/pip install -e ".[dev]"
.venv/bin/pytest          # data layer, formatting/plots, and headless UI tests (Textual pilot)

Layout: pqx/data.py (DuckDB/PyArrow access layer), pqx/fmt.py (astronomy-aware formatting), pqx/plots.py (text plots), pqx/app.py + pqx/screens.py + pqx/app.tcss (the Textual UI), pqx/demo.py (synthetic data).

Metadata

Release files for pqx 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pqx 0.1.0
File Size Uploaded
pqx-0.1.0.tar.gz 69.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pqx 0.1.0
File Interpreter ABI Platform
pqx-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 127.5 kB

Release files / pqx-0.1.0.tar.gz

Download URL pqx-0.1.0.tar.gz
Size 69.9 kB
Tags Source
SHA-256 checksum
How to use checksums
fdf0928cc6dee81b189c07837e077f2875a7774fbd68f0e5bc8d117e95ce10c2
BLAKE2b-256 checksum
How to use checksums
f6d85ced977c6e651cfa5c3ef0db143eec0534b47deb2480bac11415dee23658
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.21 {"installer":{"name":"uv","version":"0.12.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / pqx-0.1.0-py3-none-any.whl

Download URL pqx-0.1.0-py3-none-any.whl
Size 57.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
444e04d00b3c1ff2c8c99fc4e3baa76e7df122f405fa18d8c874fdc73b6d793f
BLAKE2b-256 checksum
How to use checksums
25768a9a97f2519724ca8c68ce2796131290276b36e81bcfca554e115b327820
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.12.21 {"installer":{"name":"uv","version":"0.12.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page