def template_fit(wave, flux, error, img_directory, sid):
    # Fit continuum
    fig = plt.figure()
    plt.plot(wave, flux)
    [cont_wave, cont_flux, cont_error] = extract_fit_part(wave, flux, error, 4040, 4060)
    [temp_wave, temp_flux, temp_error] = extract_fit_part(wave, flux, error, 5080, 5100)
    cont_wave = np.append(cont_wave, temp_wave)
    cont_flux = np.append(cont_flux, temp_flux)
    cont_error = np.append(cont_error, temp_error)
    cont_fitter = fitting.LevMarLSQFitter()
    cont = models.PowerLaw1D(cont_flux[0], cont_wave[0], - np.log(cont_flux[-1]/cont_flux[0]) / np.log(cont_wave[-1]/cont_wave[0]), fixed = {"x_0": True})
    with warnings.catch_warnings():
        warnings.filterwarnings('error')
        try:
            cont_fit = cont_fitter(cont, cont_wave, cont_flux, weights = cont_error, maxiter = 10000)
        except Exception:
            save_fig(fig, img_directory, str(sid) + "-cont-failed")
            plt.close()
            raise SpectraException("Continuum fit failed")
    plt.plot(wave, cont_fit(wave))
    save_fig(fig, img_directory, str(sid) + "-cont-success")
    plt.close()
    # Fit emission lines
    flux = flux - cont_fit(wave)
    fig1 = plt.figure()
    plt.plot(wave, flux)
    hbeta_complex_fit_func = \
            fe_temp_observed.FeII_template_obs(6.2, 2000.0, 2.6, 6.2, 2000.0, 2.6) + \
            models.Gaussian1D(3.6, 4853.30, 40.0) + \
            models.Gaussian1D(2.0, 4346.40, 2.0) + \
            models.Gaussian1D(2.0, 4101.73, 2.0) + \
            models.Gaussian1D(5.0, 4960.0, 6.0) + \
            models.Gaussian1D(20.0, 5008.0, 6.0)
    fitter = fitting.LevMarLSQFitter()
    with warnings.catch_warnings():
        warnings.filterwarnings('error')
        try:
            start = time.time()
            fit = fitter(hbeta_complex_fit_func, wave, flux, weights = error, maxiter = 3000)
            print("Time taken: ")
            print(time.time() - start)
        except Exception:
            save_fig(fig1, img_directory, str(sid) + "-failed")
            plt.close()
            raise SpectraException("Fit failed")
    expected = np.array(fit(wave))
    plt.plot(wave, expected)
    save_fig(fig1, img_directory, str(sid) + "-succeed")
    plt.close()
    rcs = 0
    for i in range(len(flux)):
        rcs = rcs + (flux[i] - expected[i]) ** 2.0
    rcs = rcs / np.abs(len(flux)-17)
    if rcs > 10.0:
        raise SpectraException("Reduced chi-square too large: " + str(rcs))
    return fit.parameters, cont_fit.parameters, rcs
def hbeta_complex_fit_2(wave, flux, error):
    os.chdir("../../")
    fig = plt.figure()
    plt.plot(wave, flux)
    [cont_wave, cont_flux, cont_error] = extract_fit_part(wave, flux, error, 4040, 4060)
    [temp_wave, temp_flux, temp_error] = extract_fit_part(wave, flux, error, 5080, 5100)
    cont_wave = np.append(cont_wave, temp_wave)
    cont_flux = np.append(cont_flux, temp_flux)
    cont_error = np.append(cont_error, temp_error)
    cont_fitter = fitting.LevMarLSQFitter()
    cont = models.PowerLaw1D(cont_flux[0], cont_wave[0], - np.log(cont_flux[-1]/cont_flux[0]) / np.log(cont_wave[-1]/cont_wave[0]), fixed = {"x_0": True})
    cont_fit = cont_fitter(cont, cont_wave, cont_flux, weights = cont_error, maxiter = 10000)
    plt.plot(wave, cont_fit(wave))
    plt.show()
    flux = flux - cont_fit(wave)
    plt.plot(wave, flux)
    hbeta_complex_fit_func = \
            fe_temp_constructor.FeII_template(9900, 0, 1500.0, 4.0, 3.0, 3.0, 3.0, 1.0)
    fitter = fitting.LevMarLSQFitter()
    with warnings.catch_warnings():
        warnings.filterwarnings('error')
        try:
            start = time.time()
            fit = fitter(hbeta_complex_fit_func, wave, flux, weights = error, maxiter = 3000)
            print(time.time() - start)
        except SpectraException:
            print(fit)
            print(fit.parameters)
            expected = np.array(fit(wave))
            plt.plot(wave, expected)
            plt.show()
            fig.savefig("Hbeta-g-failed.jpg")
            plt.close()
            raise SpectraException("Line Hbeta fit failed")
    print(fit)
    print(fit.parameters)
    expected = np.array(fit(wave))
    plt.plot(wave, expected)
    plt.show()
    fig.savefig("Hbeta-g.jpg")
    plt.close()
    rcs = 0
    for i in range(len(flux)):
        rcs = rcs + (flux[i] - expected[i]) ** 2.0
    rcs = rcs / np.abs(len(flux)-17)
    if rcs > 10.0:
        plt.close()
        raise SpectraException("Line Hbeta reduced chi-square too large" + str(rcs))
    return fit.parameters, rcs
def mc_ee_single(rmid, mjd):
    print("    Begin for " + str(mjd))
    try:
        [wave, flux, error] = read_raw_data(rmid, mjd)
        # error = pickle.load(open(Location.project_loca + "data/raw/" +
        #                          str(rmid) + "/" + str(mjd) + "/" +
        #                          "error_scaled.pkl", "rb"))
        [wave, flux, error] = mask_points(wave, flux, error)
        [wave, flux, error] = extract_fit_part(wave, flux, error, 4000.0,
                                               5500.0)
    except Exception:
        print("        Unable to locate data file.")
        return [[], []]
    flux_with_noise = noise_gene(flux, error)
    error_with_noise = np.tile(error, [100, 1])
    num_list = list(range(100))
    m = Manager()
    p = Pool(processes=100)
    fit_res = m.list()
    func = partial(get_flux, wave, rmid, mjd, fit_res)
    args = list()
    for i in range(len(flux_with_noise)):
        args.append([flux_with_noise[i], error_with_noise[i], num_list[i]])
    p.map(func, args)
    p.close()
    res = np.transpose(np.array(list(fit_res)))
    std_res = list()
    mean_res = list()
    for each in res:
        std_res.append(np.std(each))
        mean_res.append(np.mean(each))
    return [std_res, mean_res]
def main_process(sid, line):
    os.chdir("Fe2")
    try:
        os.mkdir(str(sid))
    except OSError:
        pass
    os.chdir("../Fe2-fig")
    try:
        os.mkdir(str(sid))
    except OSError:
        pass
    os.chdir("../")
    [wave, flux, fluxerr] = read_raw_data(sid)
    [wave, flux, fluxerr] = mask_points(wave, flux, fluxerr)
    # Extract the part of data for fitting
    [wave, flux, fluxerr] = extract_fit_part(wave, flux, fluxerr, line[0], line[2])
    os.chdir("Fe2-fig/" + str(sid))
    #try:
    [hbeta, bef, aft, o3sn, fesn] = compare_fe2(wave, flux, fluxerr)
    #except Exception as reason:
    #    print(str(reason))
    #    exception_logging(sid, "Fe2", reason)
    #    os.chdir("../../")
    #    return
    os.chdir("../../")
    output_fit(hbeta, sid, "Hbeta")
    output_fit(bef, sid, "bef")
    output_fit(aft, sid, "aft")
    os.chdir("Fe2/")
    sn_file = open(str(sid) + ".txt", "a")
    sn_file.write("%9.4f    %9.4f\n" % (o3sn, fesn))
    sn_file.close()
    os.chdir("../")
    print(o3sn, fesn)
    print("Process finished for " + str(sid))
def compare_fe2(wave, flux, error):
    # First fit Hbeta and OIII
    se = False
    [wave_fit, flux_fit, error_fit] = extract_fit_part(wave, flux, error, 4000.0, 5500.0)
    #try:
    #    [hbeta_g_res, g_rcs] = hbeta_complex_fit_2(wave_fit, flux_fit, error_fit)
    #except SpectraException:
    #    se = True
    #    g_rcs = 65535
    #try:
    [hbeta_l_res, l_rcs] = hbeta_complex_fit_2(wave_fit, flux_fit, error_fit)
    #except SpectraException:
    #    if se==True:
    #        raise SpectraException("Fit for Hbeta complex failed")
    #    else:
    #        l_rcs = 65535
    #        pass
    #if g_rcs>l_rcs:
    #    hbeta_res = hbeta_l_res
    #    o3range = [(hbeta_l_res[13] - 2.0 * hbeta_l_res[14], hbeta_l_res[13] + 2.0 * hbeta_l_res[14])]
    #    cont = lambda x: hbeta_l_res[18] * x + hbeta_l_res[19]
    #    hbetarange = [(hbeta_l_res[1] - 2.0 * hbeta_l_res[2], hbeta_l_res[1] + 2.0 * hbeta_l_res[2])]
    #else:
    #    hbeta_res = hbeta_g_res
    #    o3range = [(hbeta_g_res[19] - 2.0 * hbeta_g_res[20], hbeta_g_res[19] + 2.0 * hbeta_g_res[20])]
    #    cont = lambda x: hbeta_g_res[24] * x +hbeta_g_res[25]
    #    hbetarange = union([(hbeta_g_res[1] - 2.0 * hbeta_g_res[2], hbeta_g_res[1] + 2.0 * hbeta_g_res[2]), 
    #        (hbeta_g_res[4] - 2.0 * hbeta_g_res[5], hbeta_g_res[4] + 2.0 * hbeta_g_res[5])])
    #o3flux = flux_sum(o3range, wave, flux) - flux_sum(o3range, wave, list(map(cont, wave)))
    #hbetaflux = flux_sum(hbetarange, wave, flux) - flux_sum(hbetarange, wave, list(map(cont, wave)))
    #o3hb = o3flux / hbetaflux
    return [hbeta_l_res, 0, 0, 0, 0]
def rough_finder(sid, hbeta, o3, fe2):
    [wave, flux, ivar] = read_raw_data(sid)
    [wave, flux, ivar] = extract_fit_part(wave, flux, ivar, 4000, 5500)
    [wave, flux, ivar] = mask_points(wave, flux, ivar)
    try:
        [wave, flux, ivar, fig] = cont_handler(wave, flux, ivar)
    except Exception:
        fig.savefig("rough_finder/" + str(sid))
        plt.close()
        return [-1, -1]
    fig.savefig("rough_finder/" + str(sid))
    plt.close() 
    try:
        i_hbeta = find_i(wave, flux, ivar, hbeta[0], hbeta[1])
        i_o3 = find_i(wave, flux, ivar, o3[0], o3[1])
    except ValueError:
        return [0, 0]
    i_fe2 = 0
    for each in fe2:
        try:
            i_fe2 = i_fe2 + find_i(wave, flux, ivar, each[0], each[1])
        except ValueError:
            continue
    o3vshbeta = i_o3 / i_hbeta
    fe2vshbeta = i_fe2 / i_hbeta
    return [o3vshbeta, fe2vshbeta]
def cont_handler(wave, flux, ivar):
    [cont_wave, cont_flux, cont_error] = extract_fit_part(wave, flux, ivar, 4040, 4060)
    [temp_wave, temp_flux, temp_error] = extract_fit_part(wave, flux, ivar, 5080, 5100)
    cont_wave = np.append(cont_wave, temp_wave)
    cont_flux = np.append(cont_flux, temp_flux)
    cont_error = np.append(cont_error, temp_error)
    cont_fitter = fitting.LevMarLSQFitter()
    with warnings.catch_warnings():
        warnings.filterwarnings('error')
        cont = models.PowerLaw1D(cont_flux[0], cont_wave[0], - np.log(cont_flux[-1] / cont_flux[0]) / np.log(cont_wave[-1] / cont_wave[0]), fixed = {"x_0": True})
    cont_fit = cont_fitter(cont, cont_wave, cont_flux, weights = cont_error, maxiter = 10000)
    fig = plt.figure()
    plt.plot(wave, flux)
    plt.plot(wave, cont_fit(wave))
    flux_n = flux - cont_fit(wave)
    return [wave, flux_n, ivar, fig]
def mc_ee_single(rmid, mjd):
    print("    Begin for " + str(mjd))
    try:
        [wave, flux, error] = read_raw_data(rmid, mjd)
        # error = pickle.load(open(Location.project_loca + "data/raw/" +
        #                          str(rmid) + "/" + str(mjd) + "/" +
        #                          "error_scaled.pkl", "rb"))
        [wave, flux, error] = mask_points(wave, flux, error)
        [wave, flux, error] = extract_fit_part(wave, flux, error, 4000.0,
                                               5500.0)
    except Exception:
        print("        Unable to locate data file.")
        return [[], []]
    flux_with_noise = noise_gene(flux, error)
    error_with_noise = np.tile(error, [100, 1])
    num_list = list(range(100))
    m = Manager()
    p = Pool(processes=100)
    fit_res = m.list()
    func = partial(get_flux, wave, rmid, mjd, fit_res)
    args = list()
    for i in range(len(flux_with_noise)):
        args.append([flux_with_noise[i], error_with_noise[i], num_list[i]])
    p.map(func, args)
    p.close()
    res = np.transpose(np.array(list(fit_res)))
    std_res = list()
    mean_res = list()
    for each in res:
        std_res.append(np.std(each))
        mean_res.append(np.mean(each))
    return [std_res, mean_res]
def main_process(sid):
    [wave, flux, error] = read_raw_data(str(sid))
    [wave, flux, error] = mask_points(wave, flux, error)
    fit_res = read_fit_res(sid)
    [wave, flux, error] = extract_fit_part(wave, flux, error, fit_res[7] - 2.0 * fit_res[8], fit_res[7] + 2.0 * fit_res[8])
    fwhm = calc_fwhm(wave, flux)
    std = fit_res[8]
    profile = fwhm / std
    print(sid + " " + str(profile))
    return profile
def main_process(sid):
    print("Beginning process for " + str(sid))
    # Read data and preprocessing
    [wave, flux, error] = read_raw_data(sid)
    [wave, flux, error] = mask_points(wave, flux,  error)
    [wave, flux, error] = extract_fit_part(wave, flux, error, 4000.0, 5500.0)
    # Begin fitting and handling exception
    try:
        img_directory = "Fe2"
        [fit_res, cont_res, rcs] = template_fit(wave, flux, error,  img_directory, sid)
    except SpectraException as reason:
        exception_logging(sid, reason)
        print("Failed\n\n")
        return
    output_fit(fit_res, sid, "Fe2")
    output_fit(cont_res, sid, "cont")
    print("Finished\n\n")
def fe_fitter_single(rmid, lock, rcs_dict, mjd):
    # Read data and preprocessing
    try:
        [wave, flux, error] = read_raw_data(rmid, mjd)
        [wave, flux, error] = mask_points(wave, flux, error)
        [wave, flux, error] = extract_fit_part(wave, flux, error, 4000.0,
                                               5500.0)
    except Exception as reason:
        lock.acquire()
        exception_logging(rmid, mjd, reason)
        print("Failed for " + str(mjd))
        lock.release()
        return
    os.chdir(Location.project_loca + "result/fit_with_temp/data")
    try:
        os.mkdir(str(rmid))
    except OSError:
        pass
    os.chdir(Location.project_loca + "result/fit_with_temp/fig")
    try:
        os.mkdir(str(rmid))
    except OSError:
        pass
    # Begin fitting and handling exception
    try:
        [fit_res, cont_res, rcs, numcont,
         numfit] = template_fit(wave, flux, error, True, [], rmid, mjd)
    except Exception as reason:
        lock.acquire()
        exception_logging(rmid, mjd, reason)
        print("Failed for " + str(mjd))
        lock.release()
        return
    output_fit(fit_res, rmid, mjd, "Fe2")
    output_fit(cont_res, rmid, mjd, "cont")
    lock.acquire()
    rcs_dict[mjd] = rcs
    print("Finished for " + str(mjd))
    lock.release()
def get_fwhm_hb(rmid, mjd):
    day_dir = Location.project_loca + "result/fit_with_temp/data/" + \
        str(rmid) + "/" + str(mjd) + "-"
    hb_file = open(day_dir + "Fe2.pkl", "rb")
    hb = pickle.load(hb_file)[10:12]
    hb_file.close()
    cont_file = open(day_dir + "cont.pkl", "rb")
    cont = pickle.load(cont_file)
    cont_file.close()
    cont_func = models.PowerLaw1D(cont[0], cont[1], cont[2])
    [wave, flux, error] = read_raw_data(rmid, mjd)
    [wave, flux,
     error] = extract_fit_part(wave, flux, error, hb[0] - 2.0 * hb[1],
                               hb[0] + 2.0 * hb[1])
    [wave, flux, error] = mask_points(wave, flux, error)
    flux = flux - cont_func(wave)
    up_wave = wave[0:flux.argmax()]
    up_flux = flux[0:flux.argmax()]
    down_flux = flux[flux.argmax():-1]
    down_wave = wave[flux.argmax():-1]
    wave_min = find_wave(up_wave, up_flux, 0.5 * np.amax(flux))
    wave_max = find_wave(down_wave, down_flux, 0.5 * np.amax(flux))
    return (wave_max - wave_min) / hb[1]
def fe_fitter_single(rmid, lock, rcs_dict, mjd):
    # Read data and preprocessing
    try:
        [wave, flux, error] = read_raw_data(rmid, mjd)
        [wave, flux, error] = mask_points(wave, flux,  error)
        [wave, flux, error] = extract_fit_part(wave, flux, error, 4000.0, 5500.0)
    except Exception as reason:
        lock.acquire()
        exception_logging(rmid, mjd, reason)
        print("Failed for " + str(mjd))
        lock.release()
        return
    os.chdir(Location.project_loca + "result/fit_with_temp/data")
    try:
        os.mkdir(str(rmid))
    except OSError:
        pass
    os.chdir(Location.project_loca + "result/fit_with_temp/fig")
    try:
        os.mkdir(str(rmid))
    except OSError:
        pass
    # Begin fitting and handling exception
    try:
        [fit_res, cont_res, rcs, numcont, numfit] = template_fit(wave, flux, error, True, [], rmid, mjd)
    except Exception as reason:
        lock.acquire()
        exception_logging(rmid, mjd, reason)
        print("Failed for " + str(mjd))
        lock.release()
        return
    output_fit(fit_res, rmid, mjd, "Fe2")
    output_fit(cont_res, rmid, mjd, "cont")
    lock.acquire()
    rcs_dict[mjd] = rcs
    print("Finished for " + str(mjd))
    lock.release()
def template_fit(wave, flux, error, image_control, init_value, rmid, mjd):
    img_directory = Location.project_loca + "result/fit_with_temp/fig/" + \
        str(rmid)
    # Fit continuum
    if image_control:  # Control image output
        fig = plt.figure()
        plt.plot(wave, flux)
    # Part of the spectra without any prominent emission lines
    no_line_part = [[4000.0, 4050.0], [4150.0, 4280.0], [4420, 4750], [5050, 5500]]
    cont_wave = np.array([])
    cont_flux = np.array([])
    cont_error = np.array([])
    for each_part in no_line_part:
        [pwave, pflux, perror] = extract_fit_part(wave, flux, error, each_part[0], each_part[1])
        cont_wave = np.append(cont_wave, pwave)
        cont_flux = np.append(cont_flux, pflux)
        cont_error = np.append(cont_error, perror)
    cont_fitter = fitting.LevMarLSQFitter()
    if init_value == []:
        cont = fe_temp_observed.FeII_template_obs(0.0, 2000.0, 2.6, 0.0, 2000.0, 2.6, bounds = {"i_r_l1": [0.0, 50.0], "i_r_n3": [0.0, 50.0]}) + \
            models.PowerLaw1D(flux[0], wave[0], - np.log(abs(flux[-1]/flux[0])+0.001) / np.log(abs(wave[-1]/wave[0]) + 0.001), fixed = {"x_0": True})
    else:
        fe2_param = init_value[1][0:6]
        cont = fe_temp_observed.FeII_template_obs(fe2_param[0], fe2_param[1],
                                                  fe2_param[2], fe2_param[3],
                                                  fe2_param[4], fe2_param[5],
                                                  bounds = {"i_r_l1": [0.0, 50.0], "i_r_n3": [0.0, 50.0]}) + \
            models.PowerLaw1D(init_value[0][0], init_value[0][1], init_value[0][2], fixed = {"x_0": True})
    with warnings.catch_warnings():
        warnings.filterwarnings('error')
        try:
            cont_fit = cont_fitter(cont, cont_wave, cont_flux, weights = cont_error ** (-2), maxiter = 10000)
        except Exception as reason:
            if image_control:  # Control image output
                save_fig(fig, img_directory, str(mjd) + "-cont-failed")
                plt.close()
            raise SpectraException("Continuum fit failed because of " +
                                   str(reason))
    if image_control:  # Control image output
        para = cont_fit.parameters[6:9]
        cont_cont = models.PowerLaw1D(para[0], para[1], para[2])
        cont_spec = cont_cont(wave)
        fit_spec = cont_fit(wave)
        plt.plot(wave, fit_spec)
        plt.plot(wave, cont_spec)
        plt.plot(wave, fit_spec - cont_spec)
        save_fig(fig, img_directory, str(mjd) + "-cont-success")
        plt.close()
    # Fit emission lines
    flux = flux - cont_fit(wave)
    if image_control:  # Control image output
        fig1 = plt.figure()
        plt.plot(wave, flux)
    if init_value == []:
        hbeta_complex_fit_func = \
            models.Gaussian1D(3.6, 4853.30, 7.0, bounds = {"amplitude": [0.0, 50.0], "mean": [4830, 4880], "stddev": [0.0001, 10.1]}) + \
            models.Gaussian1D(3.6, 4853.30, 40.0, bounds = {"amplitude": [0.0, 50.0], "mean": [4830, 4880], "stddev": [10.1, 500.0]}) + \
            models.Gaussian1D(2.0, 4346.40, 2.0, bounds = {"amplitude": [0.0, 50.0], "mean": [4323, 4369], "stddev": [0.0001, 50.0]}) + \
            models.Gaussian1D(2.0, 4101.73, 2.0, bounds = {"amplitude": [0.0, 50.0], "mean": [4078, 4125], "stddev": [0.0001, 50.0]}) + \
            models.Gaussian1D(5.0, 4960.0, 6.0, bounds = {"amplitude": [0.0, 50.0], "mean": [4937, 4983], "stddev": [0.0001, 23.8]}) + \
            models.Gaussian1D(20.0, 5008.0, 6.0, bounds = {"amplitude": [0.0, 50.0], "mean": [4985, 5031], "stddev": [0.0001, 23.8]})
    else:
        hbetan_param = init_value[1][6:9]
        hbetab_param = init_value[1][9:12]
        hother_param = init_value[1][12:18]
        o3_param = init_value[1][18:24]
        hbeta_complex_fit_func = \
                    models.Gaussian1D(hbetan_param[0], hbetan_param[1], hbetan_param[2], bounds = {"amplitude": [0.0, 50.0], "mean": [4830, 4880], "stddev": [0.0001, 10.1]}) + \
                    models.Gaussian1D(hbetab_param[0], hbetab_param[1], hbetab_param[2], bounds = {"amplitude": [0.0, 50.0], "mean": [4830, 4880], "stddev": [10.1, 500.0]}) + \
                    models.Gaussian1D(hother_param[0], hother_param[1], hother_param[2], bounds = {"amplitude": [0.0, 50.0], "mean": [4323, 4369], "stddev": [0.0001, 50.0]}) + \
                    models.Gaussian1D(hother_param[3], hother_param[4], hother_param[5], bounds = {"amplitude": [0.0, 50.0], "mean": [4078, 4125], "stddev": [0.0001, 50.0]}) + \
                    models.Gaussian1D(o3_param[0], o3_param[1], o3_param[2], bounds = {"amplitude": [0.0, 50.0], "mean": [4937, 4983], "stddev": [0.0001, 23.8]}) + \
                    models.Gaussian1D(o3_param[3], o3_param[4], o3_param[5], bounds = {"amplitude": [0.0, 50.0], "mean": [4985, 5031], "stddev": [0.0001, 23.8]})
    fitter = fitting.LevMarLSQFitter()
    with warnings.catch_warnings():
        warnings.filterwarnings('error')
        try:
            fit = fitter(hbeta_complex_fit_func, wave, flux, weights = error ** (-2), maxiter = 3000)
        except Exception as reason:
            if image_control:  # Control image output
                save_fig(fig1, img_directory, str(mjd) + "-failed")
                plt.close()
            raise SpectraException("Fit failed because of " + str(reason))
    expected = np.array(fit(wave))
    if image_control:  # Control image output
        plt.plot(wave, expected)
        save_fig(fig1, img_directory, str(mjd) + "-succeed")
        plt.close()
    rcs = 0
    for i in range(len(flux)):
        rcs = rcs + (flux[i] - expected[i]) ** 2.0
    rcs = rcs / np.abs(len(flux)-23)
    if rcs > 10.0:
        raise SpectraException("Reduced chi-square too large: " + str(rcs))
    return np.append(cont_fit.parameters[0:6], fit.parameters), cont_fit.parameters[6:9], rcs, cont_fitter.fit_info['nfev'], fitter.fit_info['nfev']
def template_fit(wave, flux, error, image_control, init_value, rmid, mjd):
    img_directory = Location.project_loca + "result/fit_with_temp/fig/" + \
        str(rmid)
    # Fit continuum
    if image_control:  # Control image output
        fig = plt.figure()
        plt.plot(wave, flux)
    # Part of the spectra without any prominent emission lines
    no_line_part = [[4000.0, 4050.0], [4150.0, 4280.0], [4420, 4750],
                    [5050, 5500]]
    cont_wave = np.array([])
    cont_flux = np.array([])
    cont_error = np.array([])
    for each_part in no_line_part:
        [pwave, pflux, perror] = extract_fit_part(wave, flux, error,
                                                  each_part[0], each_part[1])
        cont_wave = np.append(cont_wave, pwave)
        cont_flux = np.append(cont_flux, pflux)
        cont_error = np.append(cont_error, perror)
    cont_fitter = fitting.LevMarLSQFitter()
    if init_value == []:
        cont = fe_temp_observed.FeII_template_obs(0.0, 2000.0, 2.6, 0.0, 2000.0, 2.6, bounds = {"i_r_l1": [0.0, 50.0], "i_r_n3": [0.0, 50.0]}) + \
            models.PowerLaw1D(flux[0], wave[0], - np.log(abs(flux[-1]/flux[0])+0.001) / np.log(abs(wave[-1]/wave[0]) + 0.001), fixed = {"x_0": True})
    else:
        fe2_param = init_value[1][0:6]
        cont = fe_temp_observed.FeII_template_obs(fe2_param[0], fe2_param[1],
                                                  fe2_param[2], fe2_param[3],
                                                  fe2_param[4], fe2_param[5],
                                                  bounds = {"i_r_l1": [0.0, 50.0], "i_r_n3": [0.0, 50.0]}) + \
            models.PowerLaw1D(init_value[0][0], init_value[0][1], init_value[0][2], fixed = {"x_0": True})
    with warnings.catch_warnings():
        warnings.filterwarnings('error')
        try:
            cont_fit = cont_fitter(cont,
                                   cont_wave,
                                   cont_flux,
                                   weights=cont_error**(-2),
                                   maxiter=10000)
        except Exception as reason:
            if image_control:  # Control image output
                save_fig(fig, img_directory, str(mjd) + "-cont-failed")
                plt.close()
            raise SpectraException("Continuum fit failed because of " +
                                   str(reason))
    if image_control:  # Control image output
        para = cont_fit.parameters[6:9]
        cont_cont = models.PowerLaw1D(para[0], para[1], para[2])
        cont_spec = cont_cont(wave)
        fit_spec = cont_fit(wave)
        plt.plot(wave, fit_spec)
        plt.plot(wave, cont_spec)
        plt.plot(wave, fit_spec - cont_spec)
        save_fig(fig, img_directory, str(mjd) + "-cont-success")
        plt.close()
    # Fit emission lines
    flux = flux - cont_fit(wave)
    if image_control:  # Control image output
        fig1 = plt.figure()
        plt.plot(wave, flux)
    if init_value == []:
        hbeta_complex_fit_func = \
            models.Gaussian1D(3.6, 4853.30, 7.0, bounds = {"amplitude": [0.0, 50.0], "mean": [4830, 4880], "stddev": [0.0001, 10.1]}) + \
            models.Gaussian1D(3.6, 4853.30, 40.0, bounds = {"amplitude": [0.0, 50.0], "mean": [4830, 4880], "stddev": [10.1, 500.0]}) + \
            models.Gaussian1D(2.0, 4346.40, 2.0, bounds = {"amplitude": [0.0, 50.0], "mean": [4323, 4369], "stddev": [0.0001, 50.0]}) + \
            models.Gaussian1D(2.0, 4101.73, 2.0, bounds = {"amplitude": [0.0, 50.0], "mean": [4078, 4125], "stddev": [0.0001, 50.0]}) + \
            models.Gaussian1D(5.0, 4960.0, 6.0, bounds = {"amplitude": [0.0, 50.0], "mean": [4937, 4983], "stddev": [0.0001, 23.8]}) + \
            models.Gaussian1D(20.0, 5008.0, 6.0, bounds = {"amplitude": [0.0, 50.0], "mean": [4985, 5031], "stddev": [0.0001, 23.8]})
    else:
        hbetan_param = init_value[1][6:9]
        hbetab_param = init_value[1][9:12]
        hother_param = init_value[1][12:18]
        o3_param = init_value[1][18:24]
        hbeta_complex_fit_func = \
                    models.Gaussian1D(hbetan_param[0], hbetan_param[1], hbetan_param[2], bounds = {"amplitude": [0.0, 50.0], "mean": [4830, 4880], "stddev": [0.0001, 10.1]}) + \
                    models.Gaussian1D(hbetab_param[0], hbetab_param[1], hbetab_param[2], bounds = {"amplitude": [0.0, 50.0], "mean": [4830, 4880], "stddev": [10.1, 500.0]}) + \
                    models.Gaussian1D(hother_param[0], hother_param[1], hother_param[2], bounds = {"amplitude": [0.0, 50.0], "mean": [4323, 4369], "stddev": [0.0001, 50.0]}) + \
                    models.Gaussian1D(hother_param[3], hother_param[4], hother_param[5], bounds = {"amplitude": [0.0, 50.0], "mean": [4078, 4125], "stddev": [0.0001, 50.0]}) + \
                    models.Gaussian1D(o3_param[0], o3_param[1], o3_param[2], bounds = {"amplitude": [0.0, 50.0], "mean": [4937, 4983], "stddev": [0.0001, 23.8]}) + \
                    models.Gaussian1D(o3_param[3], o3_param[4], o3_param[5], bounds = {"amplitude": [0.0, 50.0], "mean": [4985, 5031], "stddev": [0.0001, 23.8]})
    fitter = fitting.LevMarLSQFitter()
    with warnings.catch_warnings():
        warnings.filterwarnings('error')
        try:
            fit = fitter(hbeta_complex_fit_func,
                         wave,
                         flux,
                         weights=error**(-2),
                         maxiter=3000)
        except Exception as reason:
            if image_control:  # Control image output
                save_fig(fig1, img_directory, str(mjd) + "-failed")
                plt.close()
            raise SpectraException("Fit failed because of " + str(reason))
    expected = np.array(fit(wave))
    if image_control:  # Control image output
        plt.plot(wave, expected)
        save_fig(fig1, img_directory, str(mjd) + "-succeed")
        plt.close()
    rcs = 0
    for i in range(len(flux)):
        rcs = rcs + (flux[i] - expected[i])**2.0
    rcs = rcs / np.abs(len(flux) - 23)
    if rcs > 10.0:
        raise SpectraException("Reduced chi-square too large: " + str(rcs))
    return np.append(
        cont_fit.parameters[0:6], fit.parameters), cont_fit.parameters[
            6:9], rcs, cont_fitter.fit_info['nfev'], fitter.fit_info['nfev']
def find_i(wave, flux, ivar, wavelength, width):
    [wave_i, flux_i, ivar_i] = extract_fit_part(wave, flux, ivar, wavelength - 0.5 * width, wavelength + 0.5 * width)
    i = max(flux_i)
    return i