### Quick Start: Load Spectra and Prepare Data Source: https://github.com/theskyentist/unite/blob/main/README.md This snippet shows how to load spectral data using a specific instrument configuration (JWST/NIRSpec G395M in this example) and prepare it for modeling. It computes necessary scales for error estimation. ```python # 2. Load spectra (NIRSpec example; any instrument works) g395m = nirspec.G395M() spec = from_DJA('dja-spectrum.fits', disperser=g395m) spectra = Spectra([spec], redshift=5.28) filtered_lines, filtered_cont = spectra.prepare(lc, cc) spectra.compute_scales(filtered_lines, filtered_cont, error_scale=True) ``` -------------------------------- ### Install Unite from Source using Pip Source: https://github.com/theskyentist/unite/blob/main/docs/contributing.md Clone the repository and install the project with development dependencies using pip. ```bash git clone https://github.com/TheSkyentist/unite.git cd unite pip install -e ".[dev]" ``` -------------------------------- ### Quick Start: Fit Emission Lines in a Simulated Spectrum Source: https://github.com/theskyentist/unite/blob/main/docs/installation.md This example demonstrates fitting three emission lines (H-alpha and [NII] doublet) in a simulated spectrum using Unite. It includes spectrum simulation, model building, and MCMC sampling. ```python import jax jax.config.update('jax_enable_x64', True) import astropy.units as u import numpy as np from numpyro import infer from unite import line, model, prior from unite.continuum import ContinuumConfiguration, Linear from unite.disperser.generic import SimpleDisperser from unite.results import make_hdul, make_parameter_table from unite.spectrum import Spectra, Spectrum # --- Simulate a spectrum --- rng = np.random.default_rng(42) wavelength = np.linspace(6400, 6700, 300) * u.AA wl = wavelength.value sigma = 5.0 / (2 * np.sqrt(2 * np.log(2))) flux = ( 80 * np.exp(-0.5 * ((wl - 6563.0) / sigma) ** 2) + 30 * np.exp(-0.5 * ((wl - 6549.0) / sigma) ** 2) + 90 * np.exp(-0.5 * ((wl - 6585.0) / sigma) ** 2) + 10.0 + rng.normal(0, 2, len(wl)) ) error = np.full_like(flux, 2.0) low = wavelength - 0.5 * np.gradient(wavelength) high = wavelength + 0.5 * np.gradient(wavelength) # --- Build the model --- disperser = SimpleDisperser(wavelength=wl, unit=u.AA, R=3000.0, name='sim') spectrum = Spectrum(low=low, high=high, flux=flux, error=error, disperser=disperser) z = line.Redshift('z', prior=prior.Uniform(-0.005, 0.005)) fwhm = line.FWHM('fwhm', prior=prior.Uniform(1.0, 10.0)) lc = line.LineConfiguration() lc.add_line('H_alpha', 6563.0 * u.AA, redshift=z, fwhm_gauss=fwhm, flux=line.Flux('Ha_flux', prior=prior.Uniform(0, 5))) lc.add_line('NII_6585', 6585.0 * u.AA, redshift=z, fwhm_gauss=fwhm, flux=line.Flux('NII6585_flux', prior=prior.Uniform(0, 5))) lc.add_line('NII_6549', 6549.0 * u.AA, redshift=z, fwhm_gauss=fwhm, flux=line.Flux('NII6549_flux', prior=prior.Uniform(0, 5))) cc = ContinuumConfiguration.from_lines(lc.centers, pad=0.05, form=Linear()) spectra = Spectra([spectrum], redshift=0.0) filtered_lines, filtered_cont = spectra.prepare(lc, cc) spectra.compute_scales(filtered_lines, filtered_cont, error_scale=True) # --- Sample --- builder = model.ModelBuilder(filtered_lines, filtered_cont, spectra) model_fn, model_args = builder.build() mcmc = infer.MCMC(infer.NUTS(model_fn), num_warmup=200, num_samples=500) mcmc.run(jax.random.PRNGKey(0), model_args) # --- Results --- table = make_parameter_table(mcmc.get_samples(), model_args) print(table['z', 'fwhm', 'Ha_flux']) ``` -------------------------------- ### Set up Development Environment with Pixi Source: https://github.com/theskyentist/unite/blob/main/docs/contributing.md Clone the repository and install dependencies using Pixi, which manages both the Python environment and common tasks. ```bash git clone https://github.com/TheSkyentist/unite.git cd unite pixi install ``` -------------------------------- ### Install Unite using uv Source: https://github.com/theskyentist/unite/blob/main/docs/installation.md Install the Unite package using uv, a fast Python package installer. ```bash uv pip install unite ``` -------------------------------- ### Install JAXNS Source: https://github.com/theskyentist/unite/blob/main/docs/usage/inference.md Install the JAXNS library, a JAX-native nested sampler, which is used by NumPyro's contrib module. ```bash pip install jaxns ``` -------------------------------- ### Quick Start: Extract Results Source: https://github.com/theskyentist/unite/blob/main/README.md This snippet indicates where to extract and process the results from the MCMC run. The actual extraction functions are imported but not shown in this minimal example. ```python # 4. Extract results ``` -------------------------------- ### Install Unite using pip Source: https://github.com/theskyentist/unite/blob/main/docs/installation.md Install the Unite package using pip. This is the most common installation method. ```bash pip install unite ``` -------------------------------- ### Run All Benchmarks Source: https://github.com/theskyentist/unite/blob/main/benchmarks/README.md Execute the full suite of benchmarks, including slow ones. Use this to get a comprehensive performance overview. ```bash pixi run bench # all benchmarks ``` -------------------------------- ### Install Unite using pixi Source: https://github.com/theskyentist/unite/blob/main/docs/installation.md Install the Unite package using pixi, a package manager for reproducible environments. ```bash pixi add unite --pypi ``` -------------------------------- ### Example YAML Configuration Source: https://github.com/theskyentist/unite/blob/main/docs/usage/serialization.md A human-readable YAML representation of a two-line configuration, demonstrating line definitions, shared token references, and continuum regions. ```yaml lines: lines: - name: H_alpha center: 6563.0 AA profile: Gaussian redshift: name: nlr_z prior: {type: Uniform, low: -0.005, high: 0.005} fwhm_gauss: name: nlr_fwhm prior: {type: Uniform, low: 1.0, high: 10.0} flux: name: Ha_flux prior: {type: Uniform, low: 0, high: 5} - name: NII_6585 center: 6585.0 AA profile: Gaussian redshift: {ref: nlr_z} # ← shared token reference fwhm_gauss: {ref: nlr_fwhm} # ← shared token reference flux: name: NII6585_flux prior: {type: Uniform, low: 0, high: 5} continuum: regions: - low: 6241.85 AA high: 6931.05 AA form: {type: Linear} ``` -------------------------------- ### ArviZ Integration Example (Commented) Source: https://github.com/theskyentist/unite/blob/main/docs/usage/results.md Shows how to integrate with ArviZ for advanced diagnostics, including converting NumPyro MCMC objects and extracting log-likelihoods. This snippet is commented out. ```python import arviz as az # NUTS — pass the mcmc object directly; ArviZ extracts samples and log-likelihood # idata = az.from_numpyro(mcmc, log_likelihood=log_liks) ``` -------------------------------- ### Run Default Interactive Profiling Source: https://github.com/theskyentist/unite/blob/main/benchmarks/README.md Starts interactive profiling with default settings, generating a Perfetto trace for the 'single_grating' config. ```bash pixi run profile # default: single_grating config, writes Perfetto trace ``` -------------------------------- ### Quick Start: Configure Lines and Continuum Source: https://github.com/theskyentist/unite/blob/main/README.md This snippet demonstrates how to configure emission and absorption lines with shared kinematics (redshift and FWHM) and set up a linear continuum model. It uses JAX, Astropy, and NumPyro components from the 'unite' library. ```python import jax import astropy.units as u from numpyro import infer from unite import line, model, prior from unite.continuum import ContinuumConfiguration, Linear from unite.instrument import nirspec from unite.results import make_parameter_table, make_spectra_tables from unite.spectrum import Spectra, from_DJA # 1. Configure lines with shared kinematics z = line.Redshift('z', prior=prior.Uniform(-0.005, 0.005)) fwhm = line.FWHM('narrow', prior=prior.Uniform(100, 1000)) lc = line.LineConfiguration() lc.add_line( 'H_alpha', 6563.0 * u.AA, redshift=z, fwhm_gauss=fwhm, flux=line.Flux(prior=prior.Uniform(0, 10)) ) lc.add_line( 'NII_6585', 6585.0 * u.AA, redshift=z, fwhm_gauss=fwhm, flux=line.Flux(prior=prior.Uniform(0, 10)) ) # Tau-parametrized absorption line: transmission = exp(-tau * phi) lc.add_line( 'HI_abs', 6563.0 * u.AA, redshift=z, fwhm_gauss=line.FWHM('abs', prior=prior.Uniform(50, 500)), tau=line.Tau(prior=prior.Uniform(0, 5)) ) cc = ContinuumConfiguration.from_lines(lc.centers, width=15_000*u.km/u.s, form=Linear()) ``` -------------------------------- ### Quick Start: Build and Run Inference Model Source: https://github.com/theskyentist/unite/blob/main/README.md This snippet demonstrates building the 'unite' inference model and running it using NumPyro's NUTS sampler. It highlights the `integration_mode` parameter for controlling line profile integration. ```python # 3. Build and run with any NumPyro sampler # integration_mode='analytic' (default) uses exact CDF integration; # integration_mode='convolution' convolves intrinsic model with LSF on a fine grid # (n_super uniform points per pixel) — most accurate for absorption lines builder = model.ModelBuilder(filtered_lines, filtered_cont, spectra) model_fn, model_args = builder.build(integration_mode='analytic') mcmc = infer.MCMC(infer.NUTS(model_fn), num_warmup=500, num_samples=1000) mcmc.run(jax.random.PRNGKey(0), model_args) ``` -------------------------------- ### Configure Dispersers and Load Spectra Source: https://github.com/theskyentist/unite/blob/main/docs/concepts.md Sets up instrument dispersers and loads spectral data. This example demonstrates configuring JWST/NIRSpec dispersers and loading spectra from FITS files. ```python from unite.instrument import nirspec from unite.spectrum import Spectra # Configure dispersers g235h = nirspec.G235H() g395m = nirspec.G395M() # Load spectra (NIRSpec example) spectrum1 = nirspec.NIRSpecSpectrum.from_DJA('g235h.fits', disperser=g235h) spectrum2 = nirspec.NIRSpecSpectrum.from_DJA('g395m.fits', disperser=g395m) # Wrap in Spectra container spectra = Spectra([spectrum1, spectrum2], redshift=5.28) ``` -------------------------------- ### Initialize and Run NUTS Sampler Source: https://github.com/theskyentist/unite/blob/main/docs/usage/inference.md Initializes the NUTS sampler with a model function and runs MCMC. `dense_mass=True` is recommended for correlated parameters. This example shows basic NUTS usage. ```python import jax from numpyro import infer kernel = infer.NUTS(model_fn, dense_mass = True) # dense_mass=True helps with correlated parameters mcmc = infer.MCMC( kernel, num_warmup=500, num_samples=1000, progress_bar=True, ) mcmc.run(jax.random.PRNGKey(0), model_args) samples = mcmc.get_samples() ``` -------------------------------- ### Get Unite Version Source: https://github.com/theskyentist/unite/blob/main/docs/contributing.md Import the unite library and print its version to include in issue reports. ```python import unite print(unite.__version__) ``` -------------------------------- ### Fixed Prior Example Source: https://github.com/theskyentist/unite/blob/main/docs/usage/priors.md Sets a parameter to a constant, non-sampled value. Useful for fixing ratios or calibration parameters to known theoretical values. ```python p = prior.Fixed(6564.61) ``` -------------------------------- ### Create Empty Line Configuration Source: https://github.com/theskyentist/unite/blob/main/docs/usage/line_configuration.md Initialize an empty LineConfiguration object. This is the starting point for defining emission lines. Requires importing the line and prior modules from unite, and astropy.units. ```python from unite import line, prior from astropy import units as u lc = line.LineConfiguration() ``` -------------------------------- ### YAML Serialization of Priors Source: https://github.com/theskyentist/unite/blob/main/docs/usage/priors.md Shows how priors with parameter expressions are serialized into YAML. This includes examples of single-token references and compound arithmetic operations. ```yaml # fwhm_narrow + 150 fwhm_broad: prior: type: Uniform low: {op: '+', left: {ref: fwhm_gauss_narrow}, right: 150.0} high: 5000.0 # flux_4363_narrow * flux_5007_broad / flux_5007_narrow flux_4363_broad: prior: type: Fixed value: op: / left: op: '*' left: {ref: flux_4363_narrow} right: {ref: flux_5007_broad} right: {ref: flux_5007_narrow} ``` -------------------------------- ### BibTeX Citation for Unite (Zenodo Release) Source: https://github.com/theskyentist/unite/blob/main/CITATION.md This is an example BibTeX entry for citing a specific version of the unite software release archived on Zenodo. Visit the provided DOI link to obtain the exact entry for your desired version. ```bibtex @software{hviding_unite, author = {Hviding, Raphael Erik}, title = {{unite}: Unified liNe Integration Turbo Engine}, publisher = {Zenodo}, doi = {10.5281/zenodo.15585034}, url = {https://doi.org/10.5281/zenodo.15585034} } ``` -------------------------------- ### Select Specific GPU Device for Inference Source: https://github.com/theskyentist/unite/blob/main/docs/usage/inference.md Demonstrates how to explicitly select a GPU device for running MCMC inference using a context manager. Ensure JAX is installed with CUDA support and a GPU is available. ```python # Select a specific device with jax.default_device(jax.devices('gpu')[0]): mcmc.run(jax.random.PRNGKey(0), model_args) ``` -------------------------------- ### Deep Dependency Chains Example Source: https://github.com/theskyentist/unite/blob/main/docs/usage/priors.md Demonstrates arbitrarily deep dependency chains for priors, where each FWHM parameter depends on the previous one. Topological sorting ensures correct sampling order. ```python fwhm_narrow = line.FWHM('n', prior=prior.Uniform(50, 500)) fwhm_broad = line.FWHM('b', prior=prior.Uniform(fwhm_narrow + 150, 3000)) fwhm_very_broad = line.FWHM('vb', prior=prior.Uniform(fwhm_broad + 200, 5000)) ``` -------------------------------- ### Configure Emission Line Source: https://github.com/theskyentist/unite/blob/main/docs/concepts.md Example of adding an emission line to a LineConfiguration, specifying its name, rest-frame center, redshift, FWHM, and flux prior. ```python from unite import line, prior from astropy import units as u lc = line.LineConfiguration() lc.add_line( name='H_alpha', center=6563.0 * u.AA, redshift=z, fwhm_gauss=fwhm, flux=line.Flux('Ha_flux', prior=prior.Uniform(0, 10)), profile='Gaussian', # default ) ``` -------------------------------- ### Get Summary Statistics at Specific Percentiles Source: https://github.com/theskyentist/unite/blob/main/README.md This snippet demonstrates how to obtain summary statistics for model parameters and spectra at specified percentiles. Ensure you have the necessary samples and model arguments defined. ```python samples = mcmc.get_samples() param_table = make_parameter_table(samples, model_args, percentiles=[0.16, 0.5, 0.84]) spectra_tables = make_spectra_tables(samples, model_args, percentiles=[0.16, 0.5, 0.84]) ``` -------------------------------- ### Run NUTS with Multiple Chains for Convergence Assessment Source: https://github.com/theskyentist/unite/blob/main/docs/usage/inference.md Configures and runs MCMC using NUTS with multiple chains (4 in this example) to facilitate convergence assessment using metrics like R-hat. Parallel chain execution is efficient on GPUs. ```python mcmc = infer.MCMC( infer.NUTS(model_fn), num_warmup=500, num_samples=1000, num_chains=4, progress_bar=True, ) mcmc.run(jax.random.PRNGKey(0), model_args) ``` -------------------------------- ### Share Parameters Across Multiple Continuum Regions Source: https://github.com/theskyentist/unite/blob/main/docs/usage/continuum_configuration.md Example of defining shared Scale, ContShape, and NormWavelength parameters using the same Parameter instances across two different ContinuumRegions. This couples the regions to a single sampled value for global fitting. ```python from unite import continuum from unite.prior import Uniform, Fixed from astropy import units as u pl = continuum.PowerLaw() shared_scale = continuum.Scale('pl', prior=Uniform(0, 10)) shared_beta = continuum.ContShape('pl', prior=Uniform(-5, 5)) shared_nw = continuum.NormWavelength('pl', prior=Fixed(1.25)) cc = continuum.ContinuumConfiguration([ continuum.ContinuumRegion( 0.9 * u.um, 1.4 * u.um, form=pl, params={ 'scale': shared_scale, 'beta': shared_beta, 'norm_wav': shared_nw }, ), continuum.ContinuumRegion( 1.7 * u.um, 2.5 * u.um, form=pl, params={ 'scale': shared_scale, 'beta': shared_beta, 'norm_wav': shared_nw }, ), ]) ``` -------------------------------- ### Set Up Multi-Component Models with Shared Parameters Source: https://github.com/theskyentist/unite/blob/main/docs/usage/line_configuration.md Demonstrates how to define multiple lines with the same name but different parameters, utilizing shared tokens where appropriate for multi-component modeling. ```python z = line.Redshift('nlr', prior=prior.Uniform(-0.01, 0.01)) fwhm_n = line.FWHM('narrow', prior=prior.Uniform(50, 400)) fwhm_b = line.FWHM('broad', prior=prior.Uniform(500, 3000)) lc.add_line('H_alpha', 6563.0 * u.AA, redshift=z, fwhm_gauss=fwhm_n, flux=line.Flux('Ha_n', prior=prior.Uniform(0, 10))) lc.add_line('H_alpha', 6563.0 * u.AA, redshift=z, fwhm_gauss=fwhm_b, flux=line.Flux('Ha_b', prior=prior.Uniform(0, 10))) ``` -------------------------------- ### Get Per-Spectrum Model Tables Source: https://github.com/theskyentist/unite/blob/main/docs/usage/results.md Retrieve a dictionary of model tables, keyed by spectrum name. Each table contains the model decomposed into individual components. You can get all posterior samples or specific percentiles. ```python import numpy as np # Get all posterior samples tables = make_spectra_tables(samples, model_args) # OR get specific percentiles percentiles = np.array([0.16, 0.5, 0.84]) tables = make_spectra_tables(samples, model_args, percentiles=percentiles) # Access by spectrum name t = tables['my_spectrum'] # Or iterate over all spectra for name, t in tables.items(): print(name) # spectrum name (same as t.meta['SPECNAME']) print(t.colnames) ``` -------------------------------- ### Check JAX Devices and Backend Source: https://github.com/theskyentist/unite/blob/main/docs/usage/inference.md Prints the available JAX devices (e.g., GPU, CPU) and the default backend being used. This helps verify GPU acceleration is active. ```python import jax print(jax.devices()) # e.g. [CudaDevice(id=0)] print(jax.default_backend()) # 'gpu', 'cpu', or 'tpu' ``` -------------------------------- ### Get MCMC Samples Source: https://github.com/theskyentist/unite/blob/main/docs/usage/results.md Retrieves posterior samples from an MCMC object. This is a prerequisite for generating output tables. ```python from unite.results import make_parameter_table, make_spectra_tables, make_hdul samples = mcmc.get_samples() # dict of str → ndarray, shape (n_samples,) ``` -------------------------------- ### Initialize NUTS with SVI Results Source: https://github.com/theskyentist/unite/blob/main/docs/usage/inference.md Use the parameters obtained from a converged SVI run as the initial values for NUTS. This can significantly reduce the number of warmup steps required for NUTS, especially in complex models. ```python from numpyro.infer import init_to_value # 1. Run SVI to convergence (see above) params = svi_result.params # 2. Pass to NUTS via init_to_value kernel = infer.NUTS(model_fn, init_strategy=init_to_value(values=init_values)) mcmc = infer.MCMC(kernel, num_warmup=50, num_samples=1000) mcmc.run(jax.random.PRNGKey(1), model_args) samples = mcmc.get_samples() ``` -------------------------------- ### Get Functional Form from Registry Source: https://github.com/theskyentist/unite/blob/main/docs/usage/continuum_configuration.md Programmatically retrieve functional forms from the built-in registry, allowing for dynamic instantiation with specific parameters. ```python from unite.continuum import get_form form = get_form('Polynomial', degree=3) ``` -------------------------------- ### Create a Configuration Container Source: https://github.com/theskyentist/unite/blob/main/docs/usage/serialization.md Instantiate a `Configuration` object, which bundles lines, continuum, and dispersers. Ensure necessary configuration objects are imported. ```python from unite.config import Configuration from unite.instrument.config import InstrumentConfig config = Configuration( lines=lc, # LineConfiguration continuum=cc, # ContinuumConfiguration (optional) dispersers=dc, # InstrumentConfig (optional) ) ``` -------------------------------- ### Convert Configuration to Dictionary Source: https://github.com/theskyentist/unite/blob/main/docs/usage/serialization.md Demonstrates converting a configuration object to a dictionary for programmatic manipulation. ```python d = config.to_dict() # Modify the dict... config2 = Configuration.from_dict(d) ``` -------------------------------- ### Import Calibration Tokens Source: https://github.com/theskyentist/unite/blob/main/docs/usage/instrument.md Import necessary calibration token classes from the `unite.instrument` module. ```python from unite.instrument import RScale, FluxScale, PixOffset ``` -------------------------------- ### Uniform Prior Example Source: https://github.com/theskyentist/unite/blob/main/docs/usage/priors.md Defines a flat prior distribution between a specified low and high bound. Useful for parameters with no strong prior expectation. ```python from unite import prior p = prior.Uniform(low=0.0, high=1000.0) ``` -------------------------------- ### TruncatedNormal Prior Example Source: https://github.com/theskyentist/unite/blob/main/docs/usage/priors.md Defines a Gaussian distribution truncated to a specific range [low, high]. Suitable for parameters with a prior expectation around a central value. ```python p = prior.TruncatedNormal(loc=1.0, scale=0.05, low=0.8, high=1.2) ``` -------------------------------- ### Benchmark with JAX JIT Warm-up Source: https://github.com/theskyentist/unite/blob/main/benchmarks/README.md Illustrates warming the JIT cache before the timed benchmark call to avoid measuring compilation overhead. ```python fn = jax.jit(...) fn(args).block_until_ready() # compile here benchmark(lambda: block(fn(args))) # measure here ``` -------------------------------- ### Dependent Prior: FWHM Example Source: https://github.com/theskyentist/unite/blob/main/docs/usage/priors.md Demonstrates a dependent prior where the lower bound of 'fwhm_broad' is defined relative to 'fwhm_narrow'. This creates a dependency chain resolved at build time. ```python from unite import line, prior fwhm_narrow = line.FWHM('narrow', prior=prior.Uniform(50, 500)) # Broad component must be at least 150 km/s wider fwhm_broad = line.FWHM('broad', prior=prior.Uniform(fwhm_narrow + 150, 5000)) ``` -------------------------------- ### Save and Load Combined Configuration Source: https://github.com/theskyentist/unite/blob/main/docs/usage/serialization.md Shows how to save a combined configuration to a YAML file and then restore it. ```python cfg_combined = cfg1 + cfg2 cfg_combined.save('combined.yaml') cfg_restored = Configuration.load('combined.yaml') ``` -------------------------------- ### Combine Configurations with Strict Merging Source: https://github.com/theskyentist/unite/blob/main/docs/usage/serialization.md Demonstrates combining two configurations. Raises ValueError if token names conflict. ```python try: cfg_combined = cfg1 + cfg2 except ValueError as e: print(f"Name collision: {e}") ``` -------------------------------- ### Initialize ModelBuilder Source: https://github.com/theskyentist/unite/blob/main/docs/usage/build_model.md Initialize the ModelBuilder with filtered spectral lines, continuum, and spectra data. This prepares the data for model building. ```python from unite import model builder = model.ModelBuilder(filtered_lines, filtered_cont, spectra) model_fn, model_args = builder.build() ``` -------------------------------- ### Combine Configurations with Missing Sub-Configs Source: https://github.com/theskyentist/unite/blob/main/docs/usage/serialization.md Illustrates how configuration combination handles cases where one configuration lacks a sub-component (e.g., continuum). The non-None component is preserved. ```python cfg1 = Configuration(lines_1, continuum_1) # has continuum cfg2 = Configuration(lines_2) # no continuum cfg_combined = cfg1 + cfg2 # cfg_combined.continuum is continuum_1 ``` -------------------------------- ### Save and Load Configuration for Offline Editing Source: https://github.com/theskyentist/unite/blob/main/docs/usage/serialization.md Illustrates saving a configuration to YAML, editing it manually, and then reloading it. ```python # First pass — broad priors config.save('fit_v1.yaml') # Edit fit_v1.yaml in your editor, then: config_v2 = Configuration.load('fit_v1.yaml') ``` -------------------------------- ### Define Continuum Region with Custom Priors Source: https://github.com/theskyentist/unite/blob/main/docs/usage/continuum_configuration.md Example of creating a ContinuumRegion with a PowerLaw form and custom TruncatedNormal and Uniform priors for scale and beta parameters. The norm_wav parameter retains its default prior. ```python from unite import continuum from unite.prior import TruncatedNormal, Uniform, Fixed from astropy import units as u region = continuum.ContinuumRegion( 1.0 * u.um, 1.5 * u.um, form=continuum.PowerLaw(), params={ 'scale': continuum.Scale('pl', prior=TruncatedNormal(low = 0, high = 2.0, loc=1, scale=0.1)), 'beta': continuum.ContShape('pl', prior=Uniform(-3.0, 0.0)), # 'norm_wav' keeps its default Fixed(region_center) prior }, ) cc = continuum.ContinuumConfiguration([region]) ``` -------------------------------- ### Combine Full Configurations Source: https://github.com/theskyentist/unite/blob/main/docs/usage/serialization.md Demonstrates combining two `Configuration` objects using the `+` operator. The resulting configuration merges lines, continuum regions, and dispersers from both inputs. ```python # Create two independent configurations cfg1 = Configuration(lines_1, continuum_1, dispersers_1) cfg2 = Configuration(lines_2, continuum_2, dispersers_2) # Combine them cfg_combined = cfg1 + cfg2 ``` -------------------------------- ### Dependent Prior: Flux Ratio Constraint Source: https://github.com/theskyentist/unite/blob/main/docs/usage/priors.md Shows how to tie a flux ratio across kinematic components using arithmetic expressions. This example fixes the '4363_broad' flux based on other line fluxes. ```python # Flux ratio constraint: tie [OIII] 4363 ratio across kinematic components. # Same electron temperature in both narrow and broad components. flux_5007_narrow = line.Flux('5007_narrow', prior=prior.Uniform(0, 10)) flux_5007_broad = line.Flux('5007_broad', prior=prior.Uniform(0, 10)) flux_4363_narrow = line.Flux('4363_narrow', prior=prior.Uniform(0, 10)) # flux_4363_broad is fully determined — not a free parameter flux_4363_broad = line.Flux( '4363_broad', prior=prior.Fixed(flux_4363_narrow * flux_5007_broad / flux_5007_narrow), ) ``` -------------------------------- ### Benchmark with JAX Blocking Source: https://github.com/theskyentist/unite/blob/main/benchmarks/README.md Demonstrates the correct way to benchmark JAX functions by ensuring results are blocked using `block()` from `_helpers.py`. ```python def run(): return block(jit_fn(args)) benchmark(run) ``` -------------------------------- ### Run Common Development Tasks with Pixi Source: https://github.com/theskyentist/unite/blob/main/docs/contributing.md Execute standard development tasks such as running tests, linting, or building documentation using Pixi commands. ```bash pixi run test # run the test suite pixi run lint # check code style pixi run docs # build these docs ``` -------------------------------- ### Build Spectral Model with Analytic Integration Source: https://github.com/theskyentist/unite/blob/main/docs/concepts.md Uses the default analytic integration mode for building a spectral model. This mode is fast and exact for emission lines. ```python model_fn, args = builder.build(integration_mode='analytic') ``` -------------------------------- ### Prepare Spectra for Fitting Source: https://github.com/theskyentist/unite/blob/main/docs/concepts.md Filters lines and continuum regions based on spectral coverage. This step is crucial before flux normalization and model building. ```python spectra = Spectra([spectrum], redshift=0.0) filtered_lines, filtered_cont = spectra.prepare(lc, cc) ``` -------------------------------- ### Configure Continuum with Default Z-order Source: https://github.com/theskyentist/unite/blob/main/docs/usage/build_model.md Initialize a continuum configuration using line configurations, with the continuum set to the default `zorder` of 0. ```python from unite.continuum.config import ContinuumConfiguration # Default: continuum at zorder=0, absorbed by any tau at zorder >= 1 cc = ContinuumConfiguration.from_lines(lc) ``` -------------------------------- ### Run Interactive Profiling with Memory Dump Source: https://github.com/theskyentist/unite/blob/main/benchmarks/README.md Performs interactive profiling and additionally dumps device memory usage using pprof. ```bash pixi run profile-mem # also dumps device memory pprof ``` -------------------------------- ### Enable JAX 64-bit Mode via Environment Variable Source: https://github.com/theskyentist/unite/blob/main/docs/installation.md Enable 64-bit precision in JAX by setting the JAX_ENABLE_X64 environment variable before running your script. Note that this may degrade performance on GPUs. ```bash JAX_ENABLE_X64=1 python my_script.py ``` -------------------------------- ### Running Benchmark Commands Source: https://github.com/theskyentist/unite/blob/main/CLAUDE.md These commands are used to execute the benchmark suite, save baseline results, and compare current performance against baselines. They are executed using the 'pixi run' command. ```bash pixi run bench # full local wall-time suite (pytest-benchmark) pixi run bench-save # save baseline JSON under .benchmarks/ pixi run bench-compare # compare current vs baseline pixi run profile # write a Perfetto trace to traces/ pixi run profile-mem # also dump device memory pprof ``` -------------------------------- ### Run Interactive Profiling with Pyinstrument Source: https://github.com/theskyentist/unite/blob/main/benchmarks/README.md Executes interactive profiling with Pyinstrument enabled for detailed Python call stack analysis. ```bash pixi run -e bench python profiling/profile_fit.py --config multi --pyinstrument ``` -------------------------------- ### Combine Sub-Configurations Source: https://github.com/theskyentist/unite/blob/main/docs/usage/serialization.md Shows how to combine individual sub-configurations (lines, continuum, dispersers) using the `+` operator. This is useful for building complex configurations from modular parts. ```python # Combine line configs lines_combined = lc1 + lc2 # Combine continuum configs continuum_combined = cc1 + cc2 # Combine disperser configs dispersers_combined = dc1 + dc2 ``` -------------------------------- ### Pixi Project Commands Source: https://github.com/theskyentist/unite/blob/main/CLAUDE.md Common Pixi commands for managing the Unite project, including formatting, linting, testing, documentation building, and packaging. ```bash pixi run format # Format code with ruff pixi run lint # Check code with ruff pixi run lint-fix # Auto-fix linting issues pixi run -e test-py312 test # Run pytest (test task is ambiguous; pick any of test-py312/313/314) pixi run test-cov # Run tests with coverage report pixi run test-lowest # Test against lowest compatible dependency versions pixi run docs # Build Sphinx documentation pixi run docs-clean # Build docs from scratch (clean build directory first) pixi run build # Build sdist + wheel pixi run type-check # Run basedpyright for type checking ``` -------------------------------- ### Build Spectral Model with Convolution Integration Source: https://github.com/theskyentist/unite/blob/main/docs/concepts.md Uses the convolution integration mode for building a spectral model, which provides exact LSF treatment for absorption lines and non-polynomial continua. Requires specifying the number of super-samples. ```python model_fn, args = builder.build(integration_mode='convolution', n_super=10) ``` -------------------------------- ### Explicitly Name Tokens for Clearer Site Names Source: https://github.com/theskyentist/unite/blob/main/docs/usage/line_configuration.md Shows how to provide semantic labels when creating tokens, which are then prefixed to form explicit site names for better interpretability in model outputs. ```python # Auto-generated names → based on line name, less explicit z = line.Redshift() # Explicit semantic labels → clear, shareable across lines z_nlr = line.Redshift('nlr') # → site name 'z_nlr' z_blr = line.Redshift('blr') # → site name 'z_blr' fwhm = line.FWHM('broad') # → site name 'fwhm_broad' flux = line.Flux('Ha') # → site name 'flux_Ha' ``` -------------------------------- ### Running Specific Tests with Pixi Source: https://github.com/theskyentist/unite/blob/main/CLAUDE.md How to execute specific test files or test functions using Pixi, specifying the Python version environment. ```bash pixi run -e test-py312 test -- tests/test_instrument_base.py ``` ```bash pixi run -e test-py312 test -- tests/test_instrument_nirspec.py::test_function_name ``` -------------------------------- ### Initialize Spectra Container Source: https://github.com/theskyentist/unite/blob/main/docs/usage/build_model.md Create a Spectra object to hold one or more Spectrum objects. The redshift argument shifts line centers to the observed frame. ```python from unite.instrument import Spectra # Single spectrum spectra = Spectra([spectrum], redshift=0.0) # Multiple spectra (e.g., two NIRSpec gratings) spectra = Spectra([g235h_spectrum, g395h_spectrum], redshift=5.28) ``` -------------------------------- ### Make Parameter Table (Percentile Summaries) Source: https://github.com/theskyentist/unite/blob/main/docs/usage/results.md Generates a FITS Table with rows representing specified percentiles (e.g., median and 68% credible interval) for each model parameter. Useful for summarizing results concisely. ```python import numpy as np # Return median and 68% credible interval percentiles = np.array([0.16, 0.5, 0.84]) table = make_parameter_table(samples, model_args, percentiles=percentiles) # Three rows: percentiles [0.16, 0.5, 0.84] print(table) print(table['Ha_flux']) # shape (3,) for the 3 percentiles ``` -------------------------------- ### Instantiate Linear Continuum Form Source: https://github.com/theskyentist/unite/blob/main/docs/usage/continuum_configuration.md Use the Linear form for a simple linear continuum. It has 'scale' and 'angle' as model parameters. ```python from unite.continuum import Linear form = Linear() ``` -------------------------------- ### Import NIRSpec Disperser Classes Source: https://github.com/theskyentist/unite/blob/main/docs/usage/instrument.md Import convenience classes for JWST/NIRSpec dispersers from the `unite.instrument` module. ```python from unite.instrument import nirspec ``` -------------------------------- ### Print Line Configuration Source: https://github.com/theskyentist/unite/blob/main/docs/usage/line_configuration.md Print the current state of the LineConfiguration object to review added lines and their parameters. This provides a summary of the configuration. ```default print(lc) LineConfiguration: 1 lines, 1 flux / 1 z / 1 profile params Name Wavelength Profile Redshift Params Flux Strength ------- ---------------- -------- -------- ------ ------- -------- H_alpha 6563.00 Angstrom Gaussian z fwhm Ha_flux 1.00 Redshift: z Uniform(low=-0.01, high=0.01) Params (fwhm_gauss): fwhm Uniform(low=50.0, high=500.0) Flux: Ha_flux Uniform(low=0.0, high=1.0) ``` -------------------------------- ### Configure Continuum with Custom Z-order Source: https://github.com/theskyentist/unite/blob/main/docs/usage/build_model.md Initialize a continuum configuration with a custom `zorder` value. This determines which absorbers will attenuate the continuum. ```python # Continuum at zorder=2: tau at zorder=1 does NOT attenuate the continuum cc_behind = ContinuumConfiguration.from_lines(lc, zorder=2) ``` -------------------------------- ### Run Stochastic Variational Inference (SVI) Source: https://github.com/theskyentist/unite/blob/main/docs/usage/inference.md Sets up and runs Stochastic Variational Inference (SVI) using NumPyro. This approximates the posterior with a simpler distribution, offering faster iteration and suitability for large surveys or initializing NUTS. ```python from numpyro import infer, optim guide = autoguide.AutoMultivariateNormal(model_fn) svi = infer.SVI( fit_func, guide, optim.Adam(step_size=0.01), loss=infer.Trace_ELBO() ) svi_result = svi.run(jax.random.PRNGKey(0), 10000, model_args) params = svi_result.params samples = guide.sample_posterior(jax.random.PRNGKey(1), params, sample_shape=(500,)) ``` -------------------------------- ### Instantiate Chebyshev Continuum Form Source: https://github.com/theskyentist/unite/blob/main/docs/usage/continuum_configuration.md Use the Chebyshev form for numerically stable polynomial expansions. Specify 'order' and 'stretch' during construction. Exercise caution with non-unity 'stretch'. ```python from unite.continuum import Chebyshev form = Chebyshev(order=3, stretch=1) # half_width in same units as region bounds ``` -------------------------------- ### Create Continuum Configuration from Line Centers Source: https://github.com/theskyentist/unite/blob/main/docs/concepts.md Builds a ContinuumConfiguration object from line centers, specifying a functional form for the continuum. Ensure line centers and the desired form are provided. ```python from unite.continuum import ContinuumConfiguration, Linear cc = ContinuumConfiguration.from_lines( lc.centers, # wavelength array of line rest-frame centers form=Linear(), # continuum form (or string name, e.g. 'Linear') ) ```