Esempio n. 1
0
    def __init__(self, Spectrum, init_cont=True, n_anchors=4):

        self.__dict__.update(Spectrum.__dict__)

        self.wave = Spectrum.wave
        self.flux = Spectrum.flux
        self.Spectrum = Spectrum

        if init_cont:
            cont_model = ContinuumModel(n_anchors=n_anchors)
            cont_pars = cont_model.guess(self.flux, x=self.wave)

            for yname in cont_model.ynames:
                flux_range = np.max(self.flux) - np.min(self.flux)
                ymin = cont_pars[yname].value - (flux_range / 2)
                ymax = cont_pars[yname].value + (flux_range / 2)

                cont_pars[yname].set(min=ymin, max=ymax)

        self.cont_model = cont_model
        self.cont_model_pars = cont_pars

        self.complete_model = cont_model
        self.all_pars = cont_pars

        self.peaks = []

        self.n_anchors = n_anchors
        self.n_lines = 0
        self.num_prior_lines = 0
        self.source_names = []

        self.add_source("Telluric", similar={'b': 2})
        self.add_source("Nontelluric", similar=None)
Esempio n. 2
0
    def SplineManualRegion(self, n_anchors=5):
        """
        Fit spline continuum from regions selected by users
        Up to 99 regions
        #:param n_regions: int, max number of data regions, user can break in the middle
        :param n_anchors: int, number of anchor points
        :return: continuum, coordinates of anchor points
        """

        # Select continuum regions to fit anc create a "marker" array
        # boundaries have to be from spectrum
        boundary_points = self.SelectPoints(
            n=99 * 2,
            nearest=True,
            y_message="Please Select Continuum Regions")
        boundary_x = boundary_points.T[0]
        data2fit = np.zeros_like(self.wave)
        idx = 0
        while idx < len(boundary_x) - 1:
            data2fit[(self.wave >= boundary_x[idx])
                     & (self.wave <= boundary_x[idx + 1])] = 1
            idx = idx + 2

        # tmp check if boundaries work
        # plt.scatter(self.wave, self.flux, s=10, color="0.5")
        # plt.scatter(boundary_points.T[0], boundary_points.T[1], marker="X", color="orange", s=100)
        # plt.scatter(self.wave[data2fit == 1], self.flux[data2fit == 1], s=10, color="r")
        # plt.show()

        # Fit spline continuum model
        wave2fit, flux2fit = self.wave[data2fit == 1], self.flux[data2fit == 1]
        continuum_model = ContinuumModel(n_anchors=n_anchors, verbose=0)
        pars_guess = continuum_model.guess(self.flux, x=self.wave)

        result = continuum_model.fit(data=flux2fit,
                                     params=pars_guess,
                                     x=wave2fit,
                                     weights=np.ones_like(wave2fit))

        # generate continuum and scipy.CubicSpline using the fitted parameters
        params2report = result.params
        x_points, y_points = [], []
        for i in range(n_anchors):
            x_points.append(params2report["x_%i" % (i)].value)
            y_points.append(params2report["y_%i" % (i)].value)

        spline_continuum = CubicSpline(np.asarray(x_points),
                                       np.asarray(y_points))
        anchor_points = np.asarray([x_points, y_points]).T

        return spline_continuum, anchor_points
Esempio n. 3
0
    def spline(self, *args, **kwargs):
        print("method: ", self.method)

        n_anchors = kwargs['n_anchors']

        self.model = ContinuumModel(n_anchors=n_anchors)
        cont_pars = self.model.guess(self.Spectrum.flux, x=self.Spectrum.wave)

        self.result = self.model.fit(data=self.Spectrum.flux,
                                     params=cont_pars,
                                     x=self.Spectrum.wave)

        print(self.result.params)

        self.result.plot_fit()
        plt.show()
Esempio n. 4
0
    def __init__(self, Spectrum, init_cont=True, n_anchors=4):

        self.__dict__.update(Spectrum.__dict__)

        self.wave = Spectrum.wave
        self.flux = Spectrum.flux

        if init_cont:
            cont_model = ContinuumModel(n_anchors=n_anchors)
            cont_pars = cont_model.guess(self.flux, x=self.wave)

        self.model = cont_model
        self.model_pars = cont_pars

        self.num_sources = 0
        self.source_names = []
Esempio n. 5
0
class Continuum():
    '''A class that has multiple methods for fitting different types of continua.

    Args:
        Spectrum (EdiblesSpectrum): The input EiblesSpectrum data
        method (str): The method of continuum fitting. spline (default), alphashape, polynomial


    '''
    def __init__(self, Spectrum, method='spline', *args, **kwargs):

        self.method = method
        self.Spectrum = Spectrum

        if method == 'spline':
            self.spline(*args, **kwargs)
        elif method == 'alphashape':
            self.alphashape(*args, **kwargs)
        elif method == 'polynomial':
            self.polynomial(*args, **kwargs)

    def spline(self, *args, **kwargs):
        print("method: ", self.method)

        n_anchors = kwargs['n_anchors']

        self.model = ContinuumModel(n_anchors=n_anchors)
        cont_pars = self.model.guess(self.Spectrum.flux, x=self.Spectrum.wave)

        self.result = self.model.fit(data=self.Spectrum.flux,
                                     params=cont_pars,
                                     x=self.Spectrum.wave)

        print(self.result.params)

        self.result.plot_fit()
        plt.show()

    def alphashape(self):
        print("method: ", self.method)

    def polynomial(self):
        print("method: ", self.method)
Esempio n. 6
0
def testModels(filename="tests/HD170740_w860_redl_20140915_O12.fits"):

    method = 'least_squares'

    sp = EdiblesSpectrum(filename, noDATADIR=True)
    sp.getSpectrum(xmin=7661, xmax=7670)

    n_anchors = 4

    cont_model = ContinuumModel(n_anchors=n_anchors)
    assert len(cont_model.param_names) == n_anchors * 2
    assert cont_model.n_anchors == n_anchors

    with pytest.raises(TypeError):
        assert ContinuumModel()
    with pytest.raises(TypeError):
        assert ContinuumModel(n_anchors=11)

    cont_pars = cont_model.guess(sp.flux, x=sp.wave)
    assert len(cont_pars) == len(cont_model.param_names)

    for name in cont_model.param_names:
        assert cont_pars[name].value is not None

    voigt = VoigtModel(prefix='voigt_')
    assert voigt.prefix == 'voigt_'
    assert len(voigt.param_names) == 4

    voigt_pars = voigt.guess(sp.flux, x=sp.wave)
    assert len(voigt_pars) == len(voigt.param_names)

    result = voigt.fit(data=sp.flux,
                       params=voigt_pars,
                       x=sp.wave,
                       method=method)
    assert len(result.params) == n_anchors

    out = voigt.eval(data=sp.flux, params=result.params, x=sp.wave)
    assert len(out) == len(sp.flux)
Esempio n. 7
0
    def spline(self, *args, **kwargs):
        """A spline function through a set number of anchor points

        Args:
            n_anchors (int): The number of anchor points in the spline

        """

        if self.verbose > 0:
            print("method: ", self.method)
            print()

        n_anchors = kwargs["n_anchors"]

        self.model = ContinuumModel(n_anchors=n_anchors)
        cont_pars = self.model.guess(self.Spectrum.flux, x=self.Spectrum.wave)

        self.result = self.model.fit(data=self.Spectrum.flux,
                                     params=cont_pars,
                                     x=self.Spectrum.wave)

        if self.plot:
            self.result.plot_fit()
            plt.show()
Esempio n. 8
0
def fit_NaI_Lines(target, date):
    """A function to fit Na I 2S-2P doublet lines - still very basic


    NaI1 = 3302.368 -> from edibles_linelist_atoms
    NaI2 = 3302.978 -> from edibles_linelist_atoms
    NaI_blue_diff = 0.61 -> lab data from https://www.pa.uky.edu/~peter/newpage/

    NaI3 = 5889.951 -> from edibles_linelist_atoms
    NaI4 = 5895.924 -> from edibles_linelist_atoms
    NaI_red_diff = 5.975 -> lab data from https://www.pa.uky.edu/~peter/newpage/

    blue_red_diff = 2587.583 -> NaI3 - NaI1

    """

    wavelength = 3300

    pythia = EdiblesOracle()
    bluelist = pythia.GetObsListByWavelength(wavelength, OrdersOnly=True)

    files = []
    for filename in bluelist:
        if target in filename:
            if date in filename:
                files.append(filename)

    print(files)

    sp = EdiblesSpectrum(files[0])
    print(sp.target)
    sp.getSpectrum(xmin=3300, xmax=3305)

    sigma = np.std(sp.flux)
    prominence = sigma
    peaks, _ = find_peaks(-sp.flux, prominence=prominence)
    peak_wavelengths = [sp.wave[i] for i in peaks]

    # #########################################################################

    cont = ContinuumModel(n_anchors=4)
    cont_pars = cont.guess(sp.flux, x=sp.wave)

    # #########################################################################

    voigt1 = VoigtModel(prefix='v1_')
    # voigt1_pars = voigt1.make_params(lam_0=3302, b=1, d=0.001, tau_0=0.01)
    voigt1_pars = voigt1.guess(sp.flux, x=sp.wave)

    # #########################################################################

    voigt2 = VoigtModel(prefix='v2_')
    voigt2_pars = voigt2.make_params(lam_0=peak_wavelengths[1],
                                     b=1,
                                     d=0.001,
                                     tau_0=0.01)

    voigt2_pars['v2_lam_0'].set(expr='v1_lam_0 + 0.61')
    voigt2_pars['v2_b'].set(expr='v1_b')

    # #########################################################################

    model = cont * voigt1 * voigt2
    pars = cont_pars + voigt1_pars + voigt2_pars

    result = model.fit(data=sp.flux, params=pars, x=sp.wave)

    # #########################################################################

    result.params.pretty_print()
    print('Ratio: ', result.params['v1_tau_0'] / result.params['v2_tau_0'])
    print(result.fit_report())

    plt.subplot(121)
    result.plot_fit()
    plt.title('Na I 3303')

    print()
    print()

    # #########################################################################
    # #########################################################################

    wavelength = 5890

    pythia = EdiblesOracle()
    redlist = pythia.GetObsListByWavelength(wavelength, OrdersOnly=True)

    files = []
    for filename in redlist:
        if target in filename:
            if date in filename:
                files.append(filename)

    print(files)

    sp = EdiblesSpectrum(files[1])
    print(sp.target)
    sp.getSpectrum(xmin=5885, xmax=5900)

    # #########################################################################

    cont = ContinuumModel(n_anchors=4)
    cont_pars = cont.guess(sp.flux, x=sp.wave)

    # #########################################################################

    prominence = (np.max(sp.flux) - np.min(sp.flux)) * 0.5
    peaks, _ = find_peaks(-sp.flux, prominence=prominence)
    peak_wavelengths = [sp.wave[i] for i in peaks]

    voigt3 = VoigtModel(prefix='v3_')
    voigt3_pars = voigt3.make_params(lam_0=peak_wavelengths[0],
                                     b=1,
                                     d=0.001,
                                     tau_0=0.4)
    # voigt3_pars = voigt3.guess(sp.flux, x=sp.wave)

    # #########################################################################

    voigt4 = VoigtModel(prefix='v4_')
    voigt4_pars = voigt4.make_params(lam_0=5896, b=1, d=0.001, tau_0=0.1)

    voigt4_pars['v4_lam_0'].set(expr='v3_lam_0 + 5.975')
    voigt4_pars['v4_b'].set(expr='v3_b')

    # #########################################################################

    model = cont * voigt3 * voigt4
    pars = cont_pars + voigt3_pars + voigt4_pars

    result = model.fit(data=sp.flux, params=pars, x=sp.wave)

    # #########################################################################

    result.params.pretty_print()
    print('Ratio: ', result.params['v3_tau_0'] / result.params['v4_tau_0'])
    print(result.fit_report())

    plt.subplot(122)
    result.plot_fit()
    plt.title('Na I 5890')
    plt.show()
Esempio n. 9
0
class Continuum:
    """A class that has multiple methods for fitting different types of continua.

    Args:
        Spectrum (EdiblesSpectrum): The input EiblesSpectrum data
        plot (bool): If true, plots the continuum fit
        verbose (int): If > 0, display more status messages

with open('eggs.csv', newline='') as csvfile:
    
    
        print(', '.join(row))

    """
    def __init__(self,
                 Spectrum,
                 method="spline",
                 plot=False,
                 verbose=0,
                 *args,
                 **kwargs):

        # check existing the available continuum csv files
        if Spectrum.continuum_filename:
            verbos_count = 0
            with open(Spectrum.continuum_filename) as csvfile:
                spamreader = csv.reader(csvfile, delimiter=' ', quotechar='|')
                for row in spamreader:
                    if len(row) > 0:
                        if row[0] == '######':
                            verbos_count += 1
            verbos = verbos_count

        self.method = method
        self.Spectrum = Spectrum
        self.plot = plot
        self.verbose = verbose

        if method == "spline":
            self.spline(*args, **kwargs)
        elif method == "alphashape":
            self.alphashape(*args, **kwargs)
        elif method == "polynomial":
            self.polynomial(*args, **kwargs)

    def spline(self, *args, **kwargs):
        """A spline function through a set number of anchor points

        Args:
            n_anchors (int): The number of anchor points in the spline

        """

        if self.verbose > 0:
            print("method: ", self.method)
            print()

        n_anchors = kwargs["n_anchors"]

        self.model = ContinuumModel(n_anchors=n_anchors)
        cont_pars = self.model.guess(self.Spectrum.flux, x=self.Spectrum.wave)

        self.result = self.model.fit(data=self.Spectrum.flux,
                                     params=cont_pars,
                                     x=self.Spectrum.wave)

        if self.plot:
            self.result.plot_fit()
            plt.show()

    def alphashape(self):
        if self.verbose > 0:
            print("method: ", self.method)
            print()

        print("This method is not available yet.")

    def polynomial(self):
        if self.verbose > 0:
            print("method: ", self.method)
            print()
        print("This method is not available yet.")

    def add_to_csv(self, user, comments=False):

        # Tests not in testing folder beceause we dont want to write the testing data
        assert isinstance(cont.model, ContinuumModel)
        assert isinstance(user, str)
        assert len(user) > 0, "A name must be entered"
        assert isinstance(comments, str)
        assert isinstance(cont.model.n_anchors, int)
        assert isinstance(datetime.now(), datetime)

        csv_file = self.Spectrum.filename.replace(".fits", ".csv").replace(
            "/DR4/data/", "/DR4/continuum/")

        line1 = "method=" + self.method + ", " + "n_anchors=" + str(
            self.model.n_anchors)
        line2 = ("datetime=" + str(datetime.now()) + ", " + "user="******", " + "Comments: " + comments)

        x_points = [
            self.result.params[xname].value for xname in self.model.xnames
        ]
        y_points = [
            self.result.params[yname].value for yname in self.model.ynames
        ]

        header = line1 + "\n" + line2
        with open(csv_file, mode="a") as f:
            np.savetxt(f, (x_points, y_points),
                       delimiter=",",
                       header=header,
                       comments="# ")
            f.write("\n")

        if self.verbose > 0:
            print("Appended to file!")
        if self.verbose > 1:
            print("File appended to: " + csv_file)
Esempio n. 10
0
import numpy as np
import matplotlib.pyplot as plt

from edibles.models import ContinuumModel

# #################################################################################
# Example 1

x = np.linspace(0, 3)
y = x**3 - 3 * x**2 + 1

cont_model = ContinuumModel(n_anchors=4)
cont_pars = cont_model.guess(y, x=x)

# ##############################
# Show initial model

out = cont_model.eval(data=y, params=cont_pars, x=x)

y_param_names = []
for i in range(cont_model.n_anchors):
    y_param_names.append('y_' + str(i))

x_param_names = []
for i in range(cont_model.n_anchors):
    x_param_names.append('x_' + str(i))

init_y = []
for par_name in y_param_names:
    init_y.append(cont_pars[par_name].value)
Esempio n. 11
0
import matplotlib.pyplot as plt

from edibles.utils.edibles_spectrum import EdiblesSpectrum
from edibles.models import ContinuumModel, VoigtModel

filename = "/HD170740/RED_860/HD170740_w860_redl_20140915_O12.fits"

method = 'least_squares'

sp = EdiblesSpectrum(filename)
print(sp.target)
sp.getSpectrum(xmin=7661, xmax=7670)

# #################################################################################

cont_model = ContinuumModel(n_anchors=4)
cont_pars = cont_model.guess(sp.flux, x=sp.wave)
model = cont_model
pars = cont_pars

result = model.fit(data=sp.flux, params=pars, x=sp.wave, method=method)
out = cont_model.eval(data=sp.flux, params=result.params, x=sp.wave)
resid = sp.flux - out

# result.plot_fit()
# plt.show()

# #################################################################################

voigt1 = VoigtModel(prefix='voigt1_')
voigt1_pars = voigt1.guess(resid, x=sp.wave)
Esempio n. 12
0
    def prebuilt_model(self, chosen_save_num=None, plot=False, verbose=0):
        """A function that generates continua based on data saved in csv files.


        Args:
            chosen_save_num (int): The 'save number' of the continuum data, default=None.
                If None, the function will create all saved models and (possibly) plot them.
            plot (bool): If True, plot the model(s) once it is created
            verbose (int): If > 0, print more information about the data

        """

        # assert self.num_saved_continua is not 0, otherwise there is no known continuum point
        assert self.num_saved_continua > 0, "There is no saved continuum."

        # read and parse file contents
        saves_counter = 0
        saves_dict = {}
        with open(self.Spectrum.continuum_filename, mode="r") as f:
            for line in f:
                line = line.split("\n")[0]

                # initialize new save group
                if len(line) > 0:
                    if line == "######":
                        name = "save" + str(saves_counter)
                        saves_counter += 1
                        saves_dict[name] = {"x": None, "y": None}

                    # update dict
                    elif line[0:2] == "# ":
                        key, val = line.split("# ")[1].split("=")

                        if key == "n_anchors":
                            val = int(val)
                        if key == "datetime":
                            val = datetime.strptime(val, "%Y-%m-%d %H:%M:%S.%f")

                        saves_dict[name][key] = val

                    else:
                        if saves_dict[name]["x"] is None:
                            saves_dict[name]["x"] = [
                                float(item) for item in line.split(",")
                            ]
                        else:
                            saves_dict[name]["y"] = [
                                float(item) for item in line.split(",")
                            ]

        if chosen_save_num is not None:
            assert chosen_save_num < self.num_saved_continua, (
                "There are only " + str(self.num_saved_continua) + " saved continua."
            )
            chosen_save = saves_dict["save" + str(chosen_save_num)]

            if verbose > 0:
                print("Number of saved continuum datasets: ", saves_counter)
                print("Save chosen: save" + str(chosen_save_num))
                pprint(chosen_save)

            cont_model = ContinuumModel(n_anchors=chosen_save['n_anchors'])
            params = cont_model.make_params()
            for i in range(cont_model.n_anchors):
                params['%sx_%i' % (cont_model.prefix, i)].set(value=chosen_save["x"][i], vary=False)
                params['%sy_%i' % (cont_model.prefix, i)].set(value=chosen_save["y"][i], vary=False)

            params = update_param_vals(params, cont_model.prefix)

            out = cont_model.eval(params=params, x=self.Spectrum.wave)

            if plot:
                plt.plot(self.Spectrum.wave, self.Spectrum.flux)
                plt.plot(self.Spectrum.wave, out)
                plt.scatter(chosen_save["x"], chosen_save["y"], marker="x", s=80, color="k")
                plt.show()

            return out
        else:
            for j in range(saves_counter):
                chosen_save = saves_dict["save" + str(j)]
                try:
                    method = str(chosen_save["method"])
                except:
                    method = "unknown"

                try:
                    n_anchors = str(chosen_save["n_anchors"])
                except:
                    n_anchors = "unknown"

                try:
                    date_time = str(chosen_save["datetime"])
                except:
                    date_time = "unknown"

                try:
                    user = str(chosen_save["user"])
                except:
                    user = "******"

                try:
                    comments = str(chosen_save["comments"])
                except:
                    comments = "None"

                print("Continuum group {a}/{b}".format(a = j, b=saves_counter-1))
                print("Method: " + method + ", n_anchors: " + n_anchors + ";")
                print("Added by: " + user + ", at time:" + date_time + ";")
                print("Comments: " + comments)

                if plot:
                    cont_model = ContinuumModel(n_anchors=chosen_save['n_anchors'])
                    params = cont_model.make_params()
                    for i in range(cont_model.n_anchors):
                        params['%sx_%i' % (cont_model.prefix, i)].set(value=chosen_save["x"][i], vary=False)
                        params['%sy_%i' % (cont_model.prefix, i)].set(value=chosen_save["y"][i], vary=False)

                    params = update_param_vals(params, cont_model.prefix)

                    out = cont_model.eval(params=params, x=self.Spectrum.wave)

                    plt.plot(self.Spectrum.wave, self.Spectrum.flux)
                    plt.plot(self.Spectrum.wave, out)
                    plt.scatter(chosen_save["x"], chosen_save["y"], marker="x", s=80, color="k")
                    plt.show()
                print("Please make your selection back in the script.")
Esempio n. 13
0
class Continuum:
    """A class that has multiple methods for fitting different types of continua.

    Args:
        Spectrum (EdiblesSpectrum): The input EiblesSpectrum data
        method (str): The method of fitting
        plot (bool): If true, plots the continuum fit
        verbose (int): If > 0, display more status messages

    """

    def __init__(self, Spectrum, method="None", plot=False, verbose=0, *args, **kwargs):

        # check existing the available continuum csv files
        try:
            if Spectrum.continuum_filename:
                self.num_saved_continua = 0
                with open(Spectrum.continuum_filename) as f:
                    for row in f:
                        if "######" in row:
                            self.num_saved_continua += 1
        except AttributeError:
            if verbose > 0:
                print("No previously saved data")

        self.method = method
        self.Spectrum = Spectrum
        self.plot = plot
        self.verbose = verbose

        if method == "spline":
            self.spline(*args, **kwargs)
        elif method == "alphashape":
            self.alphashape(*args, **kwargs)
        elif method == "polynomial":
            self.polynomial(*args, **kwargs)

    def spline(self, *args, **kwargs):
        """A spline function through a set number of anchor points

        Args:
            n_anchors (int): The number of anchor points in the spline

        """

        if self.verbose > 0:
            print("method: ", self.method)
            print()

        n_anchors = kwargs["n_anchors"]

        self.model = ContinuumModel(n_anchors=n_anchors)
        self.cont_pars = self.model.guess(self.Spectrum.flux, x=self.Spectrum.wave)

        self.result = self.model.fit(
            data=self.Spectrum.flux, params=self.cont_pars, x=self.Spectrum.wave
        )

        if self.plot:
            self.result.plot_fit()
            plt.show()

    def alphashape(self):
        """A function that uses alphashape to find a continuum.

        Note:
            Currently not implemented

        """

        if self.verbose > 0:
            print("method: ", self.method)
            print()

        print("This method is not available yet.")

    def polynomial(self):
        """A function that uses a polynomial to find a continuum.

        Note:
            Currently not implemented

        """

        if self.verbose > 0:
            print("method: ", self.method)
            print()
        print("This method is not available yet.")

    def prebuilt_model(self, chosen_save_num=None, plot=False, verbose=0):
        """A function that generates continua based on data saved in csv files.


        Args:
            chosen_save_num (int): The 'save number' of the continuum data, default=None.
                If None, the function will create all saved models and (possibly) plot them.
            plot (bool): If True, plot the model(s) once it is created
            verbose (int): If > 0, print more information about the data

        """

        # assert self.num_saved_continua is not 0, otherwise there is no known continuum point
        assert self.num_saved_continua > 0, "There is no saved continuum."

        # read and parse file contents
        saves_counter = 0
        saves_dict = {}
        with open(self.Spectrum.continuum_filename, mode="r") as f:
            for line in f:
                line = line.split("\n")[0]

                # initialize new save group
                if len(line) > 0:
                    if line == "######":
                        name = "save" + str(saves_counter)
                        saves_counter += 1
                        saves_dict[name] = {"x": None, "y": None}

                    # update dict
                    elif line[0:2] == "# ":
                        key, val = line.split("# ")[1].split("=")

                        if key == "n_anchors":
                            val = int(val)
                        if key == "datetime":
                            val = datetime.strptime(val, "%Y-%m-%d %H:%M:%S.%f")

                        saves_dict[name][key] = val

                    else:
                        if saves_dict[name]["x"] is None:
                            saves_dict[name]["x"] = [
                                float(item) for item in line.split(",")
                            ]
                        else:
                            saves_dict[name]["y"] = [
                                float(item) for item in line.split(",")
                            ]

        if chosen_save_num is not None:
            assert chosen_save_num < self.num_saved_continua, (
                "There are only " + str(self.num_saved_continua) + " saved continua."
            )
            chosen_save = saves_dict["save" + str(chosen_save_num)]

            if verbose > 0:
                print("Number of saved continuum datasets: ", saves_counter)
                print("Save chosen: save" + str(chosen_save_num))
                pprint(chosen_save)

            cont_model = ContinuumModel(n_anchors=chosen_save['n_anchors'])
            params = cont_model.make_params()
            for i in range(cont_model.n_anchors):
                params['%sx_%i' % (cont_model.prefix, i)].set(value=chosen_save["x"][i], vary=False)
                params['%sy_%i' % (cont_model.prefix, i)].set(value=chosen_save["y"][i], vary=False)

            params = update_param_vals(params, cont_model.prefix)

            out = cont_model.eval(params=params, x=self.Spectrum.wave)

            if plot:
                plt.plot(self.Spectrum.wave, self.Spectrum.flux)
                plt.plot(self.Spectrum.wave, out)
                plt.scatter(chosen_save["x"], chosen_save["y"], marker="x", s=80, color="k")
                plt.show()

            return out
        else:
            for j in range(saves_counter):
                chosen_save = saves_dict["save" + str(j)]
                try:
                    method = str(chosen_save["method"])
                except:
                    method = "unknown"

                try:
                    n_anchors = str(chosen_save["n_anchors"])
                except:
                    n_anchors = "unknown"

                try:
                    date_time = str(chosen_save["datetime"])
                except:
                    date_time = "unknown"

                try:
                    user = str(chosen_save["user"])
                except:
                    user = "******"

                try:
                    comments = str(chosen_save["comments"])
                except:
                    comments = "None"

                print("Continuum group {a}/{b}".format(a = j, b=saves_counter-1))
                print("Method: " + method + ", n_anchors: " + n_anchors + ";")
                print("Added by: " + user + ", at time:" + date_time + ";")
                print("Comments: " + comments)

                if plot:
                    cont_model = ContinuumModel(n_anchors=chosen_save['n_anchors'])
                    params = cont_model.make_params()
                    for i in range(cont_model.n_anchors):
                        params['%sx_%i' % (cont_model.prefix, i)].set(value=chosen_save["x"][i], vary=False)
                        params['%sy_%i' % (cont_model.prefix, i)].set(value=chosen_save["y"][i], vary=False)

                    params = update_param_vals(params, cont_model.prefix)

                    out = cont_model.eval(params=params, x=self.Spectrum.wave)

                    plt.plot(self.Spectrum.wave, self.Spectrum.flux)
                    plt.plot(self.Spectrum.wave, out)
                    plt.scatter(chosen_save["x"], chosen_save["y"], marker="x", s=80, color="k")
                    plt.show()
                print("Please make your selection back in the script.")

    def add_to_csv(self, user, comments):
        """A function that saves the continuum model parameters to a csv file.

        Each save appears as follows:

        | ######
        | # method=spline
        | # n_anchors=4
        | # datetime=2020-10-06 10:56:02.192865
        | # user=First Last
        | # comments=This is a comment.
        | x1, x2, x3, x4
        | y1, y2, y3, y4


        Args:
            user (str): The name of the person adding the data
            comments (str): Any comments the user wishes to make about the data to be saved

        Note:
            The data is saved to the ediblesdr4 github repository,
            with the same filepath as the original FITS file.



        """

        # Tests not in testing folder beceause we dont want to write the testing data
        assert isinstance(self.model, ContinuumModel)
        assert isinstance(user, str)
        assert len(user) > 0, "A name must be entered"
        assert isinstance(comments, str)
        assert isinstance(self.model.n_anchors, int)
        assert isinstance(datetime.now(), datetime)

        csv_file = self.Spectrum.filename.replace(".fits", ".csv").replace(
            "/DR4/data/", "/DR4/continuum/"
        )

        x_points = [self.result.params[xname].value for xname in self.model.xnames]
        y_points = [self.result.params[yname].value for yname in self.model.ynames]

        with open(csv_file, mode="a") as f:
            f.write("######\n")
            f.write("# method=" + str(self.method) + "\n")
            f.write("# n_anchors=" + str(self.model.n_anchors) + "\n")
            f.write("# datetime=" + str(datetime.now()) + "\n")
            f.write("# user="******"\n")
            f.write("# comments=" + str(comments) + "\n")
            np.savetxt(f, (x_points, y_points), delimiter=",")
            f.write("\n")

        if self.verbose > 0:
            print("Appended to file!")
        if self.verbose > 1:
            print("File appended to: " + csv_file)