def test_bounds(): # Single subregion sr = SpectralRegion(0.45 * u.um, 0.6 * u.um) assert sr.bounds == (0.45 * u.um, 0.6 * u.um) # Multiple subregions sr = SpectralRegion([(0.8 * u.um, 0.9 * u.um), (0.3 * u.um, 1.0 * u.um), (0.45 * u.um, 0.6 * u.um), (0.04 * u.um, 0.05 * u.um)]) assert sr.bounds == (0.04 * u.um, 1.0 * u.um)
def test_adding_spectral_regions(): # Combine two Spectral regions into one: sr = (SpectralRegion(0.45 * u.um, 0.6 * u.um) + SpectralRegion(0.8 * u.um, 0.9 * u.um)) assert set(sr.subregions) == set([(0.45 * u.um, 0.6 * u.um), (0.8 * u.um, 0.9 * u.um)]) # In-place adding spectral regions: sr1 = SpectralRegion(0.45 * u.um, 0.6 * u.um) sr2 = SpectralRegion(0.8 * u.um, 0.9 * u.um) sr1 += sr2 assert set(sr1.subregions) == set([(0.45 * u.um, 0.6 * u.um), (0.8 * u.um, 0.9 * u.um)])
def test_delitem(): # Single subregion sr = SpectralRegion(0.45 * u.um, 0.6 * u.um) del sr[0] assert sr.subregions == [] # Multiple sub-regions sr = SpectralRegion([(0.8 * u.um, 0.9 * u.um), (0.3 * u.um, 1.0 * u.um), (0.45 * u.um, 0.6 * u.um), (0.04 * u.um, 0.05 * u.um)]) del sr[1] assert sr[0].subregions == [(0.04 * u.um, 0.05 * u.um)] assert sr[1].subregions == [(0.45 * u.um, 0.6 * u.um)] assert sr[2].subregions == [(0.8 * u.um, 0.9 * u.um)]
def test_getitem(): sr = SpectralRegion([(0.8 * u.um, 0.9 * u.um), (0.3 * u.um, 1.0 * u.um), (0.45 * u.um, 0.6 * u.um), (0.04 * u.um, 0.05 * u.um)]) assert sr[0].subregions == [(0.04 * u.um, 0.05 * u.um)] assert sr[1].subregions == [(0.3 * u.um, 1.0 * u.um)] assert sr[2].subregions == [(0.45 * u.um, 0.6 * u.um)] assert sr[3].subregions == [(0.8 * u.um, 0.9 * u.um)] assert sr[-1].subregions == [(0.8 * u.um, 0.9 * u.um)]
def test_iterate(): # Create the Spectral region subregions = [(0.8 * u.um, 0.9 * u.um), (0.3 * u.um, 1.0 * u.um), (0.45 * u.um, 0.6 * u.um), (0.04 * u.um, 0.05 * u.um)] sr = SpectralRegion(subregions) # For testing, sort our subregion list. subregions.sort(key=lambda k: k[0]) for ii, s in enumerate(sr): assert s.subregions[0] == subregions[ii]
def test_invert(): sr = (SpectralRegion(0.15 * u.um, 0.2 * u.um) + SpectralRegion(0.3 * u.um, 0.4 * u.um) + SpectralRegion(0.45 * u.um, 0.6 * u.um) + SpectralRegion(0.8 * u.um, 0.9 * u.um) + SpectralRegion(1.0 * u.um, 1.2 * u.um) + SpectralRegion(1.3 * u.um, 1.5 * u.um)) sr_inverted_expected = [ (0.05 * u.um, 0.15 * u.um), (0.2 * u.um, 0.3 * u.um), (0.4 * u.um, 0.45 * u.um), (0.6 * u.um, 0.8 * u.um), (0.9 * u.um, 1.0 * u.um), (1.2 * u.um, 1.3 * u.um), (1.5 * u.um, 3.0 * u.um) ] # Invert from range. sr_inverted = sr.invert(0.05 * u.um, 3 * u.um) for ii, expected in enumerate(sr_inverted_expected): assert sr_inverted.subregions[ii] == sr_inverted_expected[ii] # Invert from spectrum. spectrum = Spectrum1D(spectral_axis=np.linspace(0.05, 3, 20) * u.um, flux=np.random.random(20) * u.Jy) sr_inverted = sr.invert_from_spectrum(spectrum) for ii, expected in enumerate(sr_inverted_expected): assert sr_inverted.subregions[ii] == sr_inverted_expected[ii]
def test_lower_upper(): # Spectral region with just one range (lower and upper bound) sr = SpectralRegion(0.45 * u.um, 0.6 * u.um) assert sr.lower == 0.45 * u.um assert sr.upper == 0.6 * u.um # Spectral region with just two ranges sr = SpectralRegion([(0.45 * u.um, 0.6 * u.um), (0.8 * u.um, 0.9 * u.um)]) assert sr.lower == 0.45 * u.um assert sr.upper == 0.9 * u.um # Spectral region with multiple ranges and not ordered sr = SpectralRegion([(0.3 * u.um, 1.0 * u.um), (0.45 * u.um, 0.6 * u.um), (0.04 * u.um, 0.05 * u.um), (0.8 * u.um, 0.9 * u.um)]) assert sr.lower == 0.04 * u.um assert sr.upper == 1.0 * u.um # Get lower bound of a single sub-region: assert sr[0].lower == 0.04 * u.um assert sr[0].upper == 0.05 * u.um
def test_slicing(): sr = (SpectralRegion(0.15 * u.um, 0.2 * u.um) + SpectralRegion(0.3 * u.um, 0.4 * u.um) + SpectralRegion(0.45 * u.um, 0.6 * u.um) + SpectralRegion(0.8 * u.um, 0.9 * u.um) + SpectralRegion(1.0 * u.um, 1.2 * u.um) + SpectralRegion(1.3 * u.um, 1.5 * u.um)) subsr = sr[3:5] assert subsr[0].subregions == [(0.8 * u.um, 0.9 * u.um)] assert subsr[1].subregions == [(1.0 * u.um, 1.2 * u.um)]
def test_from_list_list(): g1 = Gaussian1D(1, 4.6, 0.2) g2 = Gaussian1D(2.5, 5.5, 0.1) g3 = Gaussian1D(-1.7, 8.2, 0.1) x = np.linspace(0, 10, 200) y = g1(x) + g2(x) + g3(x) spectrum = Spectrum1D(flux=y * u.Jy, spectral_axis=x * u.um) lines = find_lines_derivative(spectrum, flux_threshold=0.01) spec_reg = SpectralRegion.from_line_list(lines) expected = [(4.072864321608041 * u.um, 5.072864321608041 * u.um), (4.977386934673367 * u.um, 5.977386934673367 * u.um), (7.690954773869347 * u.um, 8.690954773869347 * u.um)] for i, reg in enumerate(expected): assert_quantity_allclose(reg, (spec_reg[i].lower, spec_reg[i].upper))
def load_spectral_regions(setting: str, detector: list, orders: list): # Spectral regions # from https://www.astro.uu.se/crireswiki/Instrument?action=AttachFile&do=view&target=crmcfgWLEN_20200223_extracted.csv fname = join(dirname(__file__), "crires_wlen_extracted.csv") data = pd.read_csv(fname, skiprows=[1]) detector = np.atleast_1d(detector) norders = [0 for _ in detector] if orders is None: orders = range(1, 11) idx = data["setting"] == setting regions = [] for order in orders: for i, det in enumerate(detector): if data[f"O{order} Central Wavelength"][idx].array[0] != -1: wmin = data[f"O{order} BEG DET{det}"][idx].array[0] * u.nm wmax = data[f"O{order} END DET{det}"][idx].array[0] * u.nm regions += [SpectralRegion(wmin, wmax)] norders[i] += 1 # regions = np.sum(regions) return regions, norders
def test_from_center_error(center, width): with pytest.raises(ValueError): SpectralRegion.from_center(center=center, width=width)
def test_from_center(center, width, lower, upper): # Spectral region from center with width sr = SpectralRegion.from_center(center=center, width=width) assert_quantity_allclose(sr.lower, lower) assert_quantity_allclose(sr.upper, upper)
def norm_spectrum(spec, median_window=3, order=3): ''' Normalize a spectrum Parameters: ----------- spec: specutils.Spectrum1D Spectrum to normalize median_window: int() Window in Pixel used in median smoothing order: int() Order of the polynomial used to find the continuum Returns: -------- norm_spec: specutils.Spectrum1D Normalized spectrum ''' # Regions that should not be used for continuum estimation, # such as broad atmospheric absorption bands exclude_regions = [ SpectralRegion(4295. * u.AA, 4315. * u.AA), #SpectralRegion(6860.* u.AA, 6880.* u.AA), SpectralRegion(6860. * u.AA, 6910. * u.AA), #SpectralRegion(7590.* u.AA, 7650.* u.AA), SpectralRegion(7590. * u.AA, 7680. * u.AA), SpectralRegion(9260. * u.AA, 9420. * u.AA), #SpectralRegion(11100.* u.AA, 11450.* u.AA), #SpectralRegion(13300.* u.AA, 14500.* u.AA), ] # First estimate of the continuum # -> will be two for late type stars because of the many absorption lines # -> to limit execution time use simple LinearLSQFitter() # -> reduces normalization accuracy _cont = fit_generic_continuum( spec, model=models.Chebyshev1D(order), fitter=fitting.LinearLSQFitter(), median_window=median_window, exclude_regions=exclude_regions, )(spec.spectral_axis) # Normalize spectrum norm_spec = spec / _cont # Sigma clip the normalized spectrum to rm spectral lines clip_flux = sigma_clip( norm_spec.flux, sigma_lower=1.25, sigma_upper=3., axis=0, grow=1., ) # Calculate mask mask = np.invert(clip_flux.recordmask) # Make new spectrum spec_mask = Spectrum1D( spectral_axis=spec.spectral_axis[mask], flux=spec.flux[mask], ) # Determine new continuum _cont = fit_generic_continuum( spec_mask, model=models.Chebyshev1D(order), fitter=fitting.LinearLSQFitter(), median_window=median_window, exclude_regions=exclude_regions, )(spec.spectral_axis) # Normalize spectrum again norm_spec = spec / _cont return norm_spec, mad_std(norm_spec.flux)
interactive_mode = False #trim spectrum mask = (wl > lamb1) & (wl < lamb2) wl = wl[mask] fl = fl[mask] spectrum = Spectrum1D(flux=fl * u.Jy, spectral_axis=wl * u.AA) # start end start end regions = [8489.0, 8563.0, 8642.0, 8697.0] if interactive_mode == False: g1_fit = fit_generic_continuum(spectrum, exclude_regions=[ SpectralRegion(regions[0] * u.AA, regions[1] * u.AA), SpectralRegion(regions[2] * u.AA, regions[3] * u.AA) ]) y_continuum_fitted = g1_fit(wl * u.AA) spec_normalized = spectrum / y_continuum_fitted print(FILENAME + 'was normalized automaticaly... \n') #add a spline with a selected dots #-------------------------------- if interactive_mode == True: f0 = plt.figure(figsize=(12, 7)) ax0 = f0.add_subplot(111)