def test_fitting_with_outlier_removal_niter(): """ Test that FittingWithOutlierRemoval stops prior to reaching niter if the set of masked points has converged and correctly reports the actual number of iterations performed. """ # 2 rows with some noise around a constant level and 1 deviant point: x = np.arange(25) with NumpyRNGContext(_RANDOM_SEED): y = np.random.normal(loc=10., scale=1., size=(2, 25)) y[0, 14] = 100. # Fit 2 models with up to 5 iterations (should only take 2): fitter = FittingWithOutlierRemoval( fitter=LinearLSQFitter(), outlier_func=sigma_clip, niter=5, sigma_lower=3., sigma_upper=3., maxiters=1 ) model, mask = fitter(models.Chebyshev1D(2, n_models=2), x, y) # Confirm that only the deviant point was rejected, in 2 iterations: assert_equal(np.where(mask), [[0], [14]]) assert fitter.fit_info['niter'] == 2 # Refit just the first row without any rejection iterations, to ensure # there are no regressions for that special case: fitter = FittingWithOutlierRemoval( fitter=LinearLSQFitter(), outlier_func=sigma_clip, niter=0, sigma_lower=3., sigma_upper=3., maxiters=1 ) model, mask = fitter(models.Chebyshev1D(2), x, y[0]) # Confirm that there were no iterations or rejected points: assert mask.sum() == 0 assert fitter.fit_info['niter'] == 0
def get_order_trace_old(s): x = np.arange(len(s)) s = np.array(s) mm = s > max(s) * 0.05 dd1, dd2 = np.nonzero(mm)[0][[0, -1]] # mask out absorption feature smooth_size = 20 s0 = ni.median_filter(s, 40) s_s0 = s - s0 s_s0_std = s_s0[np.abs(s_s0) < 2. * s_s0.std()].std() mmm = s_s0 > -3. * s_s0_std s1 = ni.gaussian_filter1d(s0[dd1:dd2], smooth_size, order=1) #x1 = x[dd1:dd2] s1r = s1 s1_std = s1r.std() s1_std = s1r[np.abs(s1r) < 2. * s1_std].std() s1r[np.abs(s1r) < 2. * s1_std] = np.nan if np.any(np.isfinite(s1r[:1024])): i1 = np.nanargmax(s1r[:1024]) i1r = np.where(~np.isfinite(s1r[:1024][i1:]))[0][0] i1 = dd1 + i1 + i1r #+smooth_size else: i1 = dd1 if np.any(np.isfinite(s1r[1024:])): i2 = np.nanargmin(s1r[1024:]) i2r = np.where(~np.isfinite(s1r[1024:][:i2]))[0][-1] i2 = dd1 + 1024 + i2r else: i2 = dd2 if 0: p_init = models.Chebyshev1D(degree=6, window=[0, 2047]) fit_p = fitting.LinearLSQFitter() p = fit_p(p_init, x[i1:i2][mmm[i1:i2]], s[i1:i2][mmm[i1:i2]]) if 1: # t= np.linspace(x[i1]+10, x[i2-1]-10, 10) # p = LSQUnivariateSpline(x[i1:i2], # s[i1:i2], # t, bbox=[0, 2047]) # t= np.concatenate([[x[1],x[i1-5],x[i1],x[i1+5]], # np.linspace(x[i1]+10, x[i2-1]-10, 10), # [x[i2-5], x[i2], x[i2+5],x[-2]]]) t = np.concatenate([[x[1], x[i1]], np.linspace(x[i1] + 10, x[i2 - 1] - 10, 10), [x[i2], x[-2]]]) p = LSQUnivariateSpline(x, s0, t, bbox=[0, 2047]) return p
def read_gsp_wcs(self, ccd): """Read a GSP-specific wavelength solution Args: ccd (CCDData) :class:`~astropy.nddata.CCDData` instance Returns: astropy.modeling.Model instance """ assert isinstance(ccd, CCDData) self.model_name = ccd.header['GSP_FUNC'] self.degree = ccd.header['GSP_ORDR'] self._binning = int(ccd.header['CCDSUM'].split()[0]) if self.model_name == 'Chebyshev1D': self.model = models.Chebyshev1D(degree=self.degree) for i in range(ccd.header['GSP_ORDR'] + 1): self.model.__getattr__('c{:d}'.format(i)).value = ccd.header[ 'GSP_C{:03d}'.format(i)] self.wavelength_and_intensity = [ self.model(range(ccd.header['GSP_NPIX'])), ccd.data ] return self.wavelength_and_intensity
def make_inverse_chebyshev1d(model, sampling=1, rms=None, max_deviation=None): """ This creates a Chebyshev1D model that attempts to be the inverse of a specified model that maps from an input space (e.g., pixels) to an output space (e.g., wavelength). Parameters ---------- model: Chebyshev1D The model to be inverted sampling: int Frequency at which to sample the input coordinate space rms: float/None required maximum rms in input space max_deviation: float/None required maximum absolute deviation in input space """ order = model.degree max_order = order if (rms is None and max_deviation is None) else order + 2 incoords = np.arange(*model.domain, sampling) outcoords = model(incoords) while order <= max_order: m_init = models.Chebyshev1D(degree=order, domain=model(model.domain)) fit_it = fitting.LinearLSQFitter() m_inverse = fit_it(m_init, outcoords, incoords) trans_coords = m_inverse(outcoords) rms_inverse = np.std(trans_coords - incoords) max_dev = np.max(abs(trans_coords - incoords)) if ((rms is None or rms_inverse <= rms) and (max_deviation is None or max_dev <= max_deviation)): break order += 1 return m_inverse
def _chebyshev(wcs_dict): """Returns a chebyshev model of the wavelength solution. Constructs a Chebyshev1D mathematical model Parameters ---------- wcs_dict : dict Dictionary containing all the wcs information decoded from the header and necessary for constructing the Chebyshev1D model. Returns ------- `~astropy.modeling.Model` """ model = models.Chebyshev1D(degree=wcs_dict['order'] - 1, domain=[wcs_dict['pmin'], wcs_dict['pmax']], ) new_params = [wcs_dict['fpar'][i] for i in range(wcs_dict['order'])] model.parameters = new_params return model
def test_window_orthopoly(tmpdir): model1d = astmodels.Chebyshev1D(2, c0=2, c1=3, c2=0.5, domain=[-2, 2], window=[-0.5, 0.5]) model2d = astmodels.Chebyshev2D(1, 1, c0_0=1, c0_1=2, c1_0=3, x_domain=[-2, 2], y_domain=[-2, 2], x_window=[-0.5, 0.5], y_window=[-0.1, 0.5]) fa = AsdfFile() fa.tree['model1d'] = model1d fa.tree['model2d'] = model2d file_path = str(tmpdir.join('orthopoly_window.asdf')) fa.write_to(file_path) with asdf.open(file_path) as f: assert f.tree['model1d'](1.8) == model1d(1.8) assert f.tree['model2d'](1.8, -1.5) == model2d(1.8, -1.5)
def test__save_science_data(self): wavelength_solution = models.Chebyshev1D(degree=3) wavelength_solution.c0.value = 4419.161693945127 wavelength_solution.c1.value = 1.321103785944705 wavelength_solution.c2.value = -2.9766005683232e-06 wavelength_solution.c3.value = -4.864180906701e-10 fname = self.wc._save_science_data( ccd=self.ccd, wavelength_solution=wavelength_solution, save_to=os.getcwd(), index=None, plot_results=False, save_plots=False, plots=False) self.file_list.append(fname) fname_2 = self.wc._save_science_data( ccd=self.ccd, wavelength_solution=wavelength_solution, save_to=os.getcwd(), index=1, plot_results=False, save_plots=False, plots=False) self.file_list.append(fname_2) expected_name = os.getcwd() + '/w' + re.sub( '.fits', '', os.path.basename( self.ccd.header['GSP_FNAM'])) + "_ws_{:d}".format(1) + ".fits" self.assertEqual( fname, os.getcwd() + '/w' + os.path.basename(self.ccd.header['GSP_FNAM'])) self.assertEqual(fname_2, expected_name)
def make_inverse_chebyshev1d(model, sampling=1, rms=None): """ This creates a Chebyshev1D model that attempts to be the inverse of the model provided. Parameters ---------- model: Chebyshev1D The model to be inverted rms: float/None required maximum rms in input space (i.e., pixels) """ order = model.degree max_order = order if rms is None else order + 2 incoords = np.arange(*model.domain, sampling) outcoords = model(incoords) while order <= max_order: m_init = models.Chebyshev1D(degree=order, domain=model(model.domain)) fit_it = fitting.LinearLSQFitter() m_inverse = fit_it(m_init, outcoords, incoords) rms_inverse = np.std(m_inverse(outcoords) - incoords) if rms is None or rms_inverse <= rms: break order += 1 return m_inverse
def make_2dspec_image( nx=3000, ny=1000, background=5, trace_center=None, trace_order=3, trace_coeffs={'c0': 0, 'c1': 50, 'c2': 100}, source_amplitude=10, source_alpha=0.1 ): """ Create synthetic 2D spectroscopic image with a single source. The spatial (y-axis) position of the source along the dispersion (x-axis) direction is modeled using a Chebyshev polynomial. The flux units are counts and the noise is modeled as Poisson. Parameters ---------- nx : int (default=3000) Size of image in X axis which is assumed to be the dispersion axis ny : int (default=1000) Size of image in Y axis which is assumed to be the spatial axis background : int (default=5) Level of constant background in counts trace_center : int (default=None) Zeropoint of the trace. If None, then use center of Y (spatial) axis. trace_order : int (default=3) Order of the Chebyshev polynomial used to model the source's trace trace_coeffs : dict (default={'c0': 0, 'c1': 50, 'c2': 100}) Dict containing the Chebyshev polynomial coefficients to use in the trace model source_amplitude : int (default=10) Amplitude of modeled source in counts source_alpha : float (default=0.1) Power index of the source's Moffat profile. Use small number here to emulate extended source. Returns ------- ccd_im : `~astropy.nddata.CCDData` CCDData instance containing synthetic 2D spectroscopic image """ x = np.arange(nx) y = np.arange(ny) xx, yy = np.meshgrid(x, y) profile = models.Moffat1D() profile.amplitude = source_amplitude profile.alpha = source_alpha if trace_center is None: trace_center = ny / 2 trace_mod = models.Chebyshev1D(degree=trace_order, **trace_coeffs) trace = yy - trace_center + trace_mod(xx/nx) z = background + profile(trace) noisy_image = apply_poisson_noise(z) ccd_im = CCDData(noisy_image, unit=u.count) return ccd_im
def chebyshev1d(): coefficients = [550., 80., 3.2, 1.6, 1.6] coefficients_dict = { 'c{}'.format(i): c for i, c in enumerate(coefficients) } model = models.Chebyshev1D(degree=4, domain=[0, 3200], **coefficients_dict) return model
def test_get_wsolution(self): self.assertIsNone(self.wc.get_wsolution()) self.wc.wsolution = models.Chebyshev1D(degree=2) self.wc.wsolution.c0.value = 3977.9485 self.wc.wsolution.c1.value = 1.00153387 self.wc.wsolution.c2.value = -1.2891437 self.assertIsInstance(self.wc.get_wsolution(), Model)
def _chebyshev(self): """Returns a chebyshev model""" self.model = models.Chebyshev1D(degree=self.wcs_dict['order'] - 1, domain=[self.wcs_dict['pmin'], self.wcs_dict['pmax']], ) # self.model.parameters[0] = self.wcs_dict['pmin'] for param_index in range(self.wcs_dict['order']): self.model.parameters[param_index] = self.wcs_dict['fpar'][ param_index]
def fit_cheb(x, y, npoly=3, mask=None): """Fits a Chebyshev poly to y(x) and returns fitted y-values""" fitter = fitting.LinearLSQFitter() p_init = models.Chebyshev1D(npoly, domain=[x.min(), x.max()]) if mask is None: mask = np.ones_like(x).astype(bool) p = fitter(p_init, x[mask], y[mask]) print(p) return p(x)
def _trim_oscan(ccd, biassec, trimsec, model=None): """Subtract the overscan region and trim image to desired size. The CCDPROC function subtract_overscan() expects the TRIMSEC of the image (the part you want to keep) to span the entirety of one dimension, with the BIASSEC (overscan section) being at the end of the other dimension. Both LMI and DeVeny have edge effects on all sides of their respective chips, and so the TRIMSEC and BIASSEC do not meet the expectations of subtract_overscan(). Therefore, this function is a wrapper to first remove the undesired ROWS from top and bottom, then perform the subtract_overscan() fitting and subtraction, followed by trimming off the now-spent overscan region. Args: ccd (:TYPE:`internal link or datatype`) Description. biassec (:TYPE:`str`) Description. trimsec (:TYPE:`str`) Description. model (:TYPE:internal link or datatype`) Description. Returns: ccd (:TYPE:`internal link or datatype`) Description. """ # Convert the FITS bias & trim sections into slice classes for use yb, xb = slice_from_string(biassec, fits_convention=True) yt, xt = slice_from_string(trimsec, fits_convention=True) # First trim off the top & bottom rows ccd = ccdp.trim_image(ccd[yt.start:yt.stop, :]) # Model & Subtract the overscan if model is None: model = models.Chebyshev1D(1) # Chebyshev 1st order function else: model = models.Chebyshev1D(1) # Figure out how to incorporate others ccd = ccdp.subtract_overscan(ccd, overscan=ccd[:, xb.start:xb.stop], median=True, model=model) # Trim the overscan & return return ccdp.trim_image(ccd[:, xt.start:xt.stop])
def test_iraf_non_linear_chebyshev(remote_data_path): chebyshev_model = models.Chebyshev1D(degree=2, domain=[1616, 3259]) chebyshev_model.c0.value = 5115.64008186 chebyshev_model.c1.value = 535.515983712 chebyshev_model.c2.value = -0.779265625182 wavelength_axis = chebyshev_model(range(1, 4097)) * u.angstrom spectrum_1d = Spectrum1D.read(remote_data_path, format='iraf') assert isinstance(spectrum_1d, Spectrum1D) assert_allclose(wavelength_axis, spectrum_1d.wavelength)
def get_flattend(a0v_spec, a0v_wvl, a0v_tel_trans_masked, wvl_solutions, s_list, i1i2_list=None): a0v_flattened = [] if i1i2_list is None: i1i2_list = [[0, -1]] * len(wvl_solutions) a0v_interp1d = a0v_spec.get_flux_interp1d(a0v_wvl[0], a0v_wvl[-1], flatten=True, smooth_pixel=32) for wvl, s, (i1, i2) in zip(wvl_solutions, s_list, i1i2_list): wvl1, wvl2 = wvl[i1], wvl[i2] z_m = (wvl1 < a0v_wvl) & (a0v_wvl < wvl2) ss = interp1d(wvl, s) x_s = a0v_wvl[z_m] if len(x_s): s_interped = ss(x_s) xxx, yyy = a0v_wvl[z_m], s_interped/a0v_tel_trans_masked[z_m] p_init = models.Chebyshev1D(domain=[wvl1, wvl2], degree=6) fit_p = fitting.LinearLSQFitter() x_m = np.isfinite(yyy) p = fit_p(p_init, xxx[x_m], yyy[x_m]) res_ = p(wvl) s_f = s/res_ # now divide by A0V a0v = a0v_interp1d(wvl) s_f = s_f/a0v z_m = (wvl1 < wvl) & (wvl < wvl2) s_f[~z_m] = np.nan else: s_f = s / np.nanmax(s) a0v_flattened.append(s_f) return a0v_flattened
def chebyshev(self): """Returns a chebyshev model""" # TODO (simon): convert it to a staticmethod thus making it usable for # TODO (cont): external usage cheb = models.Chebyshev1D( degree=self.wcs['order'], domain=[self.wcs['pmin'], self.wcs['pmax']], ) for param_index in range(self.wcs['order']): cheb.parameters[param_index] = self.wcs['fpar'][param_index] return cheb
def model_constructor(self): """Generates callable mathematical model It can do chebyshev and linear model only but is easy to implement others. Chebyshev 3rd degree is by default since provided the best results for Goodman data. """ if self.model_name == 'chebyshev': self.model = models.Chebyshev1D(degree=self.degree) self.model_fit = fitting.LevMarLSQFitter() elif self.model_name == 'linear': self.model = models.Linear1D() self.model_fit = fitting.LinearLSQFitter()
def test_linear_fitter_1dcheb(self): """1 pset, 1 set 1D x, 1 set 1D y, Chebyshev 1D polynomial""" expected = np.array([[ 2817.2499999999995, 4226.6249999999991, 1680.7500000000009, 273.37499999999926 ]]).T ch1 = models.Chebyshev1D(3) ch1.parameters = [0, 1, 2, 3] y1 = ch1(self.x1) pfit = fitting.LinearLSQFitter() model = pfit(ch1, self.x1, y1) assert_allclose(model.param_sets, expected, atol=10**(-2))
def test_spectrum_from_model(): """ This test fits the the first simulated spectrum from the fixture. The initial guesses are manually set here with bounds that essentially make sense as the functionality of the test is to make sure the fit works and we get a reasonable answer out **given** good initial guesses. """ np.random.seed(0) x = np.linspace(0., 10., 200) y = 3 * np.exp(-0.5 * (x - 6.3)**2 / 0.1**2) y += np.random.normal(0., 0.2, x.shape) y_continuum = 3.2 * np.exp(-0.5 * (x - 5.6)**2 / 4.8**2) y += y_continuum spectrum = Spectrum1D(flux=y * u.Jy, spectral_axis=x * u.um) # Unitless test chebyshev = models.Chebyshev1D(3, c0=0.1, c1=4, c2=5) spectrum_chebyshev = spectrum_from_model(chebyshev, spectrum) flux_expected = np.array([ -4.90000000e+00, -3.64760991e-01, 9.22085553e+00, 2.38568496e+01, 4.35432211e+01, 6.82799702e+01, 9.80670968e+01, 1.32904601e+02, 1.72792483e+02, 2.17730742e+02, 2.67719378e+02, 3.22758392e+02, 3.82847784e+02, 4.47987553e+02, 5.18177700e+02, 5.93418224e+02, 6.73709126e+02, 7.59050405e+02, 8.49442062e+02, 9.44884096e+02 ]) assert np.allclose(spectrum_chebyshev.flux.value[::10], flux_expected, atol=1e-5) # Unitfull test gaussian = models.Gaussian1D(amplitude=5 * u.Jy, mean=4 * u.um, stddev=2.3 * u.um) spectrum_gaussian = spectrum_from_model(gaussian, spectrum) flux_expected = np.array([ 1.1020263, 1.57342489, 2.14175093, 2.77946243, 3.4389158, 4.05649712, 4.56194132, 4.89121902, 4.99980906, 4.872576, 4.52723165, 4.01028933, 3.3867847, 2.72689468, 2.09323522, 1.5319218, 1.06886794, 0.71101768, 0.45092638, 0.27264641 ]) assert np.allclose(spectrum_gaussian.flux.value[::10], flux_expected, atol=1e-5)
def dict_to_chebyshev(model_dict): """ This is the inverse of chebyshev_to_dict(), taking a dict of property/ parameter names and their values and making a ChebyshevND model instance. Parameters ---------- model_dict: dict Dictionary with pair/value that defines the Chebyshev model. Returns ------- models.ChebyshevND or None Returns the models if it is parsed successfully. If not, it will return None. Examples -------- .. code-block:: python my_model = dict( zip( ad[0].WAVECAL['name'], ad[0].WAVECAL['coefficient'] ) ) """ try: ndim = int(model_dict.pop('ndim')) if ndim == 1: model = models.Chebyshev1D(degree=int(model_dict.pop('degree'))) elif ndim == 2: model = models.Chebyshev2D(x_degree=int(model_dict.pop('x_degree')), y_degree=int(model_dict.pop('y_degree'))) else: return None except KeyError: return None for k, v in model_dict.items(): try: if k.endswith('domain_start'): setattr(model, k.replace('_start', ''), [v, model_dict[k.replace('start', 'end')]]) elif k and not k.endswith('domain_end'): # ignore k=="" setattr(model, k, v) except (KeyError, AttributeError): return None return model
def _model_constructor(self): """Generates callable mathematical model It can do Chebyshev and Linear model only but is easy to implement others. Chebyshev 3rd degree is by default since provided the best results for Goodman data. """ if self.model_name == 'chebyshev': self.model = models.Chebyshev1D(degree=self.degree) self.model_fitter = fitting.LevMarLSQFitter() elif self.model_name == 'linear': self.model = models.Linear1D() self.model_fitter = fitting.LinearLSQFitter() else: raise NotImplementedError("The model {:s} is " "not implemented".format(self.model_name))
def test_slit_illum_correct_different_roi(change_working_dir, input_data, request): ad, slit_illum_ad = input_data assert ad.detector_roi_setting() != slit_illum_ad.detector_roi_setting() p = GMOSLongslit([ad]) ad_out = p.slitIllumCorrect(slit_illum=slit_illum_ad)[0] for ext_out in ad_out: # Create output data data_o = np.ma.masked_array(ext_out.data, mask=ext_out.mask) # Bin columns n_rows = data_o.shape[0] fitter = fitting.LevMarLSQFitter() model = models.Chebyshev1D(c0=0.5 * n_rows, degree=2, domain=(0, n_rows)) model.c0.fixed = True nbins = 10 rows = np.arange(n_rows) for i in range(nbins): col_start = i * data_o.shape[1] // nbins col_end = (i + 1) * data_o.shape[1] // nbins cols = np.ma.mean(data_o[:, col_start:col_end], axis=1) fitted_model = fitter(model, rows, cols) # Check column is linear np.testing.assert_allclose(fitted_model.c2.value, 0, atol=0.001) # Check if slope is (almost) horizontal (< 2.5 deg) slope_angle = np.rad2deg( np.arctan(fitted_model.c1.value / (rows.size // 2))) assert np.abs(slope_angle) <= 1.0 if request.config.getoption("--do-plots"): plot_slit_illum_correct_results(ad, ad_out, fname="test_different_roi_")
def _create_fake_data(object_name): from astropy.table import Table astrofaker = pytest.importorskip('astrofaker') wavelength, flux = _get_spectrophotometric_data(object_name) wavecal = { 'degree': 1, 'domain': [0., wavelength.size - 1], 'c0': wavelength.mean(), 'c1': wavelength.mean() / 2, } wave_model = models.Chebyshev1D(**wavecal) wave_model.inverse = astromodels.make_inverse_chebyshev1d( wave_model, rms=0.01, max_deviation=0.03) hdu = fits.ImageHDU() hdu.header['CCDSUM'] = "1 1" hdu.data = flux[np.newaxis, :] # astrofaker needs 2D data _ad = astrofaker.create('GMOS-S') _ad.add_extension(hdu, pixel_scale=1.0) _ad[0].data = _ad[0].data.ravel() _ad[0].mask = np.zeros(_ad[0].data.size, dtype=np.uint16) # ToDo Requires mask _ad[0].variance = np.ones_like(_ad[0].data) # ToDo Requires Variance in_frame = cf.CoordinateFrame(naxes=1, axes_type=['SPATIAL'], axes_order=(0, ), unit=u.pix, axes_names=('x', ), name='pixels') out_frame = cf.SpectralFrame(unit=u.nm, name='world') _ad[0].wcs = gWCS([(in_frame, wave_model), (out_frame, None)]) _ad[0].hdr.set('NAXIS', 1) _ad[0].phu.set('OBJECT', object_name) _ad[0].phu.set('EXPTIME', 1.) _ad[0].hdr.set('BUNIT', "electron") assert _ad.object() == object_name assert _ad.exposure_time() == 1 return _ad
def getmod(self): """ Return model for current attributes """ if self.type == 'poly': mod = models.Polynomial1D(degree=self.degree) elif self.type == 'chebyshev': mod = models.Chebyshev1D(degree=self.degree) elif self.type == 'chebyshev2D': sz = self.spectrum.data.shape mod = models.Chebyshev2D(x_degree=self.degree, y_degree=self.ydegree, x_domain=[0, sz[1]], y_domain=[0, sz[0]]) else: raise ValueError('unknown fitting type: ' + self.type) return return mod
def get_order_flat1d(s, i1=None, i2=None): if i1 is None: i1 = 0 if i2 is None: i2 = len(s) x = np.arange(len(s)) if 0: from astropy.modeling import models, fitting p_init = models.Chebyshev1D(degree=6, window=[0, 2047]) fit_p = fitting.LinearLSQFitter() p = fit_p(p_init, x[i1:i2][mmm[i1:i2]], s[i1:i2][mmm[i1:i2]]) if 1: # t= np.linspace(x[i1]+10, x[i2-1]-10, 10) # p = LSQUnivariateSpline(x[i1:i2], # s[i1:i2], # t, bbox=[0, 2047]) # t= np.concatenate([[x[1],x[i1-5],x[i1],x[i1+5]], # np.linspace(x[i1]+10, x[i2-1]-10, 10), # [x[i2-5], x[i2], x[i2+5],x[-2]]]) t_list = [] if i1 > 10: t_list.append([x[1], x[i1]]) else: t_list.append([x[1]]) t_list.append(np.linspace(x[i1] + 10, x[i2 - 1] - 10, 10)) if i2 < len(s) - 10: t_list.append([x[i2], x[-2]]) else: t_list.append([x[-2]]) t = np.concatenate(t_list) # s0 = ni.median_filter(s, 40) from scipy.interpolate import LSQUnivariateSpline p = LSQUnivariateSpline(x, s, t, bbox=[0, len(s) - 1]) return p
def fit2d(self, deg=(6,3)): for i, p in enumerate(self.model.param_names): if self.ord_len == 1: cheb = models.Chebyshev1D(deg[0]) else: cheb = models.Chebyshev2D(deg[0], deg[1]) fit = fitting.LinearLSQFitter() chebfit = fit(cheb, self.x_step, self.ord_step, self.val_step[:, i]) self.val_full[:, i] = chebfit(self.x_full, self.ord_full) #print chebfit.__dict__#fit_info #print chebfit.c0_0 # print chebfit.coeffs # print chebfit._parameters # prova = chebfit.evaluate(self.x_full, self.ord_full, chebfit._parameters) if self.plots: plt.scatter(self.x_step, self.val_step[:, i], s=2) plt.scatter(self.x_full, self.val_full[:, i], s=2) # plt.scatter(self.x_full, prova, s=2) plt.show()
def fake_point_source_spatial_profile(height, width, model_parameters, fwhm=5): """ Generates a 2D array with a fake point source with constant intensity in the spectral dimension and a gaussian distribution in the spatial dimension. The center of the gaussian changes depends on the Chebyshev1D model defined by the input parameters. Parameters ---------- height : int Output 2D array's number of rows. width : int Output 2D array's number of columns. model_parameters : dict Model parameters with keys defined as 'c0', 'c1', ..., 'c{n-1}', where 'n' is the Chebyshev1D order. fwhm : float Full-width at half-maximum of the gaussian profile. Returns ------- np.ndarray 2D array with a fake point source """ order = len(model_parameters) + 1 trace_model = models.Chebyshev1D( order, domain=[0, width - 1], **model_parameters) x = np.arange(width) y = trace_model(x) n = y.size gaussian_model = models.Gaussian1D( mean=y, amplitude=[1] * n, stddev=[fwhm / (2. * np.sqrt(2 * np.log(2)))] * n, n_models=n ) source = gaussian_model(np.arange(height), model_set_axis=False).T return source
def test_chebyshev1D(self): """Tests fitting a 1D Chebyshev polynomial to some real world data.""" test_file = get_pkg_data_filename( os.path.join('data', 'idcompspec.fits')) with open(test_file) as f: lines = f.read() reclist = lines.split('begin') record = irafutil.IdentifyRecord(reclist[1]) coeffs = record.coeff order = int(record.fields['order']) initial_model = models.Chebyshev1D(order - 1, domain=record.get_range()) fitter = LinearLSQFitter() fitted_model = fitter(initial_model, record.x, record.z) assert_allclose(fitted_model.parameters, np.array(coeffs), rtol=10e-2)
def smhm_tinker(logMstar,redshift,h=0.7): """Calculate Tinker halo masses for given stellar masses. This fit was done to Figure 10 of Tinker+ (2017) uses and assumed log M* = 0.18 dex. Below log M*=10.9 we match the power-law index from Velander+ (2014). Defaults to h=0.7. """ import numpy as np from astropy.modeling import models # Tinker fit. This fit was done to Figure 10 of Tinker+ (2017) uses # an assumed log M* = 0.18 dex. Below log M*=10.9, we match the power-law # index from Velander+ (2014). tinker_smhm_fit = models.Chebyshev1D(5, c0=12.81806600627276, c1=1.2018634412571902, c2=0.013199452285390979, c3=0.01775015568831073, c4=-0.029254096888480078, c5=-0.025509308396318747, domain=[10.3, 12.19191]) ######################### # If only one redshift, duplicate it. num_gals = np.size(logMstar) if (num_gals != 1) & (np.size(redshift) == 1): zzz = np.full_like(logMstar,redshift) else: zzz = redshift # Calculate halo masses with the Tinker fit. The h^-1 correction # is applied here following the discussion in their paper. logMhalo = np.array(tinker_smhm_fit(logMstar))-np.log10(h) # For stellar masses outside of the fit domain, replace masses with NaN bad = ((logMstar <= np.min(tinker_smhm_fit.domain)) | (logMstar >= np.max(tinker_smhm_fit.domain))) logMhalo[bad] = np.nan # Return a numpy array: logMhalo = np.array(logMhalo) return logMhalo