Added some optimizations for RunScript
InterSystems Employee Programming Challenge #1. Given the Gaia DR3 epoch-photometry
archive, this finds astronomical objects whose BP or RP flux changed by more than 100%
across the observation period, writes the result to a CSV, and — as a bonus — renders the
result set as an interactive 3D galaxy you can fly through.
Built on the official intersystems-challenge1-docker-template: InterSystems IRIS
Community Edition in Docker, driven by do ^RunScript. It processes the full 20-file
benchmark in ~0.9 seconds on a 22-core dev box (a fully in-C, single embedded-Python-call
kernel). The grader runs platform: amd64 on Apple-silicon hardware (x86 under Rosetta), so
the kernel detects the emulated FPU and picks a parser that stays correct and fast there —
see “How it stays fast”.
Prerequisites: git and Docker Desktop.
git clone https://github.com/isc-epolakie/Gaia.git
cd Gaia
docker compose up --build -d
Produce the result CSV (this is what the challenge grades):
docker compose exec iris iris session iris
USER> do ^RunScript
That writes data/out/results.csv and prints the qualifying-source count and the elapsed
time. Everything needed (the analyzer classes, the C extensions, the routine) is compiled
into the image at build time, so do ^RunScript works immediately with no further setup.
See the galaxy (optional, recommended):
docker compose exec iris bash scripts/setup_web.sh # one-time web provisioning
then open http://localhost:52773/csp/gaia/ui/index.html.
https://github.com/isc-epolakie/Gaia/raw/master/docs/demo.mp4

The web UI turns the results CSV into a living star map (Three.js + WebGL, served straight
from the IRIS Community built-in web server — no extra infrastructure):
The render loop pauses when the galaxy is off-screen, so it stays light.
For each source_id in the 20 benchmark files
(EpochPhotometry_000000-003111.* … EpochPhotometry_020985-021233.*):
bp_flux and rp_flux arrays.min_flux = min, max_flux = max,percentage_change = ((max_flux − min_flux) / min_flux) × 100.percentage_change is the larger of the BP and RP values.percentage_change > 100.Output — data/out/results.csv, header + one qualifying source per line
(~57,000 rows), sorted by percentage_change descending:
source_id,bp_min_flux,bp_max_flux,rp_min_flux,rp_max_flux,percentage_change
A band with no valid flux leaves its two columns blank.
The task says to ignore “missing, null, NaN, or otherwise invalid flux values.” We treat a
value as valid only if it parses as a finite number and is strictly positive (> 0).
Negative and zero fluxes are unphysical — Gaia itself flags negative flux as rejected
(variability_flag_*_reject) — and dividing by a zero/negative min_flux would make the
percentage meaningless. Everything else (NaN, empty, null, non-numeric, ≤ 0) is dropped.
Under this rule roughly 75% of sources exceed 100% (epoch photometry captures real
transits with large swings), so big percentages are expected and kept as-is.
The whole scan runs through one embedded-Python call from ObjectScript into a C kernel
that orchestrates everything:
nthreads=0 the kernel picks 2× the onlineceil(total_bytes / largest_file) = 14 — past that, a thread has no unsplittableplatform: amd64 on Applestrtodstrtod on the emulated path. (Details below.)data/in/EpochPhotometry_*.csv.gz (20 gzipped ECSV files, shipped with the repo)
│
src/RunScript.mac ← graders run: do ^RunScript
│ times the run, then calls embedded Python
▼
%SYS.Python → ckernel.analyze_dir
│ glob + size-sort the files (biggest first), write the CSV header
▼
OpenMP prange (one file per thread, GIL released)
│ for each file in parallel:
│ • libdeflate-decompress the gzip (output buffer sized from ISIZE trailer)
│ • single-pass scan for bp/rp flux cells
│ • compute per-band min/max
│ • flock-append qualifying rows to data/out/results.csv (one write per file)
▼
data/out/results.csv
The files are ECSV (≈365 leading # comment lines, then a CSV header, then data), and
bp_flux/rp_flux are quoted arrays like "[NaN,50.0,…,157841.99]" — commas live
inside the quotes, so the row can’t be split naively. The layout is fixed, so the kernel
locates the bp/rp arrays by position (still cross-checked against the header names).
Every optimisation was verified to be both faster and byte-for-byte identical to the
previous answer against a fixed reference. The 20-file run went from ~1.8 s to ~0.92 s
on a 22-core Intel Ultra 9 185H dev box. Measured over 12 warm runs on an otherwise-idle
machine: min 0.87 s, median 0.92 s, max 0.98 s (a tight 12 % spread — the job is
memory-bandwidth-bound, so the residual variance is memory-bus contention, not the codec).
The grader ran the previous submission ~4× faster than this box, so this design projects to
~0.23 s there (or ~0.31 s if the grader’s memory bandwidth scales less than its core
count — the decompress is bandwidth-bound, so the floor is set by how fast the machine moves
bytes, not by clock speed):
%SYSTEM.WorkMgr to fan files across separate worker processes because the Cython kernelsrc/gaia/ckernel.pyx decompresses each file with libdeflate andmemchr (SIMD), and only the two flux groups are parsed. Nothing but the final rows__int128 parser — bit-identical to strtod on all 5.28M realstrtod, so the emulated path is both correct and quick.ceil(total / largest) = 14 (see “How it stays fast”).The test suite verifies that the production path (analyze_dir — the parallel, write-to-CSV
kernel) agrees with an independent single-file oracle (analyze, a separate serial scan in
the same module that parses with strtod and returns plain tuples): it checks the
qualifying-row count (57,099), the exact IDs, and every numeric min/max/percentage value per
row. It runs the check under both parser regimes (native long-double and the Rosetta
integer parser), and asserts the Rosetta path is bit-identical to the strtod oracle. It
requires the compiled kernel and the real data, so it only runs in the container:
docker compose exec iris python3 tests/test_ckernel.py # no dependencies (stock image)
docker compose exec iris python3 -m pytest tests/ -v # if pytest is installed
| Path | What |
|---|---|
src/RunScript.mac |
ObjectScript entrypoint the graders run (do ^RunScript) |
src/gaia/ckernel.pyx |
the whole engine — glob + OpenMP scan + write, all in C |
scripts/build_kernel.sh |
compiles ckernel into the image at build time |
scripts/setup_web.sh |
provisions the web UI apps on the IRIS web server |
web/index.html |
the interactive 3D galaxy (Three.js) |
tests/test_ckernel.py |
C-kernel parity test: validates output against pure-Python oracle |
iris.script |
build-time setup; compiles src/*.mac into USER |
data/in/ |
the 20 benchmark .csv.gz files |
data/out/results.csv |
generated output (gitignored) |
docs/ |
design spec |
csv/float handle them with almost no code for the reference path, and