Пример #1
0
def test_auto_correct_dispersion(f=750, phi=-6, gr=2400, 
                                 verbose=True, plot=True, close_plots=True, *args, **kwargs):
    ''' A test case to show the effect of wavelength dispersion (cf spectrometer
    reciprocal function) on the slit function 
    
    Parameters
    ----------
    
    f: focal length (mm)
         default 750 (SpectraPro 2750i)

    phi: angle in degrees (°)
        default -6

    gr: grooves spacing (gr/mm)
        default 2400
    
    '''

    from radis.test.utils import getTestFile
    from publib import set_style, fix_style
    from radis.misc.warning import SlitDispersionWarning
    
    if plot:
        plt.ion()   # dont get stuck with Matplotlib if executing through pytest
        if close_plots:
            plt.close('all')

    w_slit_632, I_slit_632 = import_experimental_slit(getTestFile('slitfunction.txt'))
    slit_measured_632nm = getTestFile('slitfunction.txt')

    w, I = np.loadtxt(getTestFile('calc_N2C_spectrum_Trot1200_Tvib3000.txt')).T
    s = calculated_spectrum(w, I, conditions={'Tvib': 3000, 'Trot': 1200},
                            Iunit='mW/cm2/sr/µm')

    slit_dispersion = lambda w: linear_dispersion(w, f=f, phi=phi, m=1, gr=gr)

    s.apply_slit(slit_measured_632nm)
    if plot:
        w_full_range = np.linspace(w.min(), w_slit_632.max())
        set_style('origin')
        plt.figure('Spectrometer Dispersion (f={0}mm, phi={1}°, gr={2}'.format(
                            f, phi, gr))
        plt.plot(w_full_range, slit_dispersion(w_full_range))
        plt.xlabel('Wavelength (nm)')
        plt.ylabel('Reciprocal Linear Dispersion')
    
    # Compare 2 spectra
        s.plot(nfig='Linear dispersion effect', color='r', label='not corrected')
    with pytest.warns(SlitDispersionWarning):   # expect a "large slit dispersion" warning
        s.apply_slit(slit_measured_632nm, slit_dispersion=slit_dispersion)
    if plot:
        s.plot(nfig='same', color='k', label='corrected')
        plt.legend()
        # Plot different slits:
        s.plot_slit()
#    plt.plot(w_slit_632, I_slit_632, color='r', label='Not corrected')
#    plt.legend()

    return True  # nothing defined yet
Пример #2
0
def test_linear_dispersion_effect(verbose=True, plot=True, close_plots=True, *args, **kwargs):
    ''' A test case to show the effect of wavelength dispersion (cf spectrometer
    reciprocal function) on the slit function
    
    Test succeeds if a :py:data:`~radis.misc.warning.SlitDispersionWarning` 
    is correctly triggered
    '''

    from radis.test.utils import getTestFile
    from publib import set_style, fix_style
    
    
    if plot:
        set_style('origin')
        plt.ion()   # dont get stuck with Matplotlib if executing through pytest
        if close_plots:
            plt.close('all')

    w_slit, I_slit = import_experimental_slit(getTestFile('slitfunction.txt'))

    if plot:
        plt.figure(fig_prefix+'Linear dispersion effect')
        plt.plot(w_slit, I_slit, '--k', label='Exp: FWHM @{0}nm: {1:.3f} nm'.format(632.8,
                                                                                    get_effective_FWHM(w_slit, I_slit)))

    from radis.misc.warning import SlitDispersionWarning
    with pytest.warns(SlitDispersionWarning):   # expect a "large slit dispersion" warning
        
        # Test how slit function FWHM scales with linear_dispersion
        for w0, FWHM in zip([380, 1000, 4200, 5500],
                            [0.396, 0.388, 0.282, 0.188]):
            w, I = dirac(w0)
    
            wc, Ic = convolve_with_slit(w, I, w_slit, I_slit, norm_by='area',
                                        slit_dispersion=linear_dispersion,
                                        verbose=False)
            assert np.isclose(FWHM, get_effective_FWHM(wc, Ic), atol=0.001)
    
            if plot:
                plt.plot(wc, Ic, label='FWHM @{0:.2f} nm: {1:.3f} nm'.format(w0,
                                                                             get_effective_FWHM(wc, Ic)))

    if plot:
        plt.xlabel('Wavelength (nm)')
        plt.ylabel('Dirac $x$ slit function')
        plt.legend(loc='best', prop={'size': 15})
        fix_style('article')

    return True
Пример #3
0
result = np.empty(100)


# In[23]:


for i, n in enumerate(s):
    int = Integrate(func, 2, n)
    result[i]=int


# In[40]:


from publib import set_style, fix_style
set_style('article')  

fig = plt.figure(figsize=(10,10))
ax = plt.subplot()
ax.scatter(ns, result, label="Logarithmic integral, $L_i(n)$")

plt.title("Primes")
plt.xlabel("$n$")
plt.legend()

fix_style('article')
plt.show()


# In[ ]:
Пример #4
0
def test_normalisation_mode(plot=True,
                            close_plots=True,
                            verbose=True,
                            *args,
                            **kwargs):
    """ Test norm_by = 'area' vs norm_by = 'max' """

    from radis.test.utils import getTestFile

    if plot:
        plt.ion()  # dont get stuck with Matplotlib if executing through pytest
        if close_plots:
            plt.close("all")

        from publib import set_style

        set_style("origin")

    # %% Compare spectra convolved with area=1 and max=1
    # Slit in nm
    # Spectrum in nm
    # Specair units: mW/cm2/sr/µm
    w, I = np.loadtxt(getTestFile("calc_N2C_spectrum_Trot1200_Tvib3000.txt")).T
    s = calculated_spectrum(w,
                            I,
                            conditions={
                                "Tvib": 3000,
                                "Trot": 1200
                            },
                            Iunit="mW/cm2/sr/µm")

    FWHM = 2

    s.apply_slit(FWHM, norm_by="area")  # spectrum convolved with area=1
    w_area, I_area = s.get("radiance")
    if plot:
        fig = plt.figure(fig_prefix + "Spectrum in nm + slit in nm")
        fig.clear()
        ax = fig.gca()
        s.plot(nfig=fig.number, wunit="nm", label="norm_by: area", lw=3)
    s.apply_slit(FWHM, norm_by="max")  # spectrum convolved with max=1
    w_max, I_max = s.get("radiance", wunit="nm")
    if plot:
        ax.plot(w_max, I_max / FWHM, "r", label="(norm_by:max)/FWHM")
        ax.legend(loc="best")
    assert np.allclose(I_area, I_max / FWHM)
    if verbose:
        print("equivalence of normalisation mode for spectrum in 'nm': OK")

    # %% Compare spectra convolved with area=1 and max=1
    # Slit in nm
    # Spectrum in cm-1

    s = load_spec(getTestFile("CO_Tgas1500K_mole_fraction0.01.spec"),
                  binary=True)
    s.update()
    # spectrum convolved with area=1
    s.apply_slit(FWHM, norm_by="area", plot_slit=plot)
    w_area, I_area = s.get("radiance")
    if plot:
        fig = plt.figure(fig_prefix + "Spectrum in cm-1 + slit in nm")
        fig.clear()
        ax = fig.gca()
        s.plot(nfig=fig.number, wunit="nm", label="norm_by: area", lw=3)
    # spectrum convolved with max=1
    s.apply_slit(FWHM, norm_by="max", plot_slit=plot)
    w_max, I_max = s.get("radiance", wunit="nm")
    if plot:
        ax.plot(w_max, I_max / FWHM, "r", label="(norm_by:max)/FWHM")
        ax.legend(loc="best")
    assert np.allclose(I_area, I_max / FWHM)
    if verbose:
        print(
            "equivalence of normalisation mode for spectrum in 'cm-1': {0}: OK"
        )
    assert is_homogeneous(s.units["radiance"], "mW/cm2/sr")
    if verbose:
        print(("radiance unit ({0}) is homogeneous to 'mW/cm2/sr': OK".format(
            s.units["radiance"])))

    return True
Пример #5
0
def plot_diff(
    s1,
    s2,
    var=None,
    wunit="default",
    Iunit="default",
    resample=True,
    method="diff",
    diff_window=0,
    show_points=False,
    label1=None,
    label2=None,
    figsize=None,
    title=None,
    nfig=None,
    normalize=False,
    verbose=True,
    save=False,
    show=True,
    show_residual=False,
    lw_multiplier=1,
    diff_scale_multiplier=1,
    discard_centile=0,
    plot_medium="vacuum_only",
    legendargs={"loc": "best"},
):
    """Plot two spectra, and the difference between them. ``method=`` allows
    you to plot the absolute difference, ratio, or both.

    If waveranges dont match, ``s2`` is interpolated over ``s1``.


    Parameters
    ----------

    s1, s2: Spectrum objects

    var: str, or None
        spectral quantity to plot (ex: ``'abscoeff'``). If None,
        plot the first one in the Spectrum from ``'radiance'``,
        ``'radiance_noslit'``, ``'transmittance'``, etc.

    wunit: ``'default'``, ``'nm'``, ``'cm-1'``, ``'nm_vac'``
        wavespace unit:  wavelength air, wavenumber, wavelength vacuum.
        If ``'default'``, use first spectrum wunit

    Iunit: str
        if ``'default'``, use first spectrum unit

    method: ``'distance'``, ``'diff'``, ``'ratio'``, or list of them.
        If ``'diff'``, plot difference of the two spectra.
        If ``'distance'``, plot Euclidian distance (note that units are meaningless then)
        If ``'ratio'``, plot ratio of two spectra
        Default ``'diff'``.

        .. warning::
            with ``'distance'``, calculation scales as ~N^2 with N the number
            of points in a spectrum (against ~N with ``'diff'``). This can quickly
            override all memory.

        Can also be a list::

            method=['diff', 'ratio']

    normalize: bool
        Normalize the spectra to be ploted

    Other Parameters
    ----------------

    diff_window: int
        If non 0, calculates diff by offsetting s1 by ``diff_window`` number of
        units on either side, and returns the minimum. Kinda compensates for experimental
        errors on the w axis. Default 0. (look up code to understand...)

    show_points: boolean
        if ``True``, make all points appear with 'o'

    label1, label2: str
        curve names

    figsize
        figure size

    nfig: int, str
        figure number of name

    title: str
        title

    verbose: boolean
        if ``True``, plot stuff such as rescale ratio in normalize mode. Default ``True``

    save: str
        Default is ``False``. By default won't save anything, type the path of the
        destination if you want to save it (format in the name).

    show: Bool
        Default is ``True``. Will show the plots : bad if there are more than 20.

    show_residual: bool
        if ``True``, calculates and shows on the graph the residual in L2 norm.
        See :func:`~radis.spectrum.compare.get_residual`. ``diff_window`` is
        used in the residual calculation too. ``normalize`` has no effect.

    diff_scale_multiplier: float
        dilate the diff plot scale. Default ``1``

    discard_centile: int
        if not ``0``, discard the firsts and lasts centile when setting the limits
        of the diff window. Example::

            discard_centile=1     #  --> discards the smallest 1% and largest 1%
            discard_centile=10    #  --> discards the smallest 10% and largest 10%

        Useful to remove spikes in a ratio, for instance.
        Note that this does not change the values of the residual. It's just
        a plot feature.
        Default ``0``

    plot_medium: bool, ``'vacuum_only'``
        if ``True`` and ``wunit`` are wavelengths, plot the propagation medium
        in the xaxis label (``[air]`` or ``[vacuum]``). If ``'vacuum_only'``,
        plot only if ``wunit=='nm_vac'``. Default ``'vacuum_only'``
        (prevents from inadvertently plotting spectra with different propagation
        medium on the same graph).

    legendargs: dict
        format arguments forwarded to the legend

    Returns
    -------

    fig: figure
        fig

    [ax0, ax1]: axes
        spectra and difference axis


    Examples
    --------

    Simple use::

        from radis import plot_diff
        plot_diff(s10, s50)                # s10, s50 are two spectra

    Advanced use, plotting the total power in the label, and getting the figure
    and axes handle to edit them afterwards::

        Punit = 'mW/cm2/sr'
        fig, axes = plot_diff(s10, s50, 'radiance_noslit', figsize=(18,6),
              label1='brd 10 cm-1, P={0:.2f} {1}'.format(s10.get_power(unit=Punit),Punit),
              label2='brd 50 cm-1, P={0:.2f} {1}'.format(s50.get_power(unit=Punit),Punit)
              )
        # modify fig, axes..

    See an example in :ref:`label_spectrum_howto_compare`, which produces the output below:

    .. image:: https://radis.readthedocs.io/en/latest/_images/cdsd4000_vs_hitemp_3409K.svg

    If you wish to plot in a logscale, it can be done in the following way::

        fig, [ax0, ax1] = plot_diff(s0, s1, normalize=False, verbose=False)
        ylim0 = ax0.get_ybound()
        ax0.set_yscale("log")
        ax0.set_ybound(ylim0)

    See Also
    --------

    :func:`~radis.spectrum.compare.get_diff`,
    :func:`~radis.spectrum.compare.get_ratio`,
    :func:`~radis.spectrum.compare.get_distance`,
    :func:`~radis.spectrum.compare.get_residual`,
    :meth:`~radis.spectrum.spectrum.compare_with`

    """

    if (not show) and (
            not save
    ):  # I added this line to avoid calculus in the case there is nothing to do (Minou)
        if verbose:
            print("plot_diff : Nothing to do")
        return None, None

    # Normal behaviour (Minou)
    # Get defaults
    # ---
    if var is None:  # if nothing is defined, try these first:
        params = s1.get_vars()
        if "radiance" in params:
            var = "radiance"
        elif "radiance_noslit" in params:
            var = "radiance_noslit"
        elif "transmittance" in params:
            var = "transmittance"
        elif "transmittance_noslit" in params:
            var = "transmittance_noslit"
        else:
            # or plot the first variable we find
            var = list(params)[0]
            if var.replace("_noslit", "") in params:
                var = var.replace("_noslit", "")
    # ... check variable exist
    if var not in s1.get_vars():
        raise ValueError(
            "{0} not defined in Spectrum {1}. Use one of : {2}".format(
                var, s1.get_name(), s1.get_vars()))
    if var not in s2.get_vars():
        raise ValueError(
            "{0} not defined in Spectrum {1}. Use one of : {2}".format(
                var, s2.get_name(), s2.get_vars()))
    if Iunit == "default":
        try:
            Iunit = s1.units[var]
        except KeyError:  # unit not defined in dictionary
            raise KeyError(
                "Iunit not defined in spectrum for variable {0}. ".format(var)
                + "Cant use default unit. Specify unit in s.units['{0}'].".
                format(var))
    if wunit == "default":
        wunit = s1.get_waveunit()

    if isinstance(method, list):
        methods = method
    else:
        methods = [method]

    for method in methods:
        if diff_window != 0 and method != "diff":
            raise NotImplementedError(
                "diff_window with method {0}".format(method))

    # Get data
    # ----
    if normalize:
        # copy before modifying directly in spectrum
        s1 = s1.copy()
        s2 = s2.copy()
        w1, I1 = s1.get(var, wunit=wunit, copy=False)
        w2, I2 = s2.get(var, wunit=wunit, copy=False)
        ratio = np.nanmax(I1) / np.nanmax(I2)
        I1 /= np.nanmax(I1)
        I2 /= np.nanmax(I2)

        if verbose:
            print(("Rescale factor: " + str(ratio)))

    def get_wdiff_Idiff():
        wdiffs, Idiffs = [], []
        for method in methods:
            if not normalize:
                if method == "distance":
                    wdiff, Idiff = get_distance(s1,
                                                s2,
                                                var=var,
                                                wunit=wunit,
                                                Iunit=Iunit)
                elif method == "diff":
                    wdiff, Idiff = get_diff(
                        s1,
                        s2,
                        var=var,
                        wunit=wunit,
                        Iunit=Iunit,
                        diff_window=diff_window,
                    )
                elif method == "ratio":
                    wdiff, Idiff = get_ratio(s1,
                                             s2,
                                             var=var,
                                             wunit=wunit,
                                             Iunit=Iunit)
                else:
                    raise ValueError(
                        "Unknown comparison method: {0}".format(method))
                wdiffs.append(wdiff)
                Idiffs.append(Idiff)
            else:
                if method == "distance":
                    raise ValueError(
                        "{0} was not implemented yet for normalized spectra".
                        format(method))
                elif method == "diff":
                    wdiff, Idiff = curve_substract(w1, I1, w2, I2)
                elif method == "ratio":
                    wdiff, Idiff = get_ratio(s1,
                                             s2,
                                             var=var,
                                             wunit=wunit,
                                             Iunit=Iunit)
                else:
                    raise ValueError(
                        "Unknown comparison method: {0}".format(method))
                wdiffs.append(wdiff)
                Idiffs.append(Idiff)
        return wdiffs, Idiffs

    wdiffs, Idiffs = get_wdiff_Idiff()

    # Plot
    # ----

    # Format units
    xlabel = format_xlabel(wunit, plot_medium)

    # Init figure
    set_style("origin")
    fig = plt.figure(num=nfig, figsize=figsize)
    gs = gridspec.GridSpec(1 + len(methods),
                           1,
                           height_ratios=[3] + [1] * len(methods))
    ax0 = plt.subplot(gs[0])
    ax0.ticklabel_format(useOffset=False)
    ax1 = []
    for i in range(len(methods)):
        ax1i = plt.subplot(gs[i + 1])
        ax1i.get_shared_x_axes().join(ax0, ax1i)
        ax1i.ticklabel_format(useOffset=False)
        ax1.append(ax1i)

    # Plotting style
    if show_points:
        style = "-o"
    else:
        style = "-"

    # Get labels and names
    if label1 is None:
        label1 = s1.get_name()
    if label2 is None:
        label2 = s2.get_name()
    # Max label length:
    if len(label1) > 60:
        label1 = label1[:58] + "..."
    if len(label2) > 60:
        label2 = label2[:58] + "..."

    # Plot compared spectra
    if normalize:
        # TODO: add option to norm_on
        ax0.plot(w1, I1, style, color="k", lw=3 * lw_multiplier, label=label1)
        ax0.plot(w2, I2, style, color="r", lw=1 * lw_multiplier, label=label2)
    else:
        ax0.plot(*s1.get(var, wunit=wunit, Iunit=Iunit),
                 style,
                 color="k",
                 lw=3 * lw_multiplier,
                 label=label1)
        ax0.plot(*s2.get(var, wunit=wunit, Iunit=Iunit),
                 style,
                 color="r",
                 lw=1 * lw_multiplier,
                 label=label2)

    # cosmetic changes
    Iunit = make_up_unit(Iunit, var)

    ax0.tick_params(labelbottom=False)
    if label1 is not None or label2 is not None:
        ax0.legend(**legendargs)

    # Start to 0
    if var in ["radiance_noslit", "radiance", "abscoeff", "absorbance"]:
        ax0.set_ylim(bottom=0)

    # plot difference (sorted)
    for ax1i, wdiff, Idiff in zip(ax1, wdiffs, Idiffs):
        b = np.argsort(wdiff)
        ax1i.plot(wdiff[b], Idiff[b], style, color="k", lw=1 * lw_multiplier)

    # Write labels
    ax1[-1].set_xlabel(make_up(xlabel))
    if normalize:
        fig.text(
            0.02,
            0.5,
            ("{0} (norm.)".format(make_up(var))),
            va="center",
            rotation="vertical",
        )
    else:
        fig.text(
            0.02,
            0.5,
            ("{0} ({1})".format(make_up(var), Iunit)),
            va="center",
            rotation="vertical",
        )

    # Set limits of 'diff' window
    for i, method in enumerate(methods):
        if method == "diff":
            # symmetrize error scale:
            # auto-zoom on min, max, but discard first and last centile (case of spikes / divergences)
            Idiff = Idiffs[i]
            if discard_centile:
                Idiff_sorted = np.sort(Idiff[~np.isnan(Idiff)])
                ymax = max(
                    abs(Idiff_sorted[-int(discard_centile *
                                          len(Idiff_sorted) // 100)]),
                    abs(Idiff_sorted[int(discard_centile * len(Idiff_sorted) //
                                         100)]),
                )
            else:
                ymax = np.nanmax(abs(Idiff))
            ax1[i].set_ylim(-ymax * diff_scale_multiplier,
                            ymax * diff_scale_multiplier)
        elif method == "distance":
            if discard_centile:
                raise NotImplementedError(
                    "discard_centile not implemented for method=distance")
            _, ymax = ax1[i].get_ylim()
            ax1[i].set_ylim(0, ymax * diff_scale_multiplier)
        elif method == "ratio":
            # auto-zoom on min, max, but discard first and last centile (case of spikes / divergences)
            Idiff = Idiffs[i]
            if discard_centile:
                Idiff_sorted = np.sort(Idiff[~np.isnan(Idiff)])
                ymin = Idiff_sorted[int(discard_centile * len(Idiff_sorted) //
                                        100)]
                ymax = Idiff_sorted[-int(discard_centile * len(Idiff_sorted) //
                                         100)]
            else:
                ymin = np.nanmin(Idiff)
                ymax = np.nanmax(Idiff)
            ax1[i].set_ylim(
                bottom=((ymin - 1) * diff_scale_multiplier + 1),
                top=((ymax - 1) * diff_scale_multiplier + 1),
            )
    #            ymax = max(abs(Idiff_sorted[len(Idiff_sorted)//100]-1),
    #                       abs(Idiff_sorted[len(-Idiff_sorted)//100]-1))
    #            ax1[i].set_ylim(ymax*diff_scale_multiplier+1, -ymax*diff_scale_multiplier+1)

    if title:
        fig.suptitle(title)
    # Fix format
    fix_style("origin", ax=ax0)
    for ax1i in ax1:
        fix_style("origin", ax=ax1i)
    plt.tight_layout()
    if title:
        plt.subplots_adjust(left=0.15, top=0.92)
    else:
        plt.subplots_adjust(left=0.15)

    # Plot difference text
    for i, method in enumerate(methods):
        if method == "diff":
            difftext = "diff"
            ax1[i].axhline(y=0, color="grey", zorder=-1)
        elif method == "distance":
            difftext = "distance"
            ax1[i].axhline(y=0, color="grey", zorder=-1)
        elif method == "ratio":
            difftext = "ratio"
            ax1[i].axhline(y=1, color="grey", zorder=-1)

        # Show residualget_residual
        if show_residual:
            difftext += " (residual={0:.2g})".format(
                get_residual(s1,
                             s2,
                             var=var,
                             norm="L2",
                             ignore_nan=True,
                             diff_window=diff_window))
        pos = ax1[i].get_position()
        fig.text(0.09, pos.ymax + 0.02, difftext)

    # Add cursors
    axes = [ax0] + ax1
    fig.cursors = MultiCursor(
        fig.canvas,
        axes,
        color="r",
        lw=1 * lw_multiplier,
        alpha=0.2,
        horizOn=False,
        vertOn=True,
    )
    if show:
        plt.show()
    if save:
        fig.savefig(save)
        if not show:
            plt.close(fig)  # to avoid memory load

    # Return graphs
    return fig, axes
Пример #6
0
def Integrate(f, a, b):
    I, _ = integrate.quad(f, a, b)
    return I


ft = lambda t: 1 / log(t)
limits = list(linspace(10, 10**10, 100))
Li = []
n = []

for i in limits:
    temp = Integrate(ft, 2, i)

    #Append results i times
    Li.append(temp)
    n.append(i)

#Creating figure
set_style('article')  #before the first plot

plt.figure()
ax = plt.subplot()
ax.plot(n, Li, 'o', label='Logarithmic integral')
plt.xlabel(r'$n \in [10,10^{10}]$')
plt.ylabel(r'$Li(n)=\int_{2}^n \frac{1}{\log \: t}dt$')
plt.title('A nice title')
plt.legend(loc='upper left')

fix_style('article')
plt.show()
Пример #7
0
def test_normalisation_mode(plot=True,
                            close_plots=True,
                            verbose=True,
                            *args,
                            **kwargs):
    ''' Test norm_by = 'area' vs norm_by = 'max' '''

    from radis.test.utils import getTestFile

    if plot:
        plt.ion()  # dont get stuck with Matplotlib if executing through pytest
        if close_plots:
            plt.close('all')

        from publib import set_style
        set_style('origin')

    # %% Compare spectra convolved with area=1 and max=1
    # Slit in nm
    # Spectrum in nm
    # Specair units: mW/cm2/sr/µm
    w, I = np.loadtxt(getTestFile('calc_N2C_spectrum_Trot1200_Tvib3000.txt')).T
    s = calculated_spectrum(w,
                            I,
                            conditions={
                                'Tvib': 3000,
                                'Trot': 1200
                            },
                            Iunit='mW/cm2/sr/µm')

    FWHM = 2

    s.apply_slit(FWHM, norm_by='area')  # spectrum convolved with area=1
    w_area, I_area = s.get('radiance')
    if plot:
        fig = plt.figure(fig_prefix + 'Spectrum in nm + slit in nm')
        fig.clear()
        ax = fig.gca()
        s.plot(nfig=fig.number, wunit='nm', label='norm_by: area', lw=3)
    s.apply_slit(FWHM, norm_by='max')  # spectrum convolved with max=1
    w_max, I_max = s.get('radiance', wunit='nm')
    if plot:
        ax.plot(w_max, I_max / FWHM, 'r', label='(norm_by:max)/FWHM')
        ax.legend(loc='best')
    assert np.allclose(I_area, I_max / FWHM)
    if verbose:
        print("equivalence of normalisation mode for spectrum in 'nm': OK")

    # %% Compare spectra convolved with area=1 and max=1
    # Slit in nm
    # Spectrum in cm-1

    s = load_spec(getTestFile('CO_Tgas1500K_mole_fraction0.01.spec'),
                  binary=True)
    s.update()
    # spectrum convolved with area=1
    s.apply_slit(FWHM, norm_by='area', plot_slit=plot)
    w_area, I_area = s.get('radiance')
    if plot:
        fig = plt.figure(fig_prefix + 'Spectrum in cm-1 + slit in nm')
        fig.clear()
        ax = fig.gca()
        s.plot(nfig=fig.number, wunit='nm', label='norm_by: area', lw=3)
    # spectrum convolved with max=1
    s.apply_slit(FWHM, norm_by='max', plot_slit=plot)
    w_max, I_max = s.get('radiance', wunit='nm')
    if plot:
        ax.plot(w_max, I_max / FWHM, 'r', label='(norm_by:max)/FWHM')
        ax.legend(loc='best')
    assert np.allclose(I_area, I_max / FWHM)
    if verbose:
        print(
            "equivalence of normalisation mode for spectrum in 'cm-1': {0}: OK"
        )
    assert is_homogeneous(s.units['radiance'], 'mW/cm2/sr')
    if verbose:
        print(("radiance unit ({0}) is homogeneous to 'mW/cm2/sr': OK".format(
            s.units['radiance'])))

    return True
Пример #8
0
import numpy as np
from scipy import integrate
import matplotlib.pyplot as plt
import math
%matplotlib inline
from publib import set_style, fix_style

set_style(['origin','latex']) # the style sheet is from https://github.com/erwanp/publib

def Integrate(f, a, b):
        I, _ = integrate.quad(f, a, b)
        return I


f = lambda x : 1/(math.log(x))

fig, ax = plt.subplots(figsize=(16,6))
Ns = np.linspace(10,10**10,100)
Is = [Integrate(f,n,2) for n in Ns]
ax.plot(Ns,Is, label="Li(n)")

ax.legend(bbox_to_anchor=(1.2, 1))
fix_style(['origin', 'latex'])
from radis import cm2nm
from radis.misc import centered_diff
from publib import set_style, fix_style

#%% ===========================================================================
# Read Data and get Inputs
# =============================================================================

SAVE_OUTPUT = True

#%% Read atmosphere data
atm = pd.read_csv(r'data/atmosphere_standard_profile_1976.csv', comment='#')
atm['path_length'] = centered_diff(atm.z_km)

#%% Plot atmosphere data
set_style('origin')
fig, ax = plt.subplots()
ax.plot(atm.P_Pa * 1e-5, atm.z_km)
ax.set_xlabel('Pressure [bar]')
ax.set_ylabel('Altitude [km]')

ax2 = ax.twiny()
ax2.plot(atm.T_K, atm.z_km, 'r')
ax2.set_xlabel('Temperature [K]', color='r')
ax2.tick_params('x', colors='r')

plt.tight_layout()
fix_style('origin')

if SAVE_OUTPUT:
    from radis.misc import make_folders
Пример #10
0
def plot_diff(s1,
              s2,
              var=None,
              wunit='default',
              Iunit='default',
              medium='default',
              resample=True,
              method='diff',
              show_points=False,
              label1=None,
              label2=None,
              figsize=None,
              title=None,
              nfig=None,
              normalize=False,
              verbose=True):
    ''' Plot two spectra, and the difference between them
    
    If waveranges dont match, `s2` is interpolated over `s1`. 
    
    
    Parameters    
    ----------
    
    s1, s2: Spectrum objects
    
    var: str, or None
        spectral quantity to plot (ex: 'abscoeff'). If None, plot the first one 
        in the Spectrum from 'radiance', 'radiance_noslit', 'transmittance', etc.
        
    wunit: 'default', 'nm', 'cm-1'
        if 'default', use first spectrum wunit
    
    Iunit: str
        if 'default', use first spectrum unit
        
    medium: 'air', 'vacuum', 'default'
        if 'default', use first spectrum propagating medium
        
    method: 'distance', 'diff', 'ratio'
        If 'diff', plot difference at same wavespace position. 
        If 'distance', plot Euclidian distance (note that units are meaningless then)
        If 'ratio', plot ratio of two spectra
        Default 'diff'.
        
        Warning: with 'distance', calculation scales as ~N^2 with N the number
        of points in a spectrum (against ~N with 'diff'). This can quickly 
        override all memory.
        
    normalize: bool
        Normalize the spectra to be ploted 
        
    Other Parameters
    ----------------
    
    show_points: boolean
        if True, make all points appear with 'o'
    
    label1, label2: str
        curve names
        
    figsize
        figure size
        
    nfig: int, str
        figure number of name
        
    title: str
        title

    verbose: boolean
        if True, plot stuff such as rescale ratio in normalize mode. Default True


    Examples
    --------

    >>> Punit = 'mW/cm2/sr'
    >>> fig, axes = plot_diff(s10, s50, figsize=(18,6),
    >>>       label1='brd 10 cm-1, P={0:.2f} {1}'.format(s10.get_power(unit=Punit),Punit),
    >>>       label2='brd 50 cm-1, P={0:.2f} {1}'.format(s50.get_power(unit=Punit),Punit)
    >>>       )
    
    
    
    See Also
    --------
    
    :func:`~radis.spectrum.compare.get_diff`, 
    :func:`~radis.spectrum.compare.get_ratio`, 
    :func:`~radis.spectrum.compare.get_distance`, 
    :func:`~radis.spectrum.compare.get_residual`, 
    :meth:`~radis.spectrum.spectrum.compare_with` 
    
    '''

    # Get defaults
    # ---
    if var is None:  # if nothing is defined, try these first:
        params = s1.get_vars()
        if 'radiance' in params:
            var = 'radiance'
        elif 'radiance_noslit' in params:
            var = 'radiance_noslit'
        elif 'transmittance' in params:
            var = 'transmittance'
        elif 'transmittance_noslit' in params:
            var = 'transmittance_noslit'
        else:
            # or plot the first variable we find
            var = list(params)[0]
            if var.replace('_noslit', '') in params:
                var = var.replace('_noslit', '')
    if Iunit == 'default':
        try:
            Iunit = s1.units[var]
        except KeyError:  # unit not defined in dictionary
            raise KeyError('Iunit not defined in spectrum. Cant plot')
    if wunit == 'default':
        wunit = s1.get_waveunit()
    if medium == 'default':
        medium = s1.conditions.get('medium', None)

    # Get data
    # ----
    if method == 'distance':
        wdiff, Idiff = get_distance(s1,
                                    s2,
                                    var=var,
                                    wunit=wunit,
                                    Iunit=Iunit,
                                    medium=medium)
    elif method == 'diff':
        wdiff, Idiff = get_diff(s1,
                                s2,
                                var=var,
                                wunit=wunit,
                                Iunit=Iunit,
                                medium=medium)
    elif method == 'ratio':
        wdiff, Idiff = get_ratio(s1,
                                 s2,
                                 var=var,
                                 wunit=wunit,
                                 Iunit=Iunit,
                                 medium=medium)
    else:
        raise ValueError('Unknown comparison method: {0}'.format(method))

    # Plot
    # ----

    # Format units
    wunit = cast_waveunit(wunit)
    if wunit == 'cm-1':
        xlabel = 'Wavenumber (cm-1)'
    elif wunit == 'nm':
        xlabel = 'Wavelength (nm)'

    # Init figure
    set_style('origin')
    fig = plt.figure(num=nfig, figsize=figsize)
    gs = gridspec.GridSpec(2, 1, height_ratios=[3, 1])
    ax0 = plt.subplot(gs[0])
    ax1 = plt.subplot(gs[1])
    ax1.get_shared_x_axes().join(ax0, ax1)

    # Plotting style
    if show_points:
        style = '-o'
    else:
        style = '-'

    # Get labels and names
    if label1 is None:
        label1 = s1.get_name()
    if label2 is None:
        label2 = s2.get_name()
    # Plot compared spectra
    if normalize:
        w1, I1 = s1.get(var, wunit, Iunit, medium)
        w2, I2 = s2.get(var, wunit, Iunit, medium)
        if verbose: print(('Rescale factor: ' + str(np.max(I1) / np.max(I2))))
        ax0.plot(w1, I1 / np.max(I1), ls=style, color='k', lw=3, label=label1)
        ax0.plot(w2, I2 / np.max(I2), ls=style, color='r', lw=1, label=label2)
    else:
        ax0.plot(*s1.get(var, wunit, Iunit, medium),
                 ls=style,
                 color='k',
                 lw=3,
                 label=label1)
        ax0.plot(*s2.get(var, wunit, Iunit, medium),
                 ls=style,
                 color='r',
                 lw=1,
                 label=label2)

    Iunit = make_up(Iunit)  # cosmetic changes

    ax0.tick_params(labelbottom='off')
    if label1 is not None or label2 is not None:
        ax0.legend(loc='best')

    # Start to 0
    if var in ['radiance_noslit', 'radiance', 'abscoeff', 'absorbance']:
        ax0.set_ylim(bottom=0)

    # plot difference (sorted)
    b = np.argsort(wdiff)
    ax1.plot(wdiff[b], Idiff[b], style, color='k', lw=1)

    if method == 'diff':
        fig.text(0.09, 0.38, 'diff')
    elif method == 'distance':
        fig.text(0.09, 0.38, 'distance')
    elif method == 'ratio':
        fig.text(0.09, 0.38, 'ratio')

    # Write labels
    ax1.set_xlabel(make_up(xlabel))
    if normalize:
        fig.text(0.02, 0.5, 'Arb. Units', va='center', rotation='vertical')
    else:
        fig.text(0.02,
                 0.5, ('{0} ({1})'.format(make_up(var), Iunit)),
                 va='center',
                 rotation='vertical')

    # Set limits
    if method == 'diff':
        # symmetrize error scale:
        ymin, ymax = ax1.get_ylim()
        ymax = max(abs(ymin), abs(ymax))
        ax1.set_ylim(-ymax, ymax)
    elif method == 'distance':
        ax1.set_ylim(bottom=0)
    elif method == 'ratio':
        # auto-zoom on min, max, but discard first decile (case of spikes / divergences)
        Idiff_s = np.sort(Idiff)
        ax1.set_ylim(bottom=0,
                     top=Idiff_s[len(Idiff_s) // 10] +
                     Idiff_s[-len(Idiff_s) // 10])

    if title:
        fig.suptitle(title)

    # Fix format
    fix_style('origin', ax=ax0)
    fix_style('origin', ax=ax1)
    plt.tight_layout()
    if title:
        plt.subplots_adjust(left=0.15, top=0.92)
    else:
        plt.subplots_adjust(left=0.15)

    # Add cursors
    fig.cursors = MultiCursor(fig.canvas, (ax0, ax1),
                              color='r',
                              lw=1,
                              alpha=0.2,
                              horizOn=False,
                              vertOn=True)

    return fig, [ax0, ax1]
Пример #11
0
def plot_diff(s1,
              s2,
              var=None,
              wunit='default',
              Iunit='default',
              medium='default',
              resample=True,
              method='diff',
              diff_window=0,
              show_points=False,
              label1=None,
              label2=None,
              figsize=None,
              title=None,
              nfig=None,
              normalize=False,
              verbose=True,
              save=False,
              show=True,
              show_residual=False,
              lw_multiplier=1,
              diff_scale_multiplier=1,
              discard_centile=0):
    ''' Plot two spectra, and the difference between them. ``method=`` allows
    you to plot the absolute difference, ratio, or both. 

    If waveranges dont match, ``s2`` is interpolated over ``s1``. 


    Parameters    
    ----------

    s1, s2: Spectrum objects

    var: str, or None
        spectral quantity to plot (ex: ``'abscoeff'``). If None, 
        plot the first one in the Spectrum from ``'radiance'``, 
        ``'radiance_noslit'``, ``'transmittance'``, etc.

    wunit: ``'default'``, ``'nm'``, ``'cm-1'``
        if ``'default'``, use first spectrum wunit

    Iunit: str
        if ``'default'``, use first spectrum unit

    medium: ``'air'``, ``'vacuum'``, ``'default'``
        if ``'default'``, use first spectrum propagating medium

    method: ``'distance'``, ``'diff'``, ``'ratio'``, or list of them.
        If ``'diff'``, plot difference of the two spectra.
        If ``'distance'``, plot Euclidian distance (note that units are meaningless then)
        If ``'ratio'``, plot ratio of two spectra
        Default ``'diff'``.

        .. warning::
            with ``'distance'``, calculation scales as ~N^2 with N the number
            of points in a spectrum (against ~N with ``'diff'``). This can quickly 
            override all memory.
            
        Can also be a list::
            
            method=['diff', 'ratio']

    normalize: bool
        Normalize the spectra to be ploted 

    Other Parameters
    ----------------

    diff_window: int
        If non 0, calculates diff by offsetting s1 by ``diff_window`` number of
        units on either side, and returns the minimum. Kinda compensates for experimental
        errors on the w axis. Default 0. (look up code to understand...)

    show_points: boolean
        if ``True``, make all points appear with 'o'

    label1, label2: str
        curve names

    figsize
        figure size

    nfig: int, str
        figure number of name

    title: str
        title

    verbose: boolean
        if ``True``, plot stuff such as rescale ratio in normalize mode. Default ``True``

    save: str
        Default is ``False``. By default won't save anything, type the path of the 
        destination if you want to save it (format in the name).
        
    show: Bool
        Default is ``True``. Will show the plots : bad if there are more than 20.
    
    show_residual: bool
        if ``True``, calculates and shows on the graph the residual in L2 norm. 
        See :func:`~radis.spectrum.compare.get_residual`. ``diff_window`` is 
        used in the residual calculation too. ``normalize`` has no effect. 
        
    diff_scale_multiplier: float
        dilate the diff plot scale. Default ``1``
    
    discard_centile: int
        if not ``0``, discard the firsts and lasts centile when setting the limits
        of the diff window. Example::
            
            discard_centile=1     #  --> discards the smallest 1% and largest 1%
            discard_centile=10    #  --> discards the smallest 10% and largest 10%
            
        Useful to remove spikes in a ratio, for instance. 
        Note that this does not change the values of the residual. It's just 
        a plot feature.
        Default ``0`` 
        
    Returns
    -------
    
    fig: figure
        fig
    
    [ax0, ax1]: axes
        spectra and difference axis
    
        
    Examples
    --------
    
    Simple use::
        
        from radis import plot_diff
        plot_diff(s10, s50)                # s10, s50 are two spectra

    Advanced use, plotting the total power in the label, and getting the figure 
    and axes handle to edit them afterwards::

        Punit = 'mW/cm2/sr'
        fig, axes = plot_diff(s10, s50, 'radiance_noslit', figsize=(18,6),
              label1='brd 10 cm-1, P={0:.2f} {1}'.format(s10.get_power(unit=Punit),Punit),
              label2='brd 50 cm-1, P={0:.2f} {1}'.format(s50.get_power(unit=Punit),Punit)
              )
        # modify fig, axes..

    See an example output in :ref:`Compare two Spectra <label_spectrum_howto_compare>`

    See Also
    --------

    :func:`~radis.spectrum.compare.get_diff`, 
    :func:`~radis.spectrum.compare.get_ratio`, 
    :func:`~radis.spectrum.compare.get_distance`, 
    :func:`~radis.spectrum.compare.get_residual`, 
    :meth:`~radis.spectrum.spectrum.compare_with` 

    '''

    if (not show) and (
            not save
    ):  #I added this line to avoid calculus in the case there is nothing to do (Minou)
        if verbose: print('plot_diff : Nothing to do')
        return None, None

    #Normal behaviour (Minou)
    # Get defaults
    # ---
    if var is None:  # if nothing is defined, try these first:
        params = s1.get_vars()
        if 'radiance' in params:
            var = 'radiance'
        elif 'radiance_noslit' in params:
            var = 'radiance_noslit'
        elif 'transmittance' in params:
            var = 'transmittance'
        elif 'transmittance_noslit' in params:
            var = 'transmittance_noslit'
        else:
            # or plot the first variable we find
            var = list(params)[0]
            if var.replace('_noslit', '') in params:
                var = var.replace('_noslit', '')
    # ... check variable exist
    if var not in s1.get_vars():
        raise ValueError(
            '{0} not defined in Spectrum {1}. Use one of : {2}'.format(
                var, s1.get_name(), s1.get_vars()))
    if var not in s2.get_vars():
        raise ValueError(
            '{0} not defined in Spectrum {1}. Use one of : {2}'.format(
                var, s2.get_name(), s2.get_vars()))
    if Iunit == 'default':
        try:
            Iunit = s1.units[var]
        except KeyError:  # unit not defined in dictionary
            raise KeyError('Iunit not defined in spectrum for variable {0}. '.format(var)+\
                           "Cant use default unit. Specify unit in s.units['{0}'].".format(var))
    if wunit == 'default':
        wunit = s1.get_waveunit()
    if medium == 'default':
        medium = s1.conditions.get('medium', None)

    if isinstance(method, list):
        methods = method
    else:
        methods = [method]

    for method in methods:
        if diff_window != 0 and method != 'diff':
            raise NotImplementedError(
                'diff_window with method {0}'.format(method))

    # Get data
    # ----
    if normalize:
        # copy before modifying directly in spectrum
        s1 = s1.copy()
        s2 = s2.copy()
        w1, I1 = s1.get(var, copy=False)
        w2, I2 = s2.get(var, copy=False)
        I1 /= np.max(I1)
        I2 /= np.max(I2)
        if verbose:
            print(('Rescale factor: ' + str(np.max(I1) / np.max(I2))))

    def get_wdiff_Idiff():
        wdiffs, Idiffs = [], []
        for method in methods:
            if not normalize:
                if method == 'distance':
                    wdiff, Idiff = get_distance(s1,
                                                s2,
                                                var=var,
                                                wunit=wunit,
                                                Iunit=Iunit,
                                                medium=medium)
                elif method == 'diff':
                    wdiff, Idiff = get_diff(s1,
                                            s2,
                                            var=var,
                                            wunit=wunit,
                                            Iunit=Iunit,
                                            medium=medium,
                                            diff_window=diff_window)
                elif method == 'ratio':
                    wdiff, Idiff = get_ratio(s1,
                                             s2,
                                             var=var,
                                             wunit=wunit,
                                             Iunit=Iunit,
                                             medium=medium)
                else:
                    raise ValueError(
                        'Unknown comparison method: {0}'.format(method))
                wdiffs.append(wdiff)
                Idiffs.append(Idiff)
            else:
                if method == 'distance':
                    raise ValueError(
                        '{0} was not implemented yet for normalized spectra'.
                        format(method))
                elif method == 'diff':
                    wdiff, Idiff = curve_substract(w1, I1, w2, I2)
                elif method == 'ratio':
                    wdiff, Idiff = get_ratio(s1,
                                             s2,
                                             var=var,
                                             wunit=wunit,
                                             Iunit=Iunit,
                                             medium=medium)
                else:
                    raise ValueError(
                        'Unknown comparison method: {0}'.format(method))
                wdiffs.append(wdiff)
                Idiffs.append(Idiff)
        return wdiffs, Idiffs

    wdiffs, Idiffs = get_wdiff_Idiff()

    # Plot
    # ----

    # Format units
    wunit = cast_waveunit(wunit)
    if wunit == 'cm-1':
        xlabel = 'Wavenumber (cm-1)'
    elif wunit == 'nm':
        xlabel = 'Wavelength (nm)'

    # Init figure
    set_style('origin')
    fig = plt.figure(num=nfig, figsize=figsize)
    gs = gridspec.GridSpec(1 + len(methods),
                           1,
                           height_ratios=[3] + [1] * len(methods))
    ax0 = plt.subplot(gs[0])
    ax0.ticklabel_format(useOffset=False)
    ax1 = []
    for i in range(len(methods)):
        ax1i = plt.subplot(gs[i + 1])
        ax1i.get_shared_x_axes().join(ax0, ax1i)
        ax1i.ticklabel_format(useOffset=False)
        ax1.append(ax1i)

    # Plotting style
    if show_points:
        style = '-o'
    else:
        style = '-'

    # Get labels and names
    if label1 is None:
        label1 = s1.get_name()
    if label2 is None:
        label2 = s2.get_name()
    # Max label length:
    if len(label1) > 60:
        label1 = label1[:58] + '...'
    if len(label2) > 60:
        label2 = label2[:58] + '...'

    # Plot compared spectra
    if normalize:
        # TODO: add option to norm_on
        ax0.plot(w1,
                 I1,
                 ls=style,
                 color='k',
                 lw=3 * lw_multiplier,
                 label=label1)
        ax0.plot(w2,
                 I2,
                 ls=style,
                 color='r',
                 lw=1 * lw_multiplier,
                 label=label2)
    else:
        ax0.plot(*s1.get(var, wunit, Iunit, medium),
                 ls=style,
                 color='k',
                 lw=3 * lw_multiplier,
                 label=label1)
        ax0.plot(*s2.get(var, wunit, Iunit, medium),
                 ls=style,
                 color='r',
                 lw=1 * lw_multiplier,
                 label=label2)

    Iunit = make_up(Iunit)  # cosmetic changes

    ax0.tick_params(labelbottom=False)
    if label1 is not None or label2 is not None:
        ax0.legend(loc='best')

    # Start to 0
    if var in ['radiance_noslit', 'radiance', 'abscoeff', 'absorbance']:
        ax0.set_ylim(bottom=0)

    # plot difference (sorted)
    for ax1i, wdiff, Idiff in zip(ax1, wdiffs, Idiffs):
        b = np.argsort(wdiff)
        ax1i.plot(wdiff[b], Idiff[b], style, color='k', lw=1 * lw_multiplier)

    # Write labels
    ax1[-1].set_xlabel(make_up(xlabel))
    if normalize:
        fig.text(0.02, 0.5, 'Arb. Units', va='center', rotation='vertical')
    else:
        fig.text(0.02,
                 0.5, ('{0} ({1})'.format(make_up(var), Iunit)),
                 va='center',
                 rotation='vertical')

    # Set limits of 'diff' window
    for i, method in enumerate(methods):
        if method == 'diff':
            # symmetrize error scale:
            # auto-zoom on min, max, but discard first and last centile (case of spikes / divergences)
            Idiff = Idiffs[i]
            if discard_centile:
                Idiff_sorted = np.sort(Idiff[~np.isnan(Idiff)])
                ymax = max(
                    abs(Idiff_sorted[-int(discard_centile *
                                          len(Idiff_sorted) // 100)]),
                    abs(Idiff_sorted[int(discard_centile * len(Idiff_sorted) //
                                         100)]))
            else:
                ymax = np.nanmax(abs(Idiff))
            ax1[i].set_ylim(-ymax * diff_scale_multiplier,
                            ymax * diff_scale_multiplier)
        elif method == 'distance':
            if discard_centile:
                raise NotImplementedError(
                    'discard_centile not implemented for method=distance')
            _, ymax = ax1[i].get_ylim()
            ax1[i].set_ylim(0, ymax * diff_scale_multiplier)
        elif method == 'ratio':
            # auto-zoom on min, max, but discard first and last centile (case of spikes / divergences)
            Idiff = Idiffs[i]
            if discard_centile:
                Idiff_sorted = np.sort(Idiff[~np.isnan(Idiff)])
                ymin = Idiff_sorted[int(discard_centile * len(Idiff_sorted) //
                                        100)]
                ymax = Idiff_sorted[-int(discard_centile * len(Idiff_sorted) //
                                         100)]
            else:
                ymin = np.nanmin(Idiff)
                ymax = np.nanmax(Idiff)
            ax1[i].set_ylim(bottom=((ymin - 1) * diff_scale_multiplier + 1),
                            top=((ymax - 1) * diff_scale_multiplier + 1))


#            ymax = max(abs(Idiff_sorted[len(Idiff_sorted)//100]-1),
#                       abs(Idiff_sorted[len(-Idiff_sorted)//100]-1))
#            ax1[i].set_ylim(ymax*diff_scale_multiplier+1, -ymax*diff_scale_multiplier+1)

    if title:
        fig.suptitle(title)

    # Fix format
    fix_style('origin', ax=ax0)
    for ax1i in ax1:
        fix_style('origin', ax=ax1i)
    plt.tight_layout()
    if title:
        plt.subplots_adjust(left=0.15, top=0.92)
    else:
        plt.subplots_adjust(left=0.15)

    # Plot difference text
    for i, method in enumerate(methods):
        if method == 'diff':
            difftext = 'diff'
            ax1[i].axhline(y=0, color='grey', zorder=-1)
        elif method == 'distance':
            difftext = 'distance'
            ax1[i].axhline(y=0, color='grey', zorder=-1)
        elif method == 'ratio':
            difftext = 'ratio'
            ax1[i].axhline(y=1, color='grey', zorder=-1)

        # Show residualget_residual
        if show_residual:
            difftext += ' (residual={0:.2g})'.format(
                get_residual(s1,
                             s2,
                             var=var,
                             norm='L2',
                             ignore_nan=True,
                             diff_window=diff_window))
        pos = ax1[i].get_position()
        fig.text(0.09, pos.ymax + 0.02, difftext)

    # Add cursors
    axes = [ax0] + ax1
    fig.cursors = MultiCursor(fig.canvas,
                              axes,
                              color='r',
                              lw=1 * lw_multiplier,
                              alpha=0.2,
                              horizOn=False,
                              vertOn=True)
    if show:
        plt.show()
    if save:
        fig.savefig(save)
        if not show:
            plt.close(fig)  #to avoid memory load if

    # Return graphs
    return fig, axes