cometspec.fluorescence

High-level fluorescence model and production-rate workflow.

This module exposes FluorescenceModel, the user-facing wrapper that ties together line-list selection, physical parameters, the line-spread function (LSF), and observed-data column names into a single object. It is the preferred entry point for fitting, synthesis, and profile- or Haser-based production-rate estimation.

The low-level numerical routines (transition normalization, rate matrices, collisions, MCMC kernel, spectrum synthesis) live in cometspec.modeling. This module is the orchestration layer where models can be created or fitted. When fitting through FluorescenceModel.fit_mcmc() attributes are overridden. The effective fallback values for parameters that are not going to be sampled are read from the model instance and forwarded explicitly to cometspec.modeling.mcmc_fitting().

Notes

  • Multi-isotopologue fitting is supported; when more than one isotopologue is active, logN is replaced by per-isotopologue logN_{iso} keys (and likewise for logQ_{iso} if collisions are sampled per iso). If not all the isotopologues have their own logN_{iso} key, the missing ones fall back to logN; the same applies to logQ.

  • FluorescenceModel.save() and FluorescenceModel.load() provide a way to save the models as pickled files. They can be loaded later in the case the user wants to fit just one long MCMC run and then build the models afterwards.

  • Check cometspec.linelist.load_default_transitions() for default supported isotopologue, and the default line lists that are loaded when linelists is not provided and their corresponding references.

  • It is recommended to call the isotopologues with the following nomenclature <number><Element><number><Element> for instance 12C14N, and it will recognize homonuclear, diatomic heteronuclear of the same element or diatomic heteronuclear of different elements. If the isotopologue name does not follow any of the previous categories, it will fall in the default category, which is to include \(|\Delta J| = \pm 1, 0\). Check cometspec.collisions.precompute_collision_scaffold() for the collision selection rules.

Classes

FluorescenceModel

High-level wrapper over fitting, synthesis, and production-rate computation.

class cometspec.fluorescence.FluorescenceModel(*, data=None, window=(3850.0, 3900.0), pumping=None, isotopologues='12C14N', systems=None, linelists=None, line_path=None, lsf=None, lsf_method='Gauss', A_min=10000.0, a=3.0, name=None, sigma=0.01, sigma1=None, sigma2=None, sigma_G=None, fwhm_L=None, ratio=None, logN=11.0, logN_by_iso=None, logQ=None, logQ_by_iso=None, T=300.0, T_by_iso=None, v_kms=0.0, v_kms_by_iso=None, dlam=0.0, dlam_by_iso=None, wave_col='WAVE', flux_col='FLUX_STACK', error_col='ERR_STACK', continuum_col='CONTINUUM', omega=1.8460336577110375e-11, include_rotations=True, pumping_v_kms=0.0, pumping_dlam_A=0.0, model_wave=None, n_cores=None, config=None)[source]

Bases: object

High-level fluorescence workflow wrapper.

This class centralizes model state (line selection, physical parameters, LSF, and data columns) and is the preferred entry point for fitting and synthesis.

IMPORTANT: When fit_mcmc calls modeling.mcmc_fitting, fallback values for parameters that are not sampled are taken from this instance (e.g. self.logQ, self.T, self.v_kms, self.dlam) and passed explicitly.

The object exposes a stable set of attributes, even before fitting.

Always available (initialized in __init__):

Selection / config

  • data (Any or None) – Observed spectrum container (DataFrame or astropy Table).

  • window (tuple[float, float] or None) – Wavelength interval (min_A, max_A) used for synthesis.

  • pumping (Any) – Solar irradiance spectrum used to evaluate \(J_\nu\). Must have WAVE and FLUX columns in \(\mathrm{Å}\) and \(\mathrm{erg}\,\mathrm{s}^{-1}\,\mathrm{cm}^{-2}\,\mathrm{Å}^{-1}\) units.

  • isotopologues (str or Sequence[str]) – Isotopologue label(s). Default labels are "12C14N", "13C14N", "12C15N", "12C13C", "12C2", "13C2" or any label containing Fe. They can also be custom labels for custom line lists.

  • systems (str or Sequence[str] or None) – CN system selector(s). Check cometspec.linelist.normalize_cn_systems_arg() for supported values.

  • linelists (pandas.DataFrame or dict[str, pandas.DataFrame] or Sequence[pandas.DataFrame] or None) – Custom normalized line list(s).

  • line_path (str or None) – Custom path for single-isotopologue line list loading. Just use it if the default line lists are located in non standard locations.

  • name (str or None) – Model label. Defaults to "Fluorescence" if not provided.

Physical / model controls

  • logN (float or None) – \(\log_{10}\) column density in molecules cm-2.

  • logN_by_iso (dict[str, float] or None) – Per-isotopologue \(\log_{10}\) column density. Same units as above. Falls back to logN for isotopologues not in this dict.

  • logQ (float or None) – \(\log_{10}\) collisional rate in s-1.

  • logQ_by_iso (dict[str, float] or None) – Per-isotopologue \(\log_{10}\) collisional rate. Same units as above. Falls back to logQ for isotopologues not in this dict.

  • T (float or None) – Kinetic temperature in K.

  • T_by_iso (dict[str, float] or None) – Per-isotopologue kinetic temperature in K. Falls back to T for isotopologues not in this dict.

  • v_kms (float or None) – Emission-frame Doppler velocity shift in km/s.

  • v_kms_by_iso (dict[str, float] or None) – Per-isotopologue emission-frame velocity shift in km/s. Falls back to v_kms for isotopologues not in this dict.

  • dlam (float or None) – Additive emission-frame wavelength shift in Å.

  • dlam_by_iso (dict[str, float] or None) – Per-isotopologue additive wavelength shift in Å. Falls back to dlam for isotopologues not in this dict.

  • omega (float) – Aperture solid angle in sr.

LSF config

  • lsf (callable or None) – Custom LSF callable; lsf_method is stored as "Given" when set.

  • lsf_method (str or None) – Built-in LSF mode: "Gauss", "2Gauss", "Gauss_Lorentz", or "Lorentz".

  • sigma (float or None) – Gaussian sigma in Å for "Gauss" mode.

  • sigma1 (float or None) – Component 1 sigma in Å for "2Gauss" mode.

  • sigma2 (float or None) – Component 2 sigma in Å for "2Gauss" mode.

  • sigma_G (float or None) – Gaussian sigma in Å for "Gauss_Lorentz" mode.

  • fwhm_L (float or None) – Lorentzian FWHM in Å for "Gauss_Lorentz" or "Lorentz" mode.

  • ratio (float or None) – Mixture ratio for "2Gauss" and "Gauss_Lorentz" modes. Gaussian / Lorentzian for "Gauss_Lorentz"; Gaussian 1 / Gaussian 2 for "2Gauss".

Pumping controls

  • pumping_v_kms (float) – Velocity shift in km/s applied to line wavelengths when sampling \(J_\nu\).

  • pumping_dlam_A (float) – Additive wavelength shift in Å applied to line wavelengths when sampling \(J_\nu\).

Note

The minimum and maximum wavelengths used to filter the default transition linelists are taken from the minimum and maximum wavelengths of the supplied solar irradiance (pumping) spectrum.

Data column names

  • wave_col (str) – Wavelength column name in data.

  • flux_col (str) – Flux column name in data.

  • error_col (str) – Uncertainty column name in data.

  • continuum_col (str) – Continuum column name in data.

Runtime knobs

  • A_min (float or None) – Minimum Einstein-A threshold for line list. User provided line lists are not filtered by A_ul

  • a (float) – emcee stretch-move parameter forwarded to fit_mcmc().

  • n_cores (int or None) – Number of CPU cores used to parallelize the MCMC sampler walker evaluations through multiprocessing (spawn start method, safe on macOS/Linux/Windows). None or 1 keeps the sampler single-threaded. Forwarded to fit_mcmc() as the default; can be overridden per-call. The tqdm progress bar (when progress=True) keeps working under both modes. When n_cores > 1 and running from a .py script (not a Jupyter notebook), the fit_mcmc() call must be wrapped in if __name__ == "__main__": (no guard needed in notebooks or when n_cores is None/1).

  • include_rotations (bool) – Enable rotational collisions in synthesis and fitting. Recommended to explicitly set this to False when fitting with no collisions. To see collisions to be included go to cometspec.collisions.precompute_collision_scaffold().

  • model_wave (numpy.ndarray or None) – Optional pre-defined synthesis wavelength grid passed at construction; if None it is built from window.

Synthesis outputs (set on every _synthesize_model() call, including __init__ and update_model(); overridden by fit_mcmc()):

  • model_wave (numpy.ndarray of float) – Actual wavelength grid used for the current model. After fit_mcmc() this is replaced by the fit evaluation grid.

  • best_model (numpy.ndarray of float) – Total synthesized flux at the current parameters. After fit_mcmc() this is replaced by the highest-likelihood-sample model. If the rate-matrix solver fails (LinAlgError, typically caused by NaN/Inf collision rates at extreme Q values), best_model will contain NaN — this signals that the chosen parameters are unphysical.

Fitting outputs (initialized empty/None; populated after fit_mcmc()):

  • priors (dict[str, tuple[float, float]]) – Parameter prior ranges. Empty dict until set.

  • param_keys (tuple[str, ...]) – Ordered sampled parameter names. Empty until fit.

  • median_params (dict[str, float]) – Posterior median for each sampled parameter.

  • up_errors_params (dict[str, float]) – Upper 1-sigma error (p84 - p50) for each parameter.

  • low_errors_params (dict[str, float]) – Lower 1-sigma error (p50 - p16) for each parameter.

  • samples_pruned (numpy.ndarray of float or None) – Pruned posterior samples, shape (N_samples, ndim).

  • lnprob_pruned (numpy.ndarray of float or None) – Log-probability of each pruned sample.

  • median_model (numpy.ndarray of float or None) – Model flux evaluated at the posterior median parameters.

  • model_p16 (numpy.ndarray of float or None) – 16th-percentile model envelope.

  • model_p84 (numpy.ndarray of float or None) – 84th-percentile model envelope.

  • logN_err (numpy.ndarray of float or None) – [upper, lower] 1-sigma errors on logN.

  • logN_err_by_iso (dict[str, numpy.ndarray] or None) – Per-isotopologue logN 1-sigma errors.

Per-isotopologue containers (created at initialization; recomputed on each fit or update):

  • lines_by_iso (dict[str, pandas.DataFrame] or None) – Annotated transition tables per isotopologue.

  • M_by_iso (dict[str, numpy.ndarray] or None) – Radiative rate matrices per isotopologue.

  • idx_to_level_by_iso (dict[str, dict] or None) – Matrix-index-to-level mappings per isotopologue.

  • n_by_iso (dict[str, numpy.ndarray] or None) – Steady-state level populations per isotopologue.

  • g_ph_by_iso (dict[str, numpy.ndarray] or None) – Photon g-factors per line per isotopologue.

  • g_en_by_iso (dict[str, numpy.ndarray] or None) – Energy g-factors per line per isotopologue.

  • g_ph_sum_by_iso (dict[str, float] or None) – Total photon g-factor per isotopologue.

  • g_en_sum_by_iso (dict[str, float] or None) – Total energy g-factor per isotopologue.

  • model_by_iso (dict[str, tuple[numpy.ndarray, numpy.ndarray]] or None) – Synthesized spectrum per isotopologue as (wave, flux) tuples.

Derived production-rate fields (set by compute_production_rate()):

  • q (float or dict[str, float] or None) – \(\log_{10}\) production rate(s).

  • q_err (float or dict or None) – 1-sigma uncertainty on q.

  • q_seeing_corrected (bool) – Whether q has been corrected for seeing losses.

  • logN_seeing_corrected (bool) – Whether logN has been corrected for seeing losses.

__init__(*, data=None, window=(3850.0, 3900.0), pumping=None, isotopologues='12C14N', systems=None, linelists=None, line_path=None, lsf=None, lsf_method='Gauss', A_min=10000.0, a=3.0, name=None, sigma=0.01, sigma1=None, sigma2=None, sigma_G=None, fwhm_L=None, ratio=None, logN=11.0, logN_by_iso=None, logQ=None, logQ_by_iso=None, T=300.0, T_by_iso=None, v_kms=0.0, v_kms_by_iso=None, dlam=0.0, dlam_by_iso=None, wave_col='WAVE', flux_col='FLUX_STACK', error_col='ERR_STACK', continuum_col='CONTINUUM', omega=1.8460336577110375e-11, include_rotations=True, pumping_v_kms=0.0, pumping_dlam_A=0.0, model_wave=None, n_cores=None, config=None)[source]

Initialize a fluorescence model instance and synthesize the first model.

The constructor stores configuration/state and immediately calls _synthesize_model() to populate model products.

Note

If multiple isotopologues are provided, it is recommended to use the format <parameter>_<iso> for each isotopologue instead of <parameter> (logN, logQ, T, v_kms, dlam).

Parameters:
  • pumping (Any) – Solar irradiance spectrum at the comet, used to evaluate J_nu for transitions. Required.

  • data (Any, optional, default None) – Observed spectrum container (typically pandas DataFrame or astropy Table).

  • window (tuple[float, float], optional, default (3850.0, 3900.0)) – Wavelength interval (lambda_min_A, lambda_max_A) used for synthesis.

  • isotopologues (str or Sequence[str], optional, default "12C14N") – Isotopologue label or list of labels.

  • systems (str or Sequence[str], optional, default None) – CN system selector(s) forwarded to modeling.load_default_transitions().

  • linelists (pandas.DataFrame or dict[str, pandas.DataFrame] or Sequence[pandas.DataFrame], optional, default None) – Optional normalized line list(s). Accepted forms:

    • None -> every isotopologue loaded from packaged defaults.

    • Single pandas.DataFrame -> assigned to the first isotopologue; the remaining isotopologues fall back to packaged defaults.

    • dict mapping iso label to DataFrame -> isotopologues missing from the dict fall back to defaults; extra keys are ignored.

    • Sequence of DataFrames -> positionally paired with the first len(linelists) isotopologues; the remainder fall back to defaults.

    Loading a default for an unsupported isotopologue label (e.g. "COH") raises ValueError.

  • lsf (Callable[[numpy.ndarray], numpy.ndarray], optional, default None) – Optional custom LSF callable. If provided, lsf_method parameterization values are ignored and lsf_method is stored as "Given".

  • lsf_method (str, optional, default "Gauss") – Built-in LSF mode when lsf is not provided. Supported values are "Gauss", "2Gauss", "Gauss_Lorentz", and "Lorentz".

  • logN (float, optional, default 11.0) – Default column density log10(N / cm^-2) used for synthesis and fallback behavior.

  • logN_by_iso (dict[str, float], optional, default None) – Optional per-isotopologue log10(N / cm^-2) map. Any isotopologue missing from the map falls back to logN.

  • logQ (float, optional, default None) – Collisional rate (log10 scale) default fallback. Q is in s^-1.

  • logQ_by_iso (dict[str, float], optional, default None) – Optional per-isotopologue log10(Q/s^-1) map. When provided, each isotopologue uses its own collisional rate; any isotopologue missing from the map falls back to logQ.

  • T (float, optional, default 300.0) – Kinetic temperature in Kelvin. Global fallback for all isotopologues.

  • T_by_iso (dict[str, float], optional, default None) – Per-isotopologue kinetic temperature in K. For each isotopologue, T_by_iso[iso] is used if present; otherwise falls back to T.

  • v_kms (float, optional, default 0.0) – Emission-frame Doppler velocity shift in km/s. Global fallback for all isotopologues.

  • v_kms_by_iso (dict[str, float], optional, default None) – Per-isotopologue emission-frame velocity shift in km/s. Falls back to v_kms for isotopologues not in this dict.

  • dlam (float, optional, default 0.0) – Additive emission-frame wavelength shift in Å. Global fallback for all isotopologues.

  • dlam_by_iso (dict[str, float], optional, default None) – Per-isotopologue additive wavelength shift in Å. Falls back to dlam for isotopologues not in this dict.

  • include_rotations (bool, optional, default True) – Enable rotational collisions in synthesis/fitting. Recommended to explicitly set this to False when fitting with no collisions, as it reduces the number of levels and speeds up the computation. To see collisions to be included go to cometspec.collisions.precompute_collision_scaffold().

  • config (FluorescenceModelConfig, optional, default None) – Optional grouped configuration. Any field set on this object overrides the corresponding individual keyword argument. Fields left at cometspec.config.UNSET (the default) are ignored, so callers that pass individual kwargs are unaffected. See cometspec.config.FluorescenceModelConfig.

Other Parameters:
  • line_path (str, optional, default None) – Optional custom path for single-isotopologue line list loading. Use it just if the default line lists are located in non standard locations.

  • sigma (float, optional, default 0.01) – Gaussian sigma for lsf_method="Gauss".

  • sigma1 (float, optional, default None) – Component 1 sigma for lsf_method="2Gauss".

  • sigma2 (float, optional, default None) – Component 2 sigma for lsf_method="2Gauss".

  • sigma_G (float, optional, default None) – Gaussian sigma for lsf_method="Gauss_Lorentz".

  • fwhm_L (float, optional, default None) – Lorentzian FWHM for lsf_method="Gauss_Lorentz" or "Lorentz".

  • ratio (float, optional, default None) – Mixture ratio for "2Gauss" and "Gauss_Lorentz" modes. For "Gauss_Lorentz" it is gauss / lorentz; for "2Gauss" it is gauss1 / gauss2.

  • A_min (float, optional, default 1e4) – Minimum Einstein-A threshold used by default transition loading. User provided line lists are not filtered by A_ul

  • a (float, optional, default 3.0) – Stored emcee stretch-move parameter used by fit_mcmc().

  • name (str, optional, default None) – Optional model label. If None, it is set to "Fluorescence".

    Note

    The minimum and maximum wavelengths used to filter the default transition linelists are taken from the minimum and maximum wavelengths of the supplied solar irradiance (pumping) spectrum.

  • wave_col (str, optional, default "WAVE") – Wavelength column name in data.

  • flux_col (str, optional, default "FLUX_STACK") – Flux column name in data.

  • error_col (str, optional, default "ERR_STACK") – Uncertainty column name in data.

  • continuum_col (str, optional, default "CONTINUUM") – Continuum column name in data.

  • omega (float, optional, default np.pi * (0.5 * np.pi / (180.0 * 3600.0)) ** 2) – Aperture solid angle in sr. The default assumes a circular aperture of radius 0.5”.

  • pumping_v_kms (float, optional, default 0.0) – Velocity shift (km/s) applied to line wavelengths when sampling pumping irradiance J_nu.

  • pumping_dlam_A (float, optional, default 0.0) – Additive shift (A) applied to line wavelengths when sampling pumping irradiance J_nu.

  • model_wave (numpy.ndarray, optional, default None) – Optional pre-defined synthesis grid. If None, a grid is built from window with 0.01 A spacing.

  • n_cores (int, optional, default None) – Default number of CPU cores used by fit_mcmc() to parallelize walker likelihood evaluations through multiprocessing (spawn start method, safe on macOS/Linux/Windows). None or 1 keeps the sampler single-threaded. Stored on the instance and overridable per fit_mcmc() call.

Raises:

ValueError – If pumping is not provided or if LSF parameterization is inconsistent.

fit_mcmc(data=None, window=None, *, pumping=None, isotopologues=None, systems=None, linelists=None, nwalkers=20, nsteps=1000, n_cores=None, priors=None, lsf=None, lsf_method=None, make_plots=True, progress=True, A_min=None, a=None, fig_file='mcmc_fit', verbose=True, pruning=True, N_Model=20000, config=None)[source]

Run MCMC using the current model state.

This method forwards current wrapper defaults/state into modeling.mcmc_fitting(), updates instance attributes with posterior summaries, and keeps pumping-shift settings synchronized.

Note

Priors consist on a dict mapping parameter name to a (min, max) tuple defining the uniform prior range for that parameter. The possible keys are: "logN", "logQ", "T", "dlam", "v_kms", ‘logN_<isotopologue>’, ‘logQ_<isotopologue>’, ‘T_<isotopologue>’, ‘dlam_<isotopologue>’, ‘v_kms_<isotopologue>’ (any iso not found falls back to <parameter>) and lsf priors, sigma, sigma1, sigma2, sigma_G, fwhm_L, ratio.

Parameters:
  • data (Any, optional, default None) – Optional observed spectrum. If provided, updates self.data.

  • window (tuple[float, float], optional, default None) – Optional fit window (lambda_min_A, lambda_max_A). If provided, updates self.window.

  • pumping (Any, optional, default None) – Optional solar irradiance spectrum. If provided, updates self.pumping.

  • isotopologues (str or Sequence[str], optional, default None) – Optional isotopologue override for this fit. If provided, updates self.isotopologues.

  • systems (str or Sequence[str], optional, default None) – Optional CN system selector override. If provided, updates self.systems.

  • linelists (pandas.DataFrame or dict[str, pandas.DataFrame] or Sequence[pandas.DataFrame], optional, default None) – Optional line-list override. If provided, updates self.linelists.

  • nwalkers (int, optional, default 20) – Number of MCMC walkers. Default is 20.

  • nsteps (int, optional, default 1000) – Number of MCMC steps. Default is 1000.

  • n_cores (int, optional, default None) – Number of CPU cores used to parallelize the MCMC walker likelihood evaluations through multiprocessing (spawn start method, safe on macOS/Linux/Windows). None falls back to self.n_cores; if that is also None or 1 the sampler runs single-threaded. Values >1 are clamped to os.cpu_count(). The tqdm progress bar (when progress=True) keeps working under both modes. When provided, this value also updates self.n_cores.

    Important

    When calling fit_mcmc() with n_cores > 1 from a .py script (not a Jupyter notebook), the call must be wrapped in if __name__ == "__main__":. Each spawn worker re-imports the user’s script, and without the guard the call re-executes on import; Python aborts with a RuntimeError. No guard is needed in notebooks or when n_cores is None/1.

  • priors (dict[str, tuple[float, float]], optional, default None) – Prior ranges for sampled parameters. If None, uses stored priors or {"logN": (9.0, 15.0), "logQ": (-5.0, 0.0), "T": (10.0, 1000.0)}.

  • lsf (Callable[[numpy.ndarray], numpy.ndarray], optional, default None) – Optional custom LSF callable for fit-time synthesis.

  • lsf_method (str, optional, default None) – Optional built-in LSF method override for this fit.

  • make_plots (bool, optional, default True) – Generate diagnostic plots inside modeling fitter. Default is True.

  • progress (bool, optional, default True) – Show sampler progress output. Default is True.

  • A_min (float, optional, default None) – Optional threshold override; if provided updates self.A_min.

  • a (float, optional, default None) – Optional stretch-move parameter override; if provided updates self.a.

  • fig_file (str, optional, default "mcmc_fit") – Figure file prefix passed to modeling fitter. Default is "mcmc_fit".

  • verbose (bool, optional, default True) – Enable verbose output in modeling fitter. Default is True.

  • pruning (bool, optional, default True) – Enable posterior pruning in modeling fitter, check our publication for details. Default is True.

  • N_Model (int, optional, default 20000) – Number of elements in the model grid. Default is 20000.

  • config (MCMCFitConfig, optional, default None) – Optional grouped configuration forwarded to cometspec.mcmc.mcmc_fitting(). Any field set on this object overrides the corresponding individual keyword argument.

Returns:

dict[str, Any] – Fit result dictionary from modeling.mcmc_fitting().

Raises:

ValueError – If no data/pumping/window are available.

Notes

Result keys and mirrored attributes:

  • param_keys -> self.param_keys

  • median_params -> self.median_params

  • up_errors_params -> self.up_errors_params

  • low_errors_params -> self.low_errors_params

  • samples_pruned -> self.samples_pruned

  • lnprob_pruned -> self.lnprob_pruned

  • model_wave, median_model, best_model, model_p16, model_p84 -> corresponding instance attributes

Side effects: Updates fit state and posterior products through _update_from_result(), and stores the pumping-shift values used during the fit in self.pumping_v_kms and self.pumping_dlam_A.

If extreme prior values cause the rate-matrix solver to fail (LinAlgError from a numerically degenerate matrix, typically due to NaN/Inf collision rates at very high Q), solve_with_normalization_fast returns NaN populations. lnlike then detects a non-finite model and returns -inf, so the walker step is rejected gracefully rather than crashing.

update_model(*, isotopologues=None, systems=None, linelists=None, logN=None, logN_by_iso=None, logQ=None, T=None, T_by_iso=None, v_kms=None, v_kms_by_iso=None, dlam=None, dlam_by_iso=None, A_min=None, lsf=None, lsf_method=None, sigma=None, sigma1=None, sigma2=None, sigma_G=None, fwhm_L=None, ratio=None, window=None, pumping=None, data=None, wave_col=None, flux_col=None, error_col=None, continuum_col=None, omega=1.8460336577110375e-11, N_Model=20000)[source]

Update instance parameters and re-synthesize the model.

Any non-None argument is applied to the instance. LSF settings are rebuilt according to lsf/lsf_method and then _synthesize_model() is called. Notice that you can give the parameters as keywords or you can update them directly, however this function should always be called after any parameter update to keep the model products consistent with the parameters.

Parameters:
  • isotopologues (str or Sequence[str], optional, default None) – Optional isotopologue selection update.

  • systems (str or Sequence[str], optional, default None) – Optional CN systems selector update.

  • linelists (pandas.DataFrame or dict[str, pandas.DataFrame], optional, default None) – Optional line-list update.

  • logN (float, optional, default None) – Optional global log10(N/cm^2) update.

  • logN_by_iso (dict[str, float], optional, default None) – Optional per-isotopologue log10(N/cm^2) update.

  • logQ (float, optional, default None) – Optional logQ update.

  • T (float, optional, default None) – Optional global temperature update.

  • T_by_iso (dict[str, float], optional, default None) – Optional per-isotopologue temperature update. Falls back to T for isotopologues not present.

  • v_kms (float, optional, default None) – Optional global emission velocity shift update.

  • v_kms_by_iso (dict[str, float], optional, default None) – Optional per-isotopologue emission velocity shift update. Falls back to v_kms.

  • dlam (float, optional, default None) – Optional global emission wavelength shift update.

  • dlam_by_iso (dict[str, float], optional, default None) – Optional per-isotopologue additive wavelength shift update. Falls back to dlam.

  • A_min (float, optional, default None) – Optional transition threshold update.

  • lsf (Callable[[numpy.ndarray], numpy.ndarray], optional, default None) – Optional custom LSF callable update.

  • lsf_method (str, optional, default None) – Optional LSF mode update.

  • sigma (float, optional, default None) – Optional Gaussian sigma update.

  • sigma1 (float, optional, default None) – Optional 2-Gaussian component sigma1 update.

  • sigma2 (float, optional, default None) – Optional 2-Gaussian component sigma2 update.

  • sigma_G (float, optional, default None) – Optional Gaussian sigma for Gauss-Lorentz update.

  • fwhm_L (float, optional, default None) – Optional Lorentzian FWHM update.

  • ratio (float, optional, default None) – Optional mixture ratio update.

  • window (tuple[float, float], optional, default None) – Optional synthesis window update.

  • pumping (Any, optional, default None) – Optional pumping spectrum update.

  • data (Any, optional, default None) – Optional observed data update.

  • wave_col (str, optional, default None) – Optional wavelength column-name update.

  • flux_col (str, optional, default None) – Optional flux column-name update.

  • error_col (str, optional, default None) – Optional uncertainty column-name update.

  • continuum_col (str, optional, default None) – Optional continuum column-name update.

  • omega (float, optional, default np.pi * (0.5 * np.pi / (180.0 * 3600.0)) ** 2) – Optional aperture solid-angle update. Default argument value matches constructor default.

Raises:

ValueError – If LSF parameters are inconsistent for the selected method.

Notes

Side effects:

  • Always calls _synthesize_model().

  • Resets self.q and self.q_err to None when logN, logN_by_iso, or isotopologue selection changes.

n_lines()[source]

Print and return the number of transitions in the synthesized model.

For a single isotopologue, prints and returns a single integer. For multiple isotopologues, prints one count per isotopologue plus the total and returns a {iso: count} dict.

Returns:

int or dict[str, int] – Line count per isotopologue, or a single int for one iso.

Raises:

RuntimeError – If the model has not been synthesized yet (i.e. _synthesize_model() has not run, so lines_by_iso is unset).

print_linelist_origins()[source]

Print and return the source of each isotopologue’s line list.

For each isotopologue, prints either "custom (user-provided)" (when the line list came from the linelists argument) or the file path that would be / was loaded from the packaged defaults. Resolution mirrors _synthesize_model(), so this can be called before or after synthesis.

Returns:

dict[str, str]{iso: origin} ordered as self.isotopologues.

compute_production_rate(*, delta_au, aperture, parent_length_km, daughter_length_km, v_outflow_km_s, use_samples=True, N_total_coma_km=10000000.0)[source]

Estimate production rate log10(Q) from fitted column densities using a Haser model.

The method uses a Haser model to convert aperture column-density constraints into total production rates, either from posterior samples or from current median logN values.

Note

This method assumes a Haser coma model. If you have a spatial flux profile instead of integrated column densities, use compute_production_rate_from_profile() instead.

Parameters:
  • delta_au (float) – Geocentric distance in AU (for arcsec-to-km projection).

  • aperture (dict) – Aperture geometry definition. Supported forms are {"type": "circular", "radius_arcsec": R} and {"type": "rectangular", "width_arcsec": W, "length_arcsec": L}.

  • parent_length_km (float) – Parent scale length in km.

  • daughter_length_km (float) – Daughter scale length in km.

  • v_outflow_km_s (float) – Gas outflow velocity in km/s.

  • use_samples (bool, optional, default True) – If True, uses self.samples_pruned chains; if False, uses current median values in self.logN/self.logN_by_iso. Default is True. Without samples, there is no error estimate.

  • N_total_coma_km (float, optional, default 1e7) – Radius in km used to approximate total coma count in the Haser model. Default is 1e7.

Returns:

tuple[float, float] or dict[str, tuple[float, float]] – For single isotopologue, returns (logQ50, logQerr). For multi-isotopologue models, returns dict[iso] = (logQ50, logQerr).

Raises:
  • ValueError – If required chains/values are missing or Haser aperture fraction is invalid.

  • KeyError – If expected isotopologue logN chains are missing.

Notes

Stores computed values in self.q and self.q_err.

add_slit_loss_error(*, lambda_nm, aperture, correct='both', eps_min_arcsec_500=0.7, eps_max_arcsec_500=1.2, zmin_deg=45.0, zmax_deg=45.0, n_points=2000)[source]

Add seeing/slit-loss systematic uncertainty to q_err, logN_err, or both.

This method can be called after compute_production_rate() (for correct="q" or correct="both") or before (for correct="logN"). Each quantity tracks its own correction state, so they can be corrected independently or together. The final error is the quadrature sum of the original error and a slit-loss error. Check cometspec.helper.add_slit_loss_error_scalar() for details on the slit-loss error calculation.

Parameters:
  • lambda_nm (float) – Wavelength in nm used for seeing scaling.

  • aperture (dict) – Aperture geometry definition dictionary. Same format as compute_production_rate().

  • correct (str, optional, default "both") – Which quantity to correct. One of "q" (default), "logN", or "both". Note that "q" requires self.q and self.q_err to be set; "logN" requires self.logN and self.logN_err to be set.

  • eps_min_arcsec_500 (float, optional, default 0.7) – Minimum seeing FWHM at 500 nm and zenith, in arcsec. Default is 0.7.

  • eps_max_arcsec_500 (float, optional, default 1.2) – Maximum seeing FWHM at 500 nm and zenith, in arcsec. Default is 1.2.

  • zmin_deg (float, optional, default 45.0) – Minimum (best) zenith angle during observations, in degrees. Default is 45.0.

  • zmax_deg (float, optional, default 45.0) – Maximum (worst) zenith angle during observations, in degrees. Default is 45.0.

  • n_points (int, optional, default 2000) – Number of wavelength points used to sample the narrow window around lambda_nm. Must be >= 2. Default is 2000.

Raises:
  • ValueError – If correct is not one of "q", "logN", "both"; or if the required attributes (self.q, self.q_err, self.logN, self.logN_err) are not set for the requested correction.

  • KeyError – If an isotopologue key is missing from self.q, self.q_err, self.logN_by_iso, or self.logN_err_by_iso.

Notes

Side effects:

  • Updates self.q_err / self.q_err_by_iso and sets self.q_seeing_corrected = True when correcting q.

  • Updates self.logN_err / self.logN_err_by_iso and sets self.logN_seeing_corrected = True when correcting logN.

  • If a quantity was already corrected, prints a warning and skips it without raising an error.

compute_aperture_integral(*, aperture, delta_au)[source]

Compute the geometric aperture integral G for a N(ρ) ∝ ρ⁻¹ column-density profile (pure radial outflow), such that Q = v * N_ap / G.

Circular: G = π ρ_ap / 2 Rectangular: G = [L·asinh(W/L) + W·asinh(L/W)] / 2

Parameters:
Returns:

astropy.units.Quantity – G in cm.

Raises:

ValueError – If the aperture type is unsupported.

compute_production_rate_from_profile(*, G, delta_au, aperture, v_outflow_km_s, use_samples=True)[source]

Estimate log10(Q) from a column-density profile via a pre-computed aperture integral G.

Examples

G = model.compute_aperture_integral(
        aperture=aperture, delta_au=delta_au, profile="rho^-1"
    )
logQ, logQ_err = model.compute_production_rate_from_profile(
        G=G, aperture=aperture, delta_au=delta_au,
        v_outflow_km_s=0.85,
    )

For a custom profile, compute G yourself (cm) and pass it directly, skipping compute_aperture_integral() entirely:

import astropy.units as u
import numpy as np
G_custom = my_numerical_integral(...) * u.cm
logQ, logQ_err = model.compute_production_rate_from_profile(
        G=G_custom, ...
    )
Parameters:
  • G (astropy.units.Quantity) – Geometric aperture integral in cm, from compute_aperture_integral() or a custom calculation. Must satisfy Q = v * N_ap / G.

  • delta_au (float) – Geocentric distance in AU.

  • aperture (dict) – Aperture geometry (needed to compute the collecting area A_cm²).

  • v_outflow_km_s (float) – Gas outflow velocity in km/s.

  • use_samples (bool, optional, default True) – If True, propagates full MCMC chains; if False, uses the median logN only. If False, no error estimate is produced.

Returns:

  • tuple[float, float](logQ50, logQ_err) for single-isotopologue models.

  • dict[str, tuple[float, float]]{iso: (logQ50, logQ_err)} for multi-isotopologue models.

Raises:

ValueError – If MCMC samples are missing and use_samples=True.

save(filename)[source]

Serialize model state to a pickle file.

The saved state includes constructor kwargs, MCMC products, and derived production-rate fields q and q_err. If the model uses a custom callable LSF (lsf_method == "Given"), that callable is not serialized.

Parameters:

filename (str) – Output file path.

classmethod load(filename)[source]

Load a serialized FluorescenceModel from disk.

Parameters:

filename (str) – Input pickle file path created by save().

Returns:

FluorescenceModel – Reconstructed fluorescence model instance.

Raises:

ValueError – If the file does not contain a compatible FluorescenceModel state version.

Notes

Side effects: If the original model used a custom callable LSF, a warning is printed because that callable is not serialized.