From 2473a03ae049d5fce0ff3abf2db9acf03df5c6d6 Mon Sep 17 00:00:00 2001 From: Miguel Verdugo Date: Thu, 7 Apr 2022 17:11:35 +0200 Subject: [PATCH] point_source function to be used with an arbitrary spectra, other minor changes --- scopesim_templates/calibration/calibration.py | 16 +++---- scopesim_templates/misc/misc.py | 43 ++++++++++++++++--- scopesim_templates/stellar/stars.py | 3 ++ .../tests/test_misc/test_misc.py | 28 +++++++++++- 4 files changed, 72 insertions(+), 18 deletions(-) diff --git a/scopesim_templates/calibration/calibration.py b/scopesim_templates/calibration/calibration.py index 02168fa..96ee2f7 100644 --- a/scopesim_templates/calibration/calibration.py +++ b/scopesim_templates/calibration/calibration.py @@ -1,9 +1,12 @@ import numpy as np from astropy import units as u from astropy.io import fits + +from spextra import Spextrum + from scopesim_templates.rc import Source, __config__ from scopesim_templates.utils.general_utils import function_call_str, make_img_wcs_header -from spextra import Spextrum +from ..misc.misc import uniform_source def flat_field(temperature=5000, amplitude=0*u.ABmag, filter_curve="V", extend=60): @@ -35,18 +38,11 @@ def flat_field(temperature=5000, amplitude=0*u.ABmag, filter_curve="V", extend=6 """ sp = Spextrum.black_body_spectrum(temperature=temperature, amplitude=amplitude, filter_curve=filter_curve) - - if isinstance(amplitude, u.Quantity) is False: - amplitude = amplitude * u.ABmag - - data = np.ones(shape=(extend, extend)) - header = make_img_wcs_header(ra=0, dec=0, pixel_scale=1, image_size=data.shape) - hdu = fits.ImageHDU(header=header, data=data) - - src = Source(spectra=sp, image_hdu=hdu) + src = uniform_source(sed=sp, amplitude=amplitude, filter_curve=filter_curve, extend=extend) return src + def empty_sky(): """ Returns an empty source so that instrumental fluxes can be simulated diff --git a/scopesim_templates/misc/misc.py b/scopesim_templates/misc/misc.py index 17eb19d..a81cd97 100644 --- a/scopesim_templates/misc/misc.py +++ b/scopesim_templates/misc/misc.py @@ -6,6 +6,7 @@ from astropy import units as u from astropy.wcs import WCS from astropy.utils.decorators import deprecated_renamed_argument +from astropy.table import Table from synphot import SourceSpectrum, Empirical1D @@ -14,25 +15,51 @@ from ..utils import general_utils as gu -def homogeneous_source(sed, amplitude=15, filter_curve="V", extend=60, ra=gu.RA0, dec=gu.DEC0): +def point_source(sed, amplitude=None, filter_curve="V", x=0, y=0, ra=gu.RA0, dec=gu.DEC0): + + if (isinstance(amplitude, u.Quantity)) is False and amplitude is not None: + amplitude = amplitude * u.ABmag + if isinstance(sed, str): + sp = Spextrum(sed) + scaled_sp = sp.scale_to_magnitude(amplitude=amplitude, filter_curve=filter_curve) + elif isinstance(sed, (Spextrum, SourceSpectrum)): + sp = Spextrum(modelclass=sed) + if amplitude is None: + scaled_sp = sp + else: + scaled_sp = sp.scale_to_magnitude(amplitude=amplitude, filter_curve=filter_curve) + + src = Source(spectra=scaled_sp, x=[x], y=[y], ref=[0], weight=[1]) + return src + + +def uniform_source(sed, amplitude=None, filter_curve="V", extend=60, ra=gu.RA0, dec=gu.DEC0): """ - Creates a homogeneous source with an arbitrary spectrum + Creates a extended uniform source with an arbitrary spectrum sed : synphot or spextra sed - amplitude : magnitude or flux of the spectrum in the filter_curve + amplitude : magnitude or flux (PER ARCSEC^2) of the spectrum in the specified filter_curve filter_curve : any filter curve + extend : int + extension of the field in arcsec, will always produce an square field + ra : RA + dec : DEC """ - if isinstance(amplitude, u.Quantity) is False: + if (isinstance(amplitude, u.Quantity)) is False and amplitude is not None: amplitude = amplitude * u.ABmag if isinstance(sed, str): sp = Spextrum(sed) scaled_sp = sp.scale_to_magnitude(amplitude=amplitude, filter_curve=filter_curve) elif isinstance(sed, (Spextrum, SourceSpectrum)): sp = Spextrum(modelclass=sed) - scaled_sp = sp.scale_to_magnitude(amplitude=amplitude, filter_curve=filter_curve) + if amplitude is None: + scaled_sp = sp + else: + scaled_sp = sp.scale_to_magnitude(amplitude=amplitude, filter_curve=filter_curve) data = np.ones(shape=(extend, extend)) - header = gu.make_img_wcs_header(ra=ra, dec=ra, pixel_scale=1, image_size=data.shape) + + header = gu.make_img_wcs_header(ra=ra, dec=dec, pixel_scale=1, image_size=data.shape) hdu = fits.ImageHDU(header=header, data=data) src = Source(spectra=scaled_sp, image_hdu=hdu) @@ -40,7 +67,7 @@ def homogeneous_source(sed, amplitude=15, filter_curve="V", extend=60, ra=gu.RA0 return src -def source_from_imagehdu(image_hdu, filter_name, pixel_unit_amplitude=None, +def source_from_imagehdu(image_hdu, filter_name, pixel_unit_amplitude=None, waverange=None, inst_pkg_path=None): """ Creates a scopesim.Source object directly from an fits.ImageHDU @@ -50,6 +77,8 @@ def source_from_imagehdu(image_hdu, filter_name, pixel_unit_amplitude=None, image_hdu : fits.ImageHDU filter_name : str Either a standard filter name or a filter from an instrument package + waverange: tuple + wave_min and wave_max of the spectral range pixel_unit_amplitude, optional A Quantity that corresponds to a pixel value of 1 in the image If not given, header keyword BUNIT is used diff --git a/scopesim_templates/stellar/stars.py b/scopesim_templates/stellar/stars.py index 9acfdc2..d1cf621 100644 --- a/scopesim_templates/stellar/stars.py +++ b/scopesim_templates/stellar/stars.py @@ -151,6 +151,9 @@ def stars(filter_name, amplitudes, spec_types, x, y, library="pyckles", ra=RA0, the spectral type(s) of the stars, e.g. "A0V", "G5III" x, y : arrays of float [arcsec] x and y coordinates of the stars on the focal plane + ra, dec : float + coordinates of the center of the field + library: str Library where the spectroscopic types are taken. By default are taken from the pickles library using diff --git a/scopesim_templates/tests/test_misc/test_misc.py b/scopesim_templates/tests/test_misc/test_misc.py index 048218d..0a8d615 100644 --- a/scopesim_templates/tests/test_misc/test_misc.py +++ b/scopesim_templates/tests/test_misc/test_misc.py @@ -1,5 +1,6 @@ from os.path import exists import pytest +import synphot from pytest import raises from astropy import units as u from astropy.io import fits @@ -51,6 +52,30 @@ def test_is_happy_with_metis_filter_and_bunit(self): assert isinstance(src, Source) +class TestPointSource: + def test_initialize_from_spextra(self): + src = misc.point_source("pickles/a0v", amplitude=16) + + assert isinstance(src, Source) + + def test_initialize_from_synphot(self): + sp = synphot.SourceSpectrum(synphot.Empirical1D, points=[1000, 10000], lookup_table=[1, 1]) + src = misc.point_source(sed=sp) + assert isinstance(src, Source) + + +class TestUniformSource: + def test_initialize_from_spextra(self): + src = misc.uniform_source("pickles/a0v", amplitude=16) + + assert isinstance(src, Source) + + def test_initialize_from_synphot(self): + sp = synphot.SourceSpectrum(synphot.Empirical1D, points=[1000, 10000], lookup_table=[1, 1]) + src = misc.uniform_source(sed=sp) + assert isinstance(src, Source) + + def test_poorman_cube_source_is_working(): cube = so._make_dummy_cube(scale=0.2, wave_unit=u.AA, ref_wave=5000, wave_step=1, wave_type="WAVE", bunit="erg / (s cm2 Angstrom)") @@ -58,4 +83,5 @@ def test_poorman_cube_source_is_working(): hdul = fits.HDUList(cube) cube_source = misc.poorman_cube_source(hdu=hdul, ext=0) - assert isinstance(cube_source, Source) \ No newline at end of file + assert isinstance(cube_source, Source) +