def test_Voigt1D_hum2(doppler): """Verify accuracy of Voigt profile in Humlicek approximation to Faddeeva.cc (SciPy).""" x = np.linspace(-20, 20, 400001) voi_w = models.Voigt1D(amplitude_L=2.0 / np.pi, fwhm_L=1.0, fwhm_G=doppler, method='wofz') vf_w = voi_w(x) dvda_w = voi_w.fit_deriv(x, x_0=0, amplitude_L=2.0 / np.pi, fwhm_L=1.0, fwhm_G=doppler) voi_h = models.Voigt1D(amplitude_L=2.0 / np.pi, fwhm_L=1.0, fwhm_G=doppler, method='humlicek2') vf_h = voi_h(x) dvda_h = voi_h.fit_deriv(x, x_0=0, amplitude_L=2.0 / np.pi, fwhm_L=1.0, fwhm_G=doppler) assert_allclose(vf_h, vf_w, rtol=1e-7 * (2 + 1 / np.sqrt(doppler))) assert_allclose(dvda_h, dvda_w, rtol=1e-9, atol=1e-7 * (1 + 30 / doppler))
def test_Voigt1D(): voi = models.Voigt1D(amplitude_L=-0.5, x_0=1.0, fwhm_L=5.0, fwhm_G=5.0) xarr = np.linspace(-5.0, 5.0, num=40) yarr = voi(xarr) voi_init = models.Voigt1D(amplitude_L=-1.0, x_0=1.0, fwhm_L=5.0, fwhm_G=5.0) fitter = fitting.LevMarLSQFitter() voi_fit = fitter(voi_init, xarr, yarr) assert_allclose(voi_fit.param_sets, voi.param_sets)
def test_Voigt1D(): voi = models.Voigt1D(amplitude_L=-0.5, x_0=1.0, fwhm_L=5.0, fwhm_G=5.0) xarr = np.linspace(-5.0, 5.0, num=40) yarr = voi(xarr) voi_init = models.Voigt1D(amplitude_L=-1.0, x_0=1.0, fwhm_L=5.0, fwhm_G=5.0) fitter = fitting.LevMarLSQFitter() voi_fit = fitter(voi_init, xarr, yarr) assert_allclose(voi_fit.param_sets, voi.param_sets) # Invalid method with pytest.raises(ValueError) as err: models.Voigt1D(method='test') assert str(err.value) ==\ "Not a valid method for Voigt1D Faddeeva function: test."
def VoigtFit(pixels, projected_footprint, A, mu, sigma, residuals, i, plot): g_init = models.Voigt1D(amplitude_L=A, x_0=mu, fwhm_G=sigma * 2., fwhm_L=sigma * 3) #g_init.x_0.min = 0. #g_init.x_0.max = 80. #g_init.fwhm_L.min = 0.1 #g_init.fwhm_G.min = 0.1 #g_init.fwhm_L.max = 20. #g_init.fwhm_G.max = 20. fit_g = fitting.LevMarLSQFitter() psf = fit_g(g_init, pixels, projected_footprint) start = psf.x_0 - 5 * (psf.fwhm_L + psf.fwhm_G) / 2 end = psf.x_0 + 5 * (psf.fwhm_L + psf.fwhm_G) / 2 integral = (integrate.quad(lambda pixels: psf(pixels), start, end))[0] ''' begin Control plot''' if ((not i % 10) and (i < 400) and (plot == True)): pl.plot(pixels, psf(pixels), label='Voigt') pl.yscale('log') pl.ylim(1., 1E6) pl.plot(pixels, projected_footprint) pl.legend() pl.show() ''' End control plot''' return
def VoigtFit(pixels, profile, A, mu, sigma, weights=[], **kwargs): #pixels = pixels[20:60] est a smaller footprint. bof. definitley need a weight map. #profile = profile[20:60] ### I will return the gaussian profile as a weight map #weights=1/profile**2 weights = np.ones(len(pixels)) g_init = models.Voigt1D(amplitude_L=A, x_0=mu, fwhm_G=sigma * 2., fwhm_L=sigma * 3) #g_init.x_0.min = 0. #g_init.x_0.max = 80. #g_init.fwhm_L.min = 0.1 #g_init.fwhm_G.min = 0.1 #g_init.fwhm_L.max = 20. #g_init.fwhm_G.max = 20. fit_g = fitting.LevMarLSQFitter() psf = fit_g(g_init, pixels, profile, weights=weights) start = psf.x_0 - 5 * (psf.fwhm_L + psf.fwhm_G) / 2 end = psf.x_0 + 5 * (psf.fwhm_L + psf.fwhm_G) / 2 integral = (integrate.quad(lambda pixels: psf(pixels), start, end))[0] ''' begin Control plot''' #pl.plot(pixels, psf(pixels), label='Voigt') #pl.plot(pixels, weights, label='weights') #pl.yscale('log') #pl.ylim(1., 1E6) #pl.plot(profile) #pl.legend() #pl.show() ''' End control plot''' return integral, psf.fwhm_L.value, psf.fwhm_G.value
def test_Voigt1D_norm(algorithm): """Test integral of normalized Voigt profile.""" voi = models.Voigt1D(amplitude_L=1.0/np.pi, x_0=0.0, fwhm_L=2.0, fwhm_G=1.5, method=algorithm) if algorithm == 'wofz': atol = 1e-14 else: atol = 1e-8 assert_allclose(quad(voi, -np.inf, np.inf)[0], 1.0, atol=atol)
def test_voigt_model(): """ Currently just tests that the model peaks at its origin. Regression test for https://github.com/astropy/astropy/issues/3942 """ m = models.Voigt1D(x_0=5, amplitude_L=10, fwhm_L=0.5, fwhm_G=0.9) x = np.arange(0, 10, 0.01) y = m(x) assert y[500] == y.max() # y[500] is right at the center
def test_parameter_description(): model = models.Gaussian1D(1.5, 2.5, 3.5) assert model.amplitude._description == "Amplitude (peak value) of the Gaussian" assert model.mean._description == "Position of peak (Gaussian)" model = models.Voigt1D(x_0=5, amplitude_L=10, fwhm_L=0.5, fwhm_G=0.9) assert model.amplitude_L._description == "The Lorentzian amplitude" assert model.fwhm_L._description == "The Lorentzian full width at half maximum" assert model.fwhm_G._description == "The Gaussian full width at half maximum"
def Signal_Analysis(x, y, params): #Create fit using initial parameters #Stop fit from wandering onto random spikes of noise bound_centre = (params[0] - 15, params[0] + 15) bound_width = (params[3] - 2, params[3] + 30) #bound_amp = (0,params[1]),'amplitude_L': bound_amp bound_parameters = {'x_o': bound_centre, 'fwhm_G': bound_width} fit_init = models.Voigt1D(params[0], params[1], params[2], params[3], bounds=bound_parameters) fit = fitting.LevMarLSQFitter() fitted_model = fit(fit_init, x, y) #Get value for fit peak (amplitude_L is not applicable) peak = abs(min(fitted_model(x))) #Post-Processing #Formula for voight width is found Olivero 1977 fwhm_V = (fitted_model.fwhm_L / 2) + m.sqrt((fitted_model.fwhm_L**2) / 4 + fitted_model.fwhm_G**2) window_length = (1 / 3) * fwhm_V if window_length > 1: box_window = convolution.Box1DKernel(window_length) y = convolution.convolve(y, box_window) else: window_length = 2 box_window = convolution.Box1DKernel(window_length) y = convolution.convolve(y, box_window) #Signal-to-Noise baseline = y - fitted_model( x ) #not cheating....just to find the sigma of the non-peak reason lazily noise = stats.mad_std(baseline) snr = abs(peak) / noise if snr > 4: peak = min(y) snr = abs(peak) / noise else: pass return y, fitted_model, snr
y_0=1.5, ellip=0.0, theta=0.0), astmodels.Sine1D(amplitude=10., frequency=0.5, phase=1.), astmodels.Cosine1D(amplitude=10., frequency=0.5, phase=1.), astmodels.Tangent1D(amplitude=10., frequency=0.5, phase=1.), astmodels.ArcSine1D(amplitude=10., frequency=0.5, phase=1.), astmodels.ArcCosine1D(amplitude=10., frequency=0.5, phase=1.), astmodels.ArcTangent1D(amplitude=10., frequency=0.5, phase=1.), astmodels.Trapezoid1D(amplitude=10., x_0=0.5, width=5., slope=1.), astmodels.TrapezoidDisk2D(amplitude=10., x_0=0.5, y_0=1.5, R_0=5., slope=1.), astmodels.Voigt1D(x_0=0.55, amplitude_L=10., fwhm_L=0.5, fwhm_G=0.9), astmodels.BlackBody(scale=10.0, temperature=6000. * u.K), astmodels.Drude1D(amplitude=10.0, x_0=0.5, fwhm=2.5), astmodels.Plummer1D(mass=10.0, r_plum=5.0), astmodels.BrokenPowerLaw1D(amplitude=10, x_break=0.5, alpha_1=2.0, alpha_2=3.5), astmodels.ExponentialCutoffPowerLaw1D(10, 0.5, 2.0, 7.), astmodels.LogParabola1D( amplitude=10, x_0=0.5, alpha=2., beta=3., ), astmodels.PowerLaw1D(amplitude=10., x_0=0.5, alpha=2.0),
def test_single_peak_estimate(): """ Single Peak fit. """ # Create the spectrum x_single, y_single = single_peak() s_single = Spectrum1D(flux=y_single*u.Jy, spectral_axis=x_single*u.um) # # Estimate parameter Gaussian1D # we give the true values for the Gaussian because it actually *should* # be pretty close to the true values, because it's a Gaussian... # g_init = estimate_line_parameters(s_single, models.Gaussian1D()) assert np.isclose(g_init.amplitude.value, 3., rtol=.2) assert np.isclose(g_init.mean.value, 6.3, rtol=.1) assert np.isclose(g_init.stddev.value, 0.8, rtol=.3) assert g_init.amplitude.unit == u.Jy assert g_init.mean.unit == u.um assert g_init.stddev.unit == u.um # # Estimate parameter Lorentz1D # unlike the Gaussian1D here we do hand-picked comparison values, because # the "single peak" is a Gaussian and therefore the Lorentzian fit shouldn't # be quite right anyway # g_init = estimate_line_parameters(s_single, models.Lorentz1D()) assert np.isclose(g_init.amplitude.value, 3.354169257846847) assert np.isclose(g_init.x_0.value, 6.218588636687762) assert np.isclose(g_init.fwhm.value, 1.6339001193853715) assert g_init.amplitude.unit == u.Jy assert g_init.x_0.unit == u.um assert g_init.fwhm.unit == u.um # # Estimate parameter Voigt1D # g_init = estimate_line_parameters(s_single, models.Voigt1D()) assert np.isclose(g_init.amplitude_L.value, 3.354169257846847) assert np.isclose(g_init.x_0.value, 6.218588636687762) assert np.isclose(g_init.fwhm_L.value, 1.1553418541989058) assert np.isclose(g_init.fwhm_G.value, 1.1553418541989058) assert g_init.amplitude_L.unit == u.Jy assert g_init.x_0.unit == u.um assert g_init.fwhm_L.unit == u.um assert g_init.fwhm_G.unit == u.um # # Estimate parameter RickerWavelet1D # mh = models.RickerWavelet1D estimators = { 'amplitude': lambda s: max(s.flux), 'x_0': lambda s: centroid(s, region=None), 'sigma': lambda s: fwhm(s) } #mh._constraints['parameter_estimator'] = estimators mh.amplitude.estimator = lambda s: max(s.flux) mh.x_0.estimator = lambda s: centroid(s, region=None) mh.sigma.estimator = lambda s: fwhm(s) g_init = estimate_line_parameters(s_single, mh) assert np.isclose(g_init.amplitude.value, 3.354169257846847) assert np.isclose(g_init.x_0.value, 6.218588636687762) assert np.isclose(g_init.sigma.value, 1.6339001193853715) assert g_init.amplitude.unit == u.Jy assert g_init.x_0.unit == u.um assert g_init.sigma.unit == u.um
def test_single_peak_estimate(): """ Single Peak fit. """ # Create the spectrum x_single, y_single = single_peak() s_single = Spectrum1D(flux=y_single*u.Jy, spectral_axis=x_single*u.um) # # Estimate parameter Gaussian1D # g_init = estimate_line_parameters(s_single, models.Gaussian1D()) assert np.isclose(g_init.amplitude.value, 3.354169257846847) assert np.isclose(g_init.mean.value, 6.218588636687762) assert np.isclose(g_init.stddev.value, 1.6339001193853715) assert g_init.amplitude.unit == u.Jy assert g_init.mean.unit == u.um assert g_init.stddev.unit == u.um # # Estimate parameter Lorentz1D # g_init = estimate_line_parameters(s_single, models.Lorentz1D()) assert np.isclose(g_init.amplitude.value, 3.354169257846847) assert np.isclose(g_init.x_0.value, 6.218588636687762) assert np.isclose(g_init.fwhm.value, 1.6339001193853715) assert g_init.amplitude.unit == u.Jy assert g_init.x_0.unit == u.um assert g_init.fwhm.unit == u.um # # Estimate parameter Voigt1D # g_init = estimate_line_parameters(s_single, models.Voigt1D()) assert np.isclose(g_init.amplitude_L.value, 3.354169257846847) assert np.isclose(g_init.x_0.value, 6.218588636687762) assert np.isclose(g_init.fwhm_L.value, 1.1553418541989058) assert np.isclose(g_init.fwhm_G.value, 1.1553418541989058) assert g_init.amplitude_L.unit == u.Jy assert g_init.x_0.unit == u.um assert g_init.fwhm_L.unit == u.um assert g_init.fwhm_G.unit == u.um # # Estimate parameter MexicanHat1D # mh = models.MexicanHat1D() estimators = { 'amplitude': lambda s: max(s.flux), 'x_0': lambda s: centroid(s, region=None), 'stddev': lambda s: fwhm(s) } mh._constraints['parameter_estimator'] = estimators g_init = estimate_line_parameters(s_single, mh) assert np.isclose(g_init.amplitude.value, 3.354169257846847) assert np.isclose(g_init.x_0.value, 6.218588636687762) assert np.isclose(g_init.stddev.value, 1.6339001193853715) assert g_init.amplitude.unit == u.Jy assert g_init.x_0.unit == u.um assert g_init.stddev.unit == u.um
def make_2d_spectra(separation_fwhm=0, n_targets=1, fwhm=8., intens=0., noise_level=1., plots=False): x = 4056 y = 1550 header_copy = fits.getheader('/data/simon/data/soar/work/20161114_eng/reduced_data/fzh.0298_CVSO166_400m2_gg455.fits') header_copy['OBJECT'] = 'Test-%s'%str(separation_fwhm) header_copy['HISTORY'] = 'Simulated spectrum N-sources %s separation_fwhm %s FWHM %s' % (n_targets, separation_fwhm, fwhm) targets = n_targets target_separation_fwhm = float(separation_fwhm) image = [] if targets > 1: target_location = [y / 2. - target_separation_fwhm / float(targets) * fwhm, y / 2. + target_separation_fwhm / float(targets) * fwhm] print separation_fwhm, int(y / 2.), target_location, (target_separation_fwhm / targets) * fwhm else: target_location = [y / 2.] sub_x = np.linspace(0, 10, x) y_axis = range(y) spectrum = [[] for i in range(int(targets))] for i in range(x): if noise_level == 0: data = np.ones(y) else: data = np.random.normal(10, noise_level, y) for tar in range(int(targets)): amplitude = intens * intensity(sub_x[i]) # theo_snr = amplitude / noise_level # print theo_snr # gauss = models.Gaussian1D(amplitude=amplitude, mean=target_location[tar], stddev=fwhm) 8.24687326842 voigt = models.Voigt1D(amplitude_L=amplitude, x_0=target_location[tar], fwhm_L=0.942561669206, fwhm_G=fwhm) # gauss2 = models.Gaussian1D(amplitude=amplitude, mean=target_location[1], stddev=fwhm) # spectrum[tar].append(amplitude) sd = voigt(y_axis) spectrum[tar].append(np.sum(sd[int(target_location[tar] - 2.5 * fwhm):int(target_location[tar] + 2.5 * fwhm)])) # gauss.amplitude.value = amplitude data += voigt(y_axis) # signal_peak = xxxx # snr = 5 # noise_level = 400. # noise_amplitude = signal_peak / snr # data = np.random.normal(noise_level, noise_amplitude, data.shape) # data2 = gauss2(y_axis) # plt.plot(data) # plt.plot(data2) # plt.show() if i == int(x / 2.) and plots: # plt.title('FWHM Separation: %s' % separation_fwhm) plt.title('Intensity: %s' % (intens)) plt.axvline(int(target_location[tar] - 2.5 * fwhm), color='r') plt.axvline(int(target_location[tar] + 2.5 * fwhm), color='r') plt.plot(data) plt.show() image.append(data) # plt.plot(y_axis, data) # plt.show() # rotated = zip(*original[::-1]) rotated_image = zip(*image[::-1]) hdu_name_file = '20161128_single-object_n%s_s%s-fwhm_%1.3f_int.fits'% (str(int(n_targets)), str(int(separation_fwhm)), intens) print(hdu_name_file) new_hdu = fits.PrimaryHDU(rotated_image, header=header_copy) new_hdu.writeto(hdu_name_file, clobber=True) for part_index in range(len(spectrum)): # f = open('obj.save', 'wb') # cPickle.dump(my_obj, f, protocol=cPickle.HIGHEST_PROTOCOL) # f.close() f = open(hdu_name_file.replace('.fits','_%s.pkl' % str(part_index + 1)), 'wb') pickle.dump(spectrum[part_index][::-1], f, protocol=pickle.HIGHEST_PROTOCOL) f.close() plt.plot(spectrum[part_index][::-1]) plt.title('Simulated spectrum') plt.xlabel('Pixel Axis') plt.ylabel('Peak Intensity') plt.savefig('img/' + hdu_name_file.replace('.fits','.png'), dpi=300) if plots: plt.show() if plots: plt.title('Target Separation %s - N targets %s' % (str(separation_fwhm), targets)) plt.imshow(rotated_image) plt.show()
print('-' * 20) print('Amplitude:', optim_ly[0]) print('Mean: ', optim_ly[1]) print('Sigma: ', optim_ly[2]) print('Error: ', np.sqrt(np.diag(covar_ly))) print('Peak: ', lorentz(np.where(sum_y == np.max(sum_y))[0][0], *optim_ly)) print('FWHM: ', FWHM(sum_y, optim_ly, lorentz)) ## Voigt lwx = FWHM(sum_x, optim_lx, lorentz) dif_lx = lwx[1] - lwx[0] lwy = FWHM(sum_y, optim_ly, lorentz) dif_ly = lwy[1] - lwy[0] vx_init = models.Voigt1D(x_0 = max_locx, amplitude_L = optim_lx[0], \ fwhm_L = dif_lx, fwhm_G = dif_gx) fit_vx = fitting.LevMarLSQFitter() vx = fit_vx(vx_init, xra, sum_x) vy_init = models.Voigt1D(x_0 = max_locy, amplitude_L = optim_ly[0], \ fwhm_L = dif_ly, fwhm_G = dif_gy) fit_vy = fitting.LevMarLSQFitter() vy = fit_vy(vy_init, yra, sum_y) optim_vx, covar_vx = curve_fit(voigt, xra, sum_x, p0=[1, max_locx, dif_lx, dif_gx]) optim_vy, covar_vy = curve_fit(voigt, yra, sum_y,
def get_model_with_fitter(model_type, x, y): min_x, max_x = np.min(x), np.max(x) location_param = np.mean(x) amplitude_param = np.max(np.abs(y)) spread_param = (max_x - min_x) / len(x) if model_type == FittingModels.GAUSSIAN_PLUS_LINEAR: model = models.Gaussian1D( amplitude=amplitude_param, mean=location_param, stddev=spread_param) + models.Polynomial1D(degree=1) fitter = fitting.LevMarLSQFitter() elif model_type == FittingModels.LORENTZIAN_PLUS_LINEAR: model = models.Lorentz1D( amplitude=amplitude_param, x_0=location_param, fwhm=spread_param) + models.Polynomial1D(degree=1) fitter = fitting.LevMarLSQFitter() elif model_type == FittingModels.VOIGT_PLUS_LINEAR: model = models.Voigt1D( x_0=location_param, amplitude_L=amplitude_param, fwhm_L=spread_param, fwhm_G=spread_param) + models.Polynomial1D(degree=1) fitter = fitting.LevMarLSQFitter() elif model_type == FittingModels.GAUSSIAN: model = models.Gaussian1D(amplitude=amplitude_param, mean=location_param, stddev=spread_param) fitter = fitting.LevMarLSQFitter() elif model_type == FittingModels.LORENTZIAN: model = models.Lorentz1D(amplitude=amplitude_param, x_0=location_param, fwhm=spread_param) fitter = fitting.LevMarLSQFitter() elif model_type == FittingModels.VOIGT: model = models.Voigt1D(x_0=location_param, amplitude_L=amplitude_param, fwhm_L=spread_param, fwhm_G=spread_param) fitter = fitting.LevMarLSQFitter() elif model_type == FittingModels.CHEBYSHEV_3: model = models.Chebyshev1D(degree=3) fitter = fitting.LinearLSQFitter() elif model_type == FittingModels.POLYNOMIAL_1: model = models.Polynomial1D(degree=1) fitter = fitting.LinearLSQFitter() elif model_type == FittingModels.POLYNOMIAL_2: model = models.Polynomial1D(degree=2) fitter = fitting.LinearLSQFitter() elif model_type == FittingModels.POLYNOMIAL_3: model = models.Polynomial1D(degree=3) fitter = fitting.LinearLSQFitter() else: raise Exception("Model " + str(model_type) + " not in default models list.") return model, fitter
def _fit_model_to_fluxOLD(self, trace_names, application_data, fitting_models, selected_data, custom_model=None, custom_fitter=None, do_update_client=True, include_fit_substracted_trace=False): # http://learn.astropy.org/rst-tutorials/User-Defined-Model.html # https://docs.astropy.org/en/stable/modeling/new-model.html # https://docs.astropy.org/en/stable/modeling/index.html # https://docs.astropy.org/en/stable/modeling/reference_api.html curve_mapping = { name: ind for ind, name in enumerate(application_data['traces']) } for fitting_model in fitting_models: for trace_name in trace_names: #ind = trace_indexes[trace_name] trace = application_data['traces'].get(trace_name) curve_number = curve_mapping[trace_name] x = np.asarray([ point['x'] for point in selected_data["points"] if point['curveNumber'] == curve_number ]) y = np.asarray([ point['y'] for point in selected_data["points"] if point['curveNumber'] == curve_number ]) ind = [ point['pointIndex'] for point in selected_data["points"] if point['curveNumber'] == curve_number ] y_err = np.asarray( trace["flux_error"] )[ind] if trace["flux_error"] is not None or len( trace["flux_error"]) > 0 else None min_x, max_x = np.min(x), np.max(x) if custom_model is None and custom_fitter is None: location_param = np.mean(x) amplitude_param = np.max(np.abs(y)) spread_param = (max_x - min_x) / len(x) if fitting_model == FittingModels.GAUSSIAN_PLUS_LINEAR: data_model = models.Gaussian1D( amplitude=amplitude_param, mean=location_param, stddev=spread_param) + models.Polynomial1D( degree=1) elif fitting_model == FittingModels.LORENTZIAN_PLUS_LINEAR: data_model = models.Lorentz1D( amplitude=amplitude_param, x_0=location_param, fwhm=spread_param) + models.Polynomial1D(degree=1) elif fitting_model == FittingModels.VOIGT_PLUS_LINEAR: data_model = models.Voigt1D( x_0=location_param, amplitude_L=amplitude_param, fwhm_L=spread_param, fwhm_G=spread_param) + models.Polynomial1D( degree=1) else: raise Exception("Unsupported fitting model " + str(fitting_model)) fitting_model_name = fitting_model fitter = fitting.LevMarLSQFitter() fitted_model = fitter(data_model, x, y, weights=1. / y_err) else: fitting_model_name = str(custom_model) fitter = custom_fitter fitted_model = fitter(custom_model, x, y, weights=1. / y_err) x_grid = np.linspace(min_x, max_x, 5 * len(x)) y_grid = fitted_model(x_grid) parameter_errors = np.sqrt( np.diag(fitter.fit_info['param_cov']) ) if fitter.fit_info['param_cov'] is not None else None fitted_trace_name = "fit" + str( len(application_data['fitted_models']) + 1) + "_" + trace_name ancestors = trace['ancestors'] + [trace_name] flambda = [f for f in np.asarray(trace['flambda'])[ind]] fitted_trace = Trace(name=fitted_trace_name, wavelength=[x for x in x_grid], flux=[y for y in y_grid], ancestors=ancestors, spectrum_type=SpectrumType.FIT, color="black", linewidth=1, alpha=1.0, wavelength_unit=trace['wavelength_unit'], flux_unit=trace['flux_unit'], flambda=flambda, catalog=trace['catalog']).to_dict() self._set_color_for_new_trace(fitted_trace, application_data) self._add_trace_to_data(application_data, fitted_trace_name, fitted_trace, False) if include_fit_substracted_trace: fitted_trace_name = "fit_substr_" + str( len(application_data['fitted_models']) + 1) + "_" + trace_name ancestors = trace['ancestors'] + [trace_name] y_grid2 = fitted_model(x) flux = y - y_grid2 f_labmda = fl.convert_flux( flux=x, wavelength=y, from_flux_unit=trace['flux_unit'], to_flux_unit=FluxUnit.F_lambda, to_wavelength_unit=trace.get('flux_unit')) fitted_trace = Trace( name=fitted_trace_name, wavelength=[x for x in x], flux=[y for y in flux], ancestors=ancestors, spectrum_type=SpectrumType.FIT, color="black", linewidth=1, alpha=1.0, wavelength_unit=trace['wavelength_unit'], flux_unit=trace['flux_unit'], flambda=f_labmda, catalog=trace['catalog']).to_dict() self._set_color_for_new_trace(fitted_trace, application_data) self._add_trace_to_data(application_data, fitted_trace_name, fitted_trace, do_update_client=False) fitted_info = {} fitted_info['name'] = fitted_trace_name fitted_info['ancestors'] = ancestors fitted_info['model'] = fitting_model_name fitted_info['parameters'] = { x: y for (x, y) in zip(fitted_model.param_names, fitted_model.parameters) } fitted_info['parameter_errors'] = { x: y for (x, y) in zip(fitted_model.param_names, parameter_errors) } if parameter_errors is not None else None fitted_info['selection_indexes'] = ind fitted_info['wavelength_unit'] = trace['wavelength_unit'] fitted_info['flux_unit'] = trace['flux_unit'] # add to application data: fitted_models = application_data['fitted_models'] fitted_models[fitted_trace_name] = fitted_info application_data['fitted_models'] = fitted_models application_data['traces'][fitted_trace_name] = fitted_trace application_data['fitted_models'][ fitted_trace_name] = fitted_info self.write_info( "fitting model2122 : " + str(application_data['fitted_models'][fitted_trace_name])) if do_update_client: self.update_client()