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,
logNis replaced by per-isotopologuelogN_{iso}keys (and likewise forlogQ_{iso}if collisions are sampled per iso). If not all the isotopologues have their ownlogN_{iso}key, the missing ones fall back tologN; the same applies tologQ.FluorescenceModel.save()andFluorescenceModel.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 whenlinelistsis 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:
objectHigh-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_mcmccallsmodeling.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(AnyorNone) – Observed spectrum container (DataFrame or astropy Table).window(tuple[float, float]orNone) – 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(strorSequence[str]) – Isotopologue label(s). Default labels are"12C14N","13C14N","12C15N","12C13C","12C2","13C2"or any label containingFe. They can also be custom labels for custom line lists.systems(strorSequence[str]orNone) – CN system selector(s). Checkcometspec.linelist.normalize_cn_systems_arg()for supported values.linelists(pandas.DataFrameordict[str, pandas.DataFrame]orSequence[pandas.DataFrame]orNone) – Custom normalized line list(s).line_path(strorNone) – Custom path for single-isotopologue line list loading. Just use it if the default line lists are located in non standard locations.name(strorNone) – Model label. Defaults to"Fluorescence"if not provided.
Physical / model controls
logN(floatorNone) – \(\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 tologNfor isotopologues not in this dict.logQ(floatorNone) – \(\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 tologQfor isotopologues not in this dict.T_by_iso(dict[str, float] or None) – Per-isotopologue kinetic temperature in K. Falls back toTfor isotopologues not in this dict.v_kms(floatorNone) – 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 tov_kmsfor isotopologues not in this dict.dlam(floatorNone) – Additive emission-frame wavelength shift in Å.dlam_by_iso(dict[str, float] or None) – Per-isotopologue additive wavelength shift in Å. Falls back todlamfor isotopologues not in this dict.omega(float) – Aperture solid angle in sr.
LSF config
lsf(callable orNone) – Custom LSF callable;lsf_methodis stored as"Given"when set.lsf_method(strorNone) – Built-in LSF mode:"Gauss","2Gauss","Gauss_Lorentz", or"Lorentz".sigma(floatorNone) – Gaussian sigma in Å for"Gauss"mode.sigma1(floatorNone) – Component 1 sigma in Å for"2Gauss"mode.sigma2(floatorNone) – Component 2 sigma in Å for"2Gauss"mode.sigma_G(floatorNone) – Gaussian sigma in Å for"Gauss_Lorentz"mode.fwhm_L(floatorNone) – Lorentzian FWHM in Å for"Gauss_Lorentz"or"Lorentz"mode.ratio(floatorNone) – 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 indata.flux_col(str) – Flux column name indata.error_col(str) – Uncertainty column name indata.continuum_col(str) – Continuum column name indata.
Runtime knobs
A_min(floatorNone) – Minimum Einstein-A threshold for line list. User provided line lists are not filtered by A_ula(float) – emcee stretch-move parameter forwarded tofit_mcmc().n_cores(intorNone) – Number of CPU cores used to parallelize the MCMC sampler walker evaluations throughmultiprocessing(spawnstart method, safe on macOS/Linux/Windows).Noneor1keeps the sampler single-threaded. Forwarded tofit_mcmc()as the default; can be overridden per-call. The tqdm progress bar (whenprogress=True) keeps working under both modes. Whenn_cores > 1and running from a.pyscript (not a Jupyter notebook), thefit_mcmc()call must be wrapped inif __name__ == "__main__":(no guard needed in notebooks or whenn_coresisNone/1).include_rotations(bool) – Enable rotational collisions in synthesis and fitting. Recommended to explicitly set this toFalsewhen fitting with no collisions. To see collisions to be included go tocometspec.collisions.precompute_collision_scaffold().model_wave(numpy.ndarrayorNone) – Optional pre-defined synthesis wavelength grid passed at construction; ifNoneit is built fromwindow.
Synthesis outputs (set on every
_synthesize_model()call, including__init__andupdate_model(); overridden byfit_mcmc()):model_wave(numpy.ndarrayoffloat) – Actual wavelength grid used for the current model. Afterfit_mcmc()this is replaced by the fit evaluation grid.best_model(numpy.ndarrayoffloat) – Total synthesized flux at the current parameters. Afterfit_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_modelwill contain NaN — this signals that the chosen parameters are unphysical.
Fitting outputs (initialized empty/
None; populated afterfit_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.ndarrayoffloatorNone) – Pruned posterior samples, shape(N_samples, ndim).lnprob_pruned(numpy.ndarrayoffloatorNone) – Log-probability of each pruned sample.median_model(numpy.ndarrayoffloatorNone) – Model flux evaluated at the posterior median parameters.model_p16(numpy.ndarrayoffloatorNone) – 16th-percentile model envelope.model_p84(numpy.ndarrayoffloatorNone) – 84th-percentile model envelope.logN_err(numpy.ndarrayoffloatorNone) –[upper, lower]1-sigma errors onlogN.logN_err_by_iso(dict[str, numpy.ndarray] or None) – Per-isotopologuelogN1-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 onq.q_seeing_corrected(bool) – Whetherqhas been corrected for seeing losses.logN_seeing_corrected(bool) – WhetherlogNhas 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 evaluateJ_nufor transitions. Required.data (
Any, optional, defaultNone) – 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 (
strorSequence[str], optional, default"12C14N") – Isotopologue label or list of labels.systems (
strorSequence[str], optional, defaultNone) – CN system selector(s) forwarded tomodeling.load_default_transitions().linelists (
pandas.DataFrameordict[str,pandas.DataFrame]orSequence[pandas.DataFrame], optional, defaultNone) – 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.dictmapping 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") raisesValueError.lsf (
Callable[[numpy.ndarray],numpy.ndarray], optional, defaultNone) – Optional custom LSF callable. If provided,lsf_methodparameterization values are ignored andlsf_methodis stored as"Given".lsf_method (
str, optional, default"Gauss") – Built-in LSF mode whenlsfis not provided. Supported values are"Gauss","2Gauss","Gauss_Lorentz", and"Lorentz".logN (
float, optional, default11.0) – Default column densitylog10(N / cm^-2)used for synthesis and fallback behavior.logN_by_iso (
dict[str,float], optional, defaultNone) – Optional per-isotopologuelog10(N / cm^-2)map. Any isotopologue missing from the map falls back tologN.logQ (
float, optional, defaultNone) – Collisional rate (log10 scale) default fallback.Qis in s^-1.logQ_by_iso (
dict[str,float], optional, defaultNone) – Optional per-isotopologuelog10(Q/s^-1)map. When provided, each isotopologue uses its own collisional rate; any isotopologue missing from the map falls back tologQ.T (
float, optional, default300.0) – Kinetic temperature in Kelvin. Global fallback for all isotopologues.T_by_iso (
dict[str,float], optional, defaultNone) – Per-isotopologue kinetic temperature in K. For each isotopologue,T_by_iso[iso]is used if present; otherwise falls back toT.v_kms (
float, optional, default0.0) – Emission-frame Doppler velocity shift in km/s. Global fallback for all isotopologues.v_kms_by_iso (
dict[str,float], optional, defaultNone) – Per-isotopologue emission-frame velocity shift in km/s. Falls back tov_kmsfor isotopologues not in this dict.dlam (
float, optional, default0.0) – Additive emission-frame wavelength shift in Å. Global fallback for all isotopologues.dlam_by_iso (
dict[str,float], optional, defaultNone) – Per-isotopologue additive wavelength shift in Å. Falls back todlamfor isotopologues not in this dict.include_rotations (
bool, optional, defaultTrue) – Enable rotational collisions in synthesis/fitting. Recommended to explicitly set this toFalsewhen fitting with no collisions, as it reduces the number of levels and speeds up the computation. To see collisions to be included go tocometspec.collisions.precompute_collision_scaffold().config (
FluorescenceModelConfig, optional, defaultNone) – Optional grouped configuration. Any field set on this object overrides the corresponding individual keyword argument. Fields left atcometspec.config.UNSET(the default) are ignored, so callers that pass individual kwargs are unaffected. Seecometspec.config.FluorescenceModelConfig.
- Other Parameters:
line_path (
str, optional, defaultNone) – 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, default0.01) – Gaussian sigma forlsf_method="Gauss".sigma1 (
float, optional, defaultNone) – Component 1 sigma forlsf_method="2Gauss".sigma2 (
float, optional, defaultNone) – Component 2 sigma forlsf_method="2Gauss".sigma_G (
float, optional, defaultNone) – Gaussian sigma forlsf_method="Gauss_Lorentz".fwhm_L (
float, optional, defaultNone) – Lorentzian FWHM forlsf_method="Gauss_Lorentz"or"Lorentz".ratio (
float, optional, defaultNone) – 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, default1e4) – Minimum Einstein-A threshold used by default transition loading. User provided line lists are not filtered by A_ula (
float, optional, default3.0) – Storedemceestretch-move parameter used byfit_mcmc().name (
str, optional, defaultNone) – Optional model label. IfNone, 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 indata.flux_col (
str, optional, default"FLUX_STACK") – Flux column name indata.error_col (
str, optional, default"ERR_STACK") – Uncertainty column name indata.continuum_col (
str, optional, default"CONTINUUM") – Continuum column name indata.omega (
float, optional, defaultnp.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, default0.0) – Velocity shift (km/s) applied to line wavelengths when sampling pumping irradianceJ_nu.pumping_dlam_A (
float, optional, default0.0) – Additive shift (A) applied to line wavelengths when sampling pumping irradianceJ_nu.model_wave (
numpy.ndarray, optional, defaultNone) – Optional pre-defined synthesis grid. IfNone, a grid is built fromwindowwith 0.01 A spacing.n_cores (
int, optional, defaultNone) – Default number of CPU cores used byfit_mcmc()to parallelize walker likelihood evaluations throughmultiprocessing(spawnstart method, safe on macOS/Linux/Windows).Noneor1keeps the sampler single-threaded. Stored on the instance and overridable perfit_mcmc()call.
- Raises:
ValueError – If
pumpingis 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, defaultNone) – Optional observed spectrum. If provided, updatesself.data.window (
tuple[float,float], optional, defaultNone) – Optional fit window(lambda_min_A, lambda_max_A). If provided, updatesself.window.pumping (
Any, optional, defaultNone) – Optional solar irradiance spectrum. If provided, updatesself.pumping.isotopologues (
strorSequence[str], optional, defaultNone) – Optional isotopologue override for this fit. If provided, updatesself.isotopologues.systems (
strorSequence[str], optional, defaultNone) – Optional CN system selector override. If provided, updatesself.systems.linelists (
pandas.DataFrameordict[str,pandas.DataFrame]orSequence[pandas.DataFrame], optional, defaultNone) – Optional line-list override. If provided, updatesself.linelists.nwalkers (
int, optional, default20) – Number of MCMC walkers. Default is20.nsteps (
int, optional, default1000) – Number of MCMC steps. Default is1000.n_cores (
int, optional, defaultNone) – Number of CPU cores used to parallelize the MCMC walker likelihood evaluations throughmultiprocessing(spawnstart method, safe on macOS/Linux/Windows).Nonefalls back toself.n_cores; if that is alsoNoneor1the sampler runs single-threaded. Values>1are clamped toos.cpu_count(). The tqdm progress bar (whenprogress=True) keeps working under both modes. When provided, this value also updatesself.n_cores.Important
When calling
fit_mcmc()withn_cores > 1from a.pyscript (not a Jupyter notebook), the call must be wrapped inif __name__ == "__main__":. Eachspawnworker re-imports the user’s script, and without the guard the call re-executes on import; Python aborts with aRuntimeError. No guard is needed in notebooks or whenn_coresisNone/1.priors (
dict[str,tuple[float,float]], optional, defaultNone) – Prior ranges for sampled parameters. IfNone, 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, defaultNone) – Optional custom LSF callable for fit-time synthesis.lsf_method (
str, optional, defaultNone) – Optional built-in LSF method override for this fit.make_plots (
bool, optional, defaultTrue) – Generate diagnostic plots inside modeling fitter. Default isTrue.progress (
bool, optional, defaultTrue) – Show sampler progress output. Default isTrue.A_min (
float, optional, defaultNone) – Optional threshold override; if provided updatesself.A_min.a (
float, optional, defaultNone) – Optional stretch-move parameter override; if provided updatesself.a.fig_file (
str, optional, default"mcmc_fit") – Figure file prefix passed to modeling fitter. Default is"mcmc_fit".verbose (
bool, optional, defaultTrue) – Enable verbose output in modeling fitter. Default isTrue.pruning (
bool, optional, defaultTrue) – Enable posterior pruning in modeling fitter, check our publication for details. Default isTrue.N_Model (
int, optional, default20000) – Number of elements in the model grid. Default is20000.config (
MCMCFitConfig, optional, defaultNone) – Optional grouped configuration forwarded tocometspec.mcmc.mcmc_fitting(). Any field set on this object overrides the corresponding individual keyword argument.
- Returns:
dict[str,Any]– Fit result dictionary frommodeling.mcmc_fitting().- Raises:
ValueError – If no data/pumping/window are available.
Notes
Result keys and mirrored attributes:
param_keys->self.param_keysmedian_params->self.median_paramsup_errors_params->self.up_errors_paramslow_errors_params->self.low_errors_paramssamples_pruned->self.samples_prunedlnprob_pruned->self.lnprob_prunedmodel_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 inself.pumping_v_kmsandself.pumping_dlam_A.If extreme prior values cause the rate-matrix solver to fail (
LinAlgErrorfrom a numerically degenerate matrix, typically due to NaN/Inf collision rates at very high Q),solve_with_normalization_fastreturns NaN populations.lnlikethen 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-
Noneargument is applied to the instance. LSF settings are rebuilt according tolsf/lsf_methodand 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 (
strorSequence[str], optional, defaultNone) – Optional isotopologue selection update.systems (
strorSequence[str], optional, defaultNone) – Optional CN systems selector update.linelists (
pandas.DataFrameordict[str,pandas.DataFrame], optional, defaultNone) – Optional line-list update.logN (
float, optional, defaultNone) – Optional globallog10(N/cm^2)update.logN_by_iso (
dict[str,float], optional, defaultNone) – Optional per-isotopologuelog10(N/cm^2)update.logQ (
float, optional, defaultNone) – OptionallogQupdate.T (
float, optional, defaultNone) – Optional global temperature update.T_by_iso (
dict[str,float], optional, defaultNone) – Optional per-isotopologue temperature update. Falls back toTfor isotopologues not present.v_kms (
float, optional, defaultNone) – Optional global emission velocity shift update.v_kms_by_iso (
dict[str,float], optional, defaultNone) – Optional per-isotopologue emission velocity shift update. Falls back tov_kms.dlam (
float, optional, defaultNone) – Optional global emission wavelength shift update.dlam_by_iso (
dict[str,float], optional, defaultNone) – Optional per-isotopologue additive wavelength shift update. Falls back todlam.A_min (
float, optional, defaultNone) – Optional transition threshold update.lsf (
Callable[[numpy.ndarray],numpy.ndarray], optional, defaultNone) – Optional custom LSF callable update.lsf_method (
str, optional, defaultNone) – Optional LSF mode update.sigma (
float, optional, defaultNone) – Optional Gaussian sigma update.sigma1 (
float, optional, defaultNone) – Optional 2-Gaussian component sigma1 update.sigma2 (
float, optional, defaultNone) – Optional 2-Gaussian component sigma2 update.sigma_G (
float, optional, defaultNone) – Optional Gaussian sigma for Gauss-Lorentz update.fwhm_L (
float, optional, defaultNone) – Optional Lorentzian FWHM update.ratio (
float, optional, defaultNone) – Optional mixture ratio update.window (
tuple[float,float], optional, defaultNone) – Optional synthesis window update.pumping (
Any, optional, defaultNone) – Optional pumping spectrum update.data (
Any, optional, defaultNone) – Optional observed data update.wave_col (
str, optional, defaultNone) – Optional wavelength column-name update.flux_col (
str, optional, defaultNone) – Optional flux column-name update.error_col (
str, optional, defaultNone) – Optional uncertainty column-name update.continuum_col (
str, optional, defaultNone) – Optional continuum column-name update.omega (
float, optional, defaultnp.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.qandself.q_errtoNonewhenlogN,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:
intordict[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, solines_by_isois 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 thelinelistsargument) 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 asself.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
logNvalues.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, defaultTrue) – IfTrue, usesself.samples_prunedchains; ifFalse, uses current median values inself.logN/self.logN_by_iso. Default isTrue. Without samples, there is no error estimate.N_total_coma_km (
float, optional, default1e7) – Radius in km used to approximate total coma count in the Haser model. Default is1e7.
- Returns:
tuple[float,float]ordict[str,tuple[float,float]]– For single isotopologue, returns(logQ50, logQerr). For multi-isotopologue models, returnsdict[iso] = (logQ50, logQerr).- Raises:
ValueError – If required chains/values are missing or Haser aperture fraction is invalid.
KeyError – If expected isotopologue
logNchains are missing.
Notes
Stores computed values in
self.qandself.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()(forcorrect="q"orcorrect="both") or before (forcorrect="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. Checkcometspec.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 ascompute_production_rate().correct (
str, optional, default"both") – Which quantity to correct. One of"q"(default),"logN", or"both". Note that"q"requiresself.qandself.q_errto be set;"logN"requiresself.logNandself.logN_errto be set.eps_min_arcsec_500 (
float, optional, default0.7) – Minimum seeing FWHM at 500 nm and zenith, in arcsec. Default is0.7.eps_max_arcsec_500 (
float, optional, default1.2) – Maximum seeing FWHM at 500 nm and zenith, in arcsec. Default is1.2.zmin_deg (
float, optional, default45.0) – Minimum (best) zenith angle during observations, in degrees. Default is45.0.zmax_deg (
float, optional, default45.0) – Maximum (worst) zenith angle during observations, in degrees. Default is45.0.n_points (
int, optional, default2000) – Number of wavelength points used to sample the narrow window aroundlambda_nm. Must be >= 2. Default is2000.
- Raises:
ValueError – If
correctis 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, orself.logN_err_by_iso.
Notes
Side effects:
Updates
self.q_err/self.q_err_by_isoand setsself.q_seeing_corrected = Truewhen correctingq.Updates
self.logN_err/self.logN_err_by_isoand setsself.logN_seeing_corrected = Truewhen correctinglogN.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:
aperture (
dict) – Aperture geometry. Same format ascompute_production_rate().delta_au (
float) – Geocentric distance in AU (for arcsec → km conversion).
- 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, fromcompute_aperture_integral()or a custom calculation. Must satisfyQ = 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, defaultTrue) – IfTrue, propagates full MCMC chains; ifFalse, uses the medianlogNonly. IfFalse, 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
qandq_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
FluorescenceModelfrom disk.- Parameters:
- Returns:
FluorescenceModel– Reconstructed fluorescence model instance.- Raises:
ValueError – If the file does not contain a compatible
FluorescenceModelstate version.
Notes
Side effects: If the original model used a custom callable LSF, a warning is printed because that callable is not serialized.