Esempio n. 1
0
def ibis8542model_spectra(ibis8542model_init):
    """IBIS8542Model with random data loaded"""

    m = ibis8542model_init

    spectra = np.empty((2, 3, 4, len(m.original_wavelengths)),
                       dtype=np.float64)
    classifications = np.empty((2, 3, 4), dtype=int)

    np.random.seed(253)
    a1_array = np.random.rand(*spectra.shape[:-1]) * 500 - 800
    a2_array = np.random.rand(*spectra.shape[:-1]) * 500 + 300
    b1_array = np.random.rand(
        *spectra.shape[:-1]) / 2 - 0.25 + m.stationary_line_core
    b2_array = np.random.rand(
        *spectra.shape[:-1]) / 2 - 0.25 + m.stationary_line_core
    s1_array = np.random.rand(*spectra.shape[:-1]) / 2 + 0.1
    s2_array = np.random.rand(*spectra.shape[:-1]) / 2 + 0.1
    g1_array = np.random.rand(*spectra.shape[:-1]) / 2 + 0.1
    g2_array = np.random.rand(*spectra.shape[:-1]) / 2 + 0.1
    d_array = np.random.rand(*spectra.shape[:-1]) * 600 + 700

    a1_array[0, 1] = np.nan
    a2_array[1, :2] = np.nan

    for i in range(len(spectra)):
        for j in range(len(spectra[0])):
            for k in range(len(spectra[0, 0])):
                if np.isnan(a1_array[i, j, k]):
                    classifications[i, j, k] = 4
                    spectra[i, j,
                            k] = voigt(m.original_wavelengths, a2_array[i, j,
                                                                        k],
                                       b2_array[i, j, k], s2_array[i, j, k],
                                       g2_array[i, j, k], d_array[i, j, k])
                elif np.isnan(a2_array[i, j, k]):
                    classifications[i, j, k] = 0
                    spectra[i, j,
                            k] = voigt(m.original_wavelengths, a1_array[i, j,
                                                                        k],
                                       b1_array[i, j, k], s1_array[i, j, k],
                                       g1_array[i, j, k], d_array[i, j, k])
                else:
                    classifications[i, j, k] = 1
                    spectra[i, j, k] = double_voigt(
                        m.original_wavelengths, a1_array[i, j, k],
                        a2_array[i, j, k], b1_array[i, j, k],
                        b2_array[i, j, k], s1_array[i, j, k], s2_array[i, j,
                                                                       k],
                        g1_array[i, j, k], g2_array[i, j, k], d_array[i, j, k])

    m.load_array(spectra, names=['time', 'row', 'column', 'wavelength'])
    m.load_background(d_array, names=['time', 'row', 'column'])

    return m, classifications
Esempio n. 2
0
def test_ibis8542model_basic():
    # Will break if default parameters are changes in mcalf.models.IBIS8542Model
    wl = 1000.97
    x_orig = np.linspace(999.81, 1002.13, num=25)
    prefilter_main = 1 - np.abs(x_orig - wl) * 0.1
    prefilter_wvscl = x_orig - wl
    m = IBIS8542Model(stationary_line_core=wl,
                      original_wavelengths=x_orig,
                      prefilter_ref_main=prefilter_main,
                      prefilter_ref_wvscl=prefilter_wvscl)

    bg = 1327.243
    arr = voigt(x_orig, -231.42, wl + 0.05, 0.2, 0.21, bg)

    m.load_array(np.array([arr, arr]), names=['row', 'wavelength'])
    m.load_background(np.array([bg, bg]), names=['row'])

    # Fit with assumed neural network classification
    fit1, fit2 = m.fit(row=[0, 1], classifications=np.array([0, 0]))
    fit3 = m.fit_spectrum(arr, classifications=0,
                          background=bg)  # Make sure this is equiv
    truth = [-215.08275199, 1001.01035476, 0.00477063, 0.28869302]

    assert np.array_equal(fit1.parameters, fit2.parameters)
    assert np.array_equal(fit1.parameters, fit3.parameters)
    assert list(fit1.parameters) == pytest.approx(truth)
Esempio n. 3
0
def test_voigt_wrappers():

    for pts, params in ([pts1, params1], [pts2, params2]):

        params_absorption = params[:4]
        params_emission = params[4:-1]
        background = params[-1]

        base_absorption = voigt_nobg(pts, *params_absorption)
        base_emission = voigt_nobg(pts, *params_emission)

        assert all([
            a == b for a, b in zip(voigt(pts, *params_absorption, background),
                                   base_absorption + background)
        ])
        assert all([
            a == b for a, b in zip(
                double_voigt_nobg(pts, *params_absorption, *params_emission),
                base_absorption + base_emission)
        ])
        assert all([
            a == b for a, b in zip(
                double_voigt(pts, *params_absorption, *params_emission,
                             background), base_absorption + base_emission +
                background)
        ])

        base_absorption_approx = voigt_approx_nobg(pts, *params_absorption)
        base_emission_approx = voigt_approx_nobg(pts, *params_emission)

        assert all([
            a == b
            for a, b in zip(voigt_approx(pts, *params_absorption, background),
                            base_absorption_approx + background)
        ])
        assert all([
            a == b for a, b in zip(
                double_voigt_approx_nobg(pts, *params_absorption, *
                                         params_emission),
                base_absorption_approx + base_emission_approx)
        ])
        assert all([
            a == b for a, b in zip(
                double_voigt_approx(pts, *params_absorption, *params_emission,
                                    background), base_absorption_approx +
                base_emission_approx + background)
        ])
Esempio n. 4
0
def plot_ibis8542(wavelengths,
                  spectrum,
                  fit=None,
                  background=0,
                  sigma=None,
                  sigma_scale=70,
                  stationary_line_core=None,
                  subtraction=False,
                  separate=False,
                  show_intensity=True,
                  show_legend=True,
                  ax=None):
    """Plot an :class:`~mcalf.models.IBIS8542Model` fit.

    .. note::
        It is recommended to use the plot method built into either the
        :class:`~mcalf.models.IBIS8542Model` class or the :class:`~mcalf.models.FitResult`
        class instead.

    Parameters
    ----------
    wavelengths : numpy.ndarray
        The x-axis values.
    spectrum : numpy.ndarray, length=n_wavelengths
        The y-axis values.
    fit : array_like, optional, default=None
        The fitted parameters.
    background : float or numpy.ndarray, length=n_wavelengths, optional, default=0
        The background to add to the fitted profiles.
    sigma : numpy.ndarray, length=n_wavelengths, optional, default=None
        The sigma profile used when fitting the parameters to `spectrum`.
        If given, will be plotted as shaded regions.
    sigma_scale : float, optional, default=70
        A factor to multiply the error bars to change their prominence.
    stationary_line_core : float, optional, default=None
        If given, will show a dashed line at this wavelength.
    subtraction : bool, optional, default=False
        Whether to plot the `spectrum` minus emission fit (if exists) instead.
    separate : bool, optional, default=False
        Whether to plot the fitted profiles separately (if multiple components exist).
    show_intensity : bool, optional, default=True
        Whether to show the intensity axis tick labels and axis label.
    show_legend : bool, optional, default=True
        Whether to draw a legend on the axes.
    ax : matplotlib.axes.Axes, optional, default=None
        Axes into which the fit will be plotted.
        Defaults to the current axis of the current figure.

    Returns
    -------
    ax : matplotlib.axes.Axes
        Axes the lines are drawn on.

    See Also
    --------
    mcalf.models.IBIS8542Model.plot : General plotting method.
    mcalf.models.IBIS8542Model.plot_separate : Plot the fit parameters separately.
    mcalf.models.IBIS8542Model.plot_subtraction : Plot the spectrum with the emission fit subtracted from it.
    mcalf.models.FitResult.plot : Plotting method provided by the fit result.

    Examples
    --------
    .. minigallery:: mcalf.visualisation.plot_ibis8542
    """
    if ax is None:
        ax = plt.gca()

    plot_settings = {
        'obs': {
            'color': '#006BA4',
            'label': 'observation'
        },
        'abs': {
            'color': '#A2C8EC',
            'label': 'absorption profile'
        },
        'emi': {
            'color': '#595959',
            'label': 'emission profile'
        },
        'fit': {
            'color': '#FF800E',
            'label': 'fitted profile'
        },
        'alc': {
            'color': '#A2C8EC',
            'label': 'absorption line core',
            'linestyle': '--'
        },
        'elc': {
            'color': '#595959',
            'label': 'emission line core',
            'linestyle': ':'
        },
        'slc': {
            'color': '#ABABAB',
            'label': 'stationary line core',
            'linestyle': '--'
        },
    }
    hide_existing_labels(plot_settings, fig=ax.get_figure())

    if fit is None:
        show_fit = show_sigma = False
        subtraction = separate = False  # not possible, ignore request
    else:  # fitted parameters provided
        show_fit = True
        show_sigma = False if sigma is None else True
        if len(fit) == 8:  # two components fitted
            fit_function = double_voigt
        else:  # one component fitted
            fit_function = voigt
            subtraction = separate = False  # not possible, ignore request

    if subtraction:
        spectrum = spectrum - voigt(wavelengths, *fit[4:], 0, clib=False)
        plot_settings['obs']['label'] = 'observation - emission'
        show_fit = show_sigma = None

    if show_sigma:  # make a shaded region around the spectral data
        ax.fill_between(wavelengths,
                        spectrum - sigma * sigma_scale,
                        spectrum + sigma * sigma_scale,
                        color='lightgrey')

    # Plot the spectral data
    ax.plot(wavelengths, spectrum, **plot_settings['obs'])

    # Plot the fitted profiles if parameters are given
    if show_fit:

        if separate:  # Plot each component separately

            ax.plot(wavelengths,
                    double_voigt(wavelengths, *fit, background, clib=False),
                    **plot_settings['fit'])
            ax.plot(wavelengths,
                    voigt(wavelengths, *fit[:4], background, clib=False),
                    **plot_settings['abs'])
            ax.plot(wavelengths, voigt(wavelengths, *fit[4:], 0, clib=False),
                    **plot_settings['emi'])

        else:  # Plot a combined profile

            ax.plot(wavelengths,
                    fit_function(wavelengths, *fit, background, clib=False),
                    **plot_settings['fit'])

        # Plot absorption line core
        ax.axvline(x=fit[1], **plot_settings['alc'])

        # Plot emission line core (if fitted)
        if fit_function is double_voigt:
            ax.axvline(x=fit[5], **plot_settings['elc'])

    # Plot stationary line core
    if stationary_line_core is not None:  # Plot vertical dashed line
        ax.axvline(x=stationary_line_core, **plot_settings['slc'])

    # Format the axis ticks and labels:
    ax.minorticks_on()
    ax.set_xlabel('wavelength (Å)')
    if show_intensity:
        ax.set_ylabel('intensity')
    else:  # hide y-axis and axes box
        for loc, spine in ax.spines.items():
            if loc != 'bottom':
                spine.set_color('none')  # don't draw spine
            ax.yaxis.set_ticks([])
            ax.xaxis.set_ticks_position('bottom')

    if show_legend:
        bbox = ax.get_position()
        ax.set_position([bbox.x0, bbox.y0, bbox.width * 0.6, bbox.height])
        ax.legend(loc='upper center', bbox_to_anchor=(1.45, 0.8), ncol=1)

    return ax
Esempio n. 5
0
"""

#%%
# First we shall create a list of wavelengths, with a variable
# wavelength spacing.
# Next, we shall use the Voigt profile to generate spectral
# intensities at each of the wavelength points.
# Typically you would provide a spectrum obtained from observations.

import numpy as np
wavelengths = np.linspace(8541, 8543, 20)
wavelengths = np.delete(wavelengths, np.s_[1:6:2])
wavelengths = np.delete(wavelengths, np.s_[-6::2])

from mcalf.profiles.voigt import voigt
spectrum = voigt(wavelengths, -526, 8542, 0.1, 0.1, 1242)

#%%
# Next, we shall import :func:`mcalf.visualisation.plot_spectrum`.

from mcalf.visualisation import plot_spectrum

#%%
# We can now simply plot the spectrum.

plot_spectrum(wavelengths, spectrum)

#%%
# Notice how the spectrum above is normalised.
# The normalisation is applied by dividing through
# by the mean of the three rightmost points.
Esempio n. 6
0
def v(classification, w, *args):
    """Voigt function wrapper."""
    if classification < 1.5:  # absorption only
        return voigt(w, *args[:4], args[-1])
    return double_voigt(w, *args)  # absorption + emission