# A conditional NIRISS atmospheric retrieval This folder is a standalone scientific exercise. It needs no private repository, Lab runtime, account or network after the materials and NumPy are installed. The measured input is the author-released nirHiss/CMADF WASP-39 b NIRISS spectrum. The atmospheric predictions and the separate known-truth recovery are synthetic. ## Download and unpack four public archives Download all four files from this same public URL prefix: https://sandboxphysics.com/stories/planet-atmospheres/materials/ 1. niriss-retrieval-materials.zip — scripts, measured bins, stellar spectra, expected posteriors, provenance and the complete checksums; 2. niriss-opacity-source.zip — actual extracted native molecular opacity; 3. niriss-grid-part1.zip — first validated model-grid chunk; 4. niriss-grid-part2.zip — second validated model-grid chunk. Each is a real ZIP below 25 MiB, with delivery margin. Put them in a fresh ordinary directory, unpack all four into that same directory, then run: ```sh unzip -n niriss-retrieval-materials.zip unzip -n niriss-opacity-source.zip unzip -n niriss-grid-part1.zip unzip -n niriss-grid-part2.zip python3 assemble_grid.py . ``` The assembler checks the complete ordered chunk list, each byte count and SHA256, contiguous offsets, total length and final grid hash before publishing the result. Missing, swapped or changed chunks fail. The large raw grid has no direct public static URL. No download or private code is needed to assemble it. Continue with the commands below in this same directory. The public URL prefix also provides README.md, provenance.json, comparison.json and explicitly allowlisted individual scientific files. ### Named anonymous download client You can use the four browser download links above, or run this standard-library client in a fresh ordinary directory: ```sh curl -fL -A 'SandboxPhysics-Public-Tutorial/1.0' https://sandboxphysics.com/stories/planet-atmospheres/materials/download_materials.py -o download_materials.py python3 download_materials.py . python3 assemble_grid.py . ``` The named User-Agent is explicit because the deployment edge can reject the default Python urllib identity. The client fetches delivery-manifest.json, checks all four archive lengths, SHA256 and media types, then unpacks them. It distinguishes verified local cache from actual HTTP requests in its receipt. Local ZIP reconstruction and numerical reruns are independent of production network delivery; the release acceptance checks actual anonymous production URLs separately. Server security policies are not changed for this exercise. ## Tested environment and commands Tested with CPython 3.9.6 and NumPy 2.0.2 on macOS arm64. The source uses NumPy and the Python standard library. requirements.txt pins the tested NumPy version. Use a Python environment that can install this version; a different platform may change floating-point proposal decisions and hence a seeded Monte Carlo path. Run in the unpacked folder: ```sh python3 -m pip install -r requirements.txt python3 verify_inputs.py . python3 validate_grid.py --materials . --output rerun-validation python3 analyze.py --materials . --output rerun python3 verify_outputs.py --expected expected --actual rerun python3 verify_science.py --materials . --output rerun-checks --synthetic ``` The first command after installation checks every delivered input, script and expected output against hashes.json. The grid check recomputes 77 frozen cases from native extracted opacity with both the production 384-layer and independent cloud-bounded 1280-layer quadrature. analyze.py runs four proper posterior models. The final command checks independent transfer and sampling limits and performs a separate native-generated synthetic recovery. Output directories are independent of the frozen inputs. No network requests occur in these programs. The optional full native grid rebuild is substantially slower: ```sh python3 rebuild_grid.py --materials . --output rebuilt-grid ``` It performs 2975 complete native gas-column solves and checks the resulting float32 grid bytes against the frozen hash. Use a fresh output directory. This rebuild is optional for rerunning the posterior but exposes the grid construction. ## Actual measurement and bin selection The unchanged original CSV is 11063 bytes, SHA256 99ef37ff99938b95aafc097a9196f1057b0a1ec874318c2f35399c34b47277a1. It comes from author repository commit 0608071e1e70ec7ff12707774ea03ace4b52ea85, archived at Zenodo 7709712. The repository carries an MIT license; the archive is CC BY 4.0. The original license is retained in licenses/niriss-author-MIT.txt. Select order=1, quality=0 and bins whose full wave +/- wave_error interval lies within 0.87--2.00 micrometres. This yields the same 74 bins in every fit. The reported dppm and dppm_err are in ppm. wave_error is a horizontal halfwidth, consistent with the author's plotting script. The filename says R100 but the generic header says Native; the numeric widths imply R about 82.8--94.7. We retain these labels, integrating each supplied interval independently as an approximate top-hat response. It is not a recovered instrument throughput or line-spread function. The input is a fitted radius-ratio-squared spectrum after upstream limb-darkening treatment, not raw photon counts or a new light-curve fit. ## Defined forward model The atmosphere is spherical, isothermal and hydrostatic in a prescribed inverse-square planet potential, with a ten-bar reference radius and a finite 1e-10 bar top. Its background particles are 85 percent H2 and 15 percent He by number; a constant water number fraction replaces that background. Mean particle mass changes with water fraction. The fixed planet mass is 0.28 Jupiter masses; the stellar radius is 0.932 solar radii. All transfer calculations use SI units. The actual ExoMolOP POKAZATEL product provides pressure-dependent molecular cross sections. The original HDF5 is 365310072 bytes, has xsecarr shape (22, 27, 76744), float64 in square centimetres per molecule, no compression or chunks, and data offset 622568. Exact ranges retain 22 native pressures, nine 800--1600 K temperature rows and 15084 wavenumber samples. The misleadingly named bin_edges coordinate contains sample wavenumbers, as confirmed by the official TauREx reader. Input conversion is cm2/molecule to m2/molecule by 1e-4. Log opacity interpolates linearly in temperature and log pressure. Below 1e-5 bar, the lowest source pressure opacity is frozen while density keeps falling. Unsupported zero or nonfinite source opacity is rejected rather than silently floored. The native sampled optical depth is integrated through exact shell chord lengths with midpoint extinction in 384 pressure shells. Each native blocked area is formed before photon-weighted binning. Moving a gray opaque cloud masks paths through the same full gas column. Photon weights use the actual fixed PHOENIX 5500 K photosphere. Frozen 3500/4500 K unocculted cool spectra change the stellar denominator, with an immaculate transit chord and uniform component intensities. The original stellar headers are nm and erg/cm2/s/nm. Common surface-flux normalization is retained. The licensed Zenodo 17674612 version 1.0 derivative has effective resolving power 5000; oversampling does not increase it. CIA, other absorbers, non-gray clouds, aerosol scattering, refraction, emission, escape and a three-dimensional terminator are omitted. The source opacity has sampled R15000. Numerical convergence within that product is not a guarantee of resolved-line physical accuracy. Top-boundary and low-pressure choices are sensitivity envelopes, not rigorous bounds on all physical model error. ## Observable grid and separated numerical checks The inference grid contains transferred and photon-binned planetary depth minus the exact reference-radius-squared baseline. Its axes have 17 temperatures, 25 log water fractions, 7 reference radius ratios, 41 log cloud pressures and 74 observational bins. Temperature interpolation stays inside each native 100 K source interval; the other axes use four-node local interpolation. Extrapolation is forbidden. Stellar contamination uses the exact bin-integrated flux ratio. An initial water axis failed an independent high-water case at 2.02564 ppm. Adding four water-abundance axis values required 476 additional complete native columns, increasing 2499 to 2975. No posterior used the failed grid. Final SHA256: 8f69b678e85120e7f4398191bf7af3c0a6c47b1d6bc6173b591346e92b08ed61. Across 77 validation points, maximum grid-native384 disagreement is 0.42462 ppm; maximum grid-independent1280 disagreement is 1.63577 ppm. At two difficult states, the grid differs from an additional 2048-layer reference by at most 1.72539 ppm. These are comparisons with declared finite quadratures, not a rigorous absolute bound relative to a continuous physical atmosphere. These are numerical comparisons, not extra Gaussian noise or a calibrated model-discrepancy prior. Separate records retain radial refinement, the original sparse-pressure failure, finite-top sensitivity and browser logarithmic-input quantization. The browser encoding differs from the Python64 final band depth by at most 0.01445 ppm over 21 corner/preset and 16 withheld states. The Python posterior does not use that browser encoding. The finite-top sensitivity is not part of this codec error. Across five presets, every-other-wavelength source sampling changes bins by about 40--145 ppm, comparable to or larger than reported measurement errors. Omitting an actual source temperature row changes bins by about 3.4--31.8 ppm. These are sensitivities of coarser representations, not inferred Gaussian noise or a rigorous bound on the exact higher-resolution spectrum. All posteriors remain conditional on the complete frozen source product and specified T/P interpolation. source_sensitivity.py recomputes these separate comparisons. ### Retained failure of the earlier coarse reference The earlier 320-layer grid appeared below two ppm against a 640/960-layer reference, but two cases reached 2.132614 and 2.085434 ppm against 1280 layers. The actual cases and old grid metadata are retained in validation/. Production now consistently uses 384 layers and the stated independent 1280-layer reference. The historical metadata is marked retired and cannot authorize a new posterior. This is separate from the earlier water-axis refinement and source sensitivities. ```sh python3 finer_reference.py --materials . --output rerun-finer ``` That command recomputes the old native 320-layer failure and the production 384-layer/model-grid comparisons against 1280 and 2048 layers at the two difficult states. To reconstruct the entire retired grid for the historical interpolation counterexample, use its explicitly selected metadata: ```sh python3 rebuild_grid.py --materials . --metadata validation/grid-320-history-metadata.json --output retired-grid ``` The optional historical reconstruction retains its original hash and is a failure reproduction, not an inference input. ## Proper posterior and retained failure The likelihood is the normalized product of 74 independent Gaussians with the reported sigma values. Unknown inter-bin covariance is assumed zero. There is no fitted jitter or noise inflation. All priors have finite support: - temperature: uniform 800--1600 K; - log10 water fraction: uniform -7 to -2; - log10 cloud pressure in bar: uniform -4 to 1; - radius ratio at ten bar: uniform 0.130--0.145; - cool fraction: zero in cloud; uniform 0--0.05 in spots4500 and spots3500; uniform 0--0.01 in spots4500-narrow. The fixed cool-region temperatures are conditions, not independently measured stellar coverage. Log-uniform water is not uniform linear water abundance. A deterministic radius anchor plus 1e-5*z is only a coordinate change; it retains the exact original finite uniform radius prior and constant triangular Jacobian. There is no Gaussian prior or arbitrary truncation on z. Correlated Gaussian proposals outside the unit-box prior are rejected, never reflected. Four chains adapt their Gaussian random-walk covariance and scale only during 6000 warmup iterations. They then retain 16000 correlated positions per chain; the algorithm extends if necessary to reach rank/folded split R-hat <= 1.01 and bulk/tail ESS >= 400 for every varying parameter. Total retained positions and ESS are different quantities. Diagnostics use all retained positions without thinning. Full physical and computational chains are saved. The delivered real-data models all pass the sampling targets and all fit poorly. Minimum retained chi-square is about 332, 257, 248 and 279 for cloud, spots4500, spots3500 and spots4500-narrow. The central 95 percent replicated-measurement interval misses 28, 23, 20 and 28 actual points respectively. Temperature and water abundance crowd prior boundaries. These restricted atmospheric models omit important physics, and data covariance is unknown. A positive cool-fraction interval does not test the point-null f=0: that point already has probability zero under a continuous positive prior. No evidence or Bayes factor is computed. The original publication used richer atmospheric models. Prediction CSVs distinguish a latent mean interval from replicated noisy measurements and retain signed standardized residuals. verify_outputs.py checks the same priors, bins, diagnostic targets and stated Monte Carlo tolerances; exact chain bytes are not a convergence diagnostic. The actual Metropolis sampler also reproduces the known mean and covariance of a correlated four-dimensional Gaussian (separate from its IID and AR(1) diagnostic tests). The known-truth atmospheric recovery is separate synthetic data, with a fixed off-grid native atmosphere and noise seed. Its successful recovery is one case, not a coverage study. ## Attribution and permissions See provenance.json and licenses/ATTRIBUTION.md. ExoMol opacity extractions, encodings and opacity-derived forward grids retain CC BY-SA 4.0. PHOENIX members from the explicitly licensed Zenodo derivative retain CC BY 4.0. NIRISS original bytes retain the author's MIT notice and the archive's CC BY 4.0 attribution. New standalone scientific Python scripts are supplied under the MIT text in licenses/scientific-scripts-MIT.txt. They contain no Lab Engine source or compiled browser runtime. No paper figures are redistributed.