def test_raise(self): with self.assertRaises(ValueError): # try to set decomposition scale to higher than maximal value starlets = SLIT_Starlets(force_no_pysap=True) # define a test image with gaussian components num_pix = 50 x, y = util.make_grid(num_pix, 1) # build a non-trivial positive image from sum of gaussians gaussian = Gaussian() gaussian1 = gaussian.function(x, y, amp=100, sigma=1, center_x=-7, center_y=-7) gaussian2 = gaussian.function(x, y, amp=500, sigma=3, center_x=-3, center_y=-3) gaussian3 = gaussian.function(x, y, amp=2000, sigma=5, center_x=+5, center_y=+5) test_image = util.array2image(gaussian1 + gaussian2 + gaussian3) n_scales = 100 _ = starlets.decomposition_2d(test_image, n_scales) with self.assertRaises(ValueError): # try to set decomposition scale to negative value starlets = SLIT_Starlets(force_no_pysap=True) # define a test image with gaussian components num_pix = 50 x, y = util.make_grid(num_pix, 1) # build a non-trivial positive image from sum of gaussians gaussian = Gaussian() gaussian1 = gaussian.function(x, y, amp=100, sigma=1, center_x=-7, center_y=-7) gaussian2 = gaussian.function(x, y, amp=500, sigma=3, center_x=-3, center_y=-3) gaussian3 = gaussian.function(x, y, amp=2000, sigma=5, center_x=+5, center_y=+5) test_image = util.array2image(gaussian1 + gaussian2 + gaussian3) n_scales = -1 _ = starlets.decomposition_2d(test_image, n_scales) with self.assertRaises(ValueError): # function_split is not supported/defined for pixel-based profiles light_model = LightModel(['SLIT_STARLETS']) num_pix = 20 x, y = util.make_grid(num_pix, 1) kwargs_list = [{ 'amp': np.ones((3, num_pix, num_pix)), 'n_scales': 3, 'n_pixels': 20**2, 'center_x': 0, 'center_y': 0, 'scale': 1 }] _ = light_model.functions_split(x, y, kwargs_list) with self.assertRaises(ValueError): # provided a wrong shape for starlet coefficients starlet_class = SLIT_Starlets() num_pix = 20 x, y = util.make_grid(num_pix, 1) coeffs_wrong = np.ones((3, num_pix**2)) kwargs_list = { 'amp': coeffs_wrong, 'n_scales': 3, 'n_pixels': 20**2, 'center_x': 0, 'center_y': 0, 'scale': 1 } _ = starlet_class.function(x, y, **kwargs_list) image_wrong = np.ones((1, num_pix, num_pix)) _ = starlet_class.decomposition(image_wrong, 3) with self.assertRaises(ValueError): # provided a wrong shape for image to be decomposed starlet_class = SLIT_Starlets() num_pix = 20 image_wrong = np.ones((2, num_pix, num_pix)) _ = starlet_class.decomposition(image_wrong, 3)
def __init__(self, light_model_list, smoothing=0.001, sersic_major_axis=None): """ :param light_model_list: list of light models :param smoothing: smoothing factor for certain models (deprecated) :param sersic_major_axis: boolean or None, if True, uses the semi-major axis as the definition of the Sersic half-light radius, if False, uses the product average of semi-major and semi-minor axis. If None, uses the convention in the lenstronomy yaml setting (which by default is =False) """ self.profile_type_list = light_model_list self.func_list = [] if sersic_major_axis is None: sersic_major_axis = sersic_major_axis_conf for profile_type in light_model_list: if profile_type == 'GAUSSIAN': from lenstronomy.LightModel.Profiles.gaussian import Gaussian self.func_list.append(Gaussian()) elif profile_type == 'GAUSSIAN_ELLIPSE': from lenstronomy.LightModel.Profiles.gaussian import GaussianEllipse self.func_list.append(GaussianEllipse()) elif profile_type == 'ELLIPSOID': from lenstronomy.LightModel.Profiles.ellipsoid import Ellipsoid self.func_list.append(Ellipsoid()) elif profile_type == 'MULTI_GAUSSIAN': from lenstronomy.LightModel.Profiles.gaussian import MultiGaussian self.func_list.append(MultiGaussian()) elif profile_type == 'MULTI_GAUSSIAN_ELLIPSE': from lenstronomy.LightModel.Profiles.gaussian import MultiGaussianEllipse self.func_list.append(MultiGaussianEllipse()) elif profile_type == 'SERSIC': from lenstronomy.LightModel.Profiles.sersic import Sersic self.func_list.append(Sersic(smoothing=smoothing)) elif profile_type == 'SERSIC_ELLIPSE': from lenstronomy.LightModel.Profiles.sersic import SersicElliptic self.func_list.append( SersicElliptic(smoothing=smoothing, sersic_major_axis=sersic_major_axis)) elif profile_type == 'CORE_SERSIC': from lenstronomy.LightModel.Profiles.sersic import CoreSersic self.func_list.append( CoreSersic(smoothing=smoothing, sersic_major_axis=sersic_major_axis)) elif profile_type == 'SHAPELETS': from lenstronomy.LightModel.Profiles.shapelets import ShapeletSet self.func_list.append(ShapeletSet()) elif profile_type == 'SHAPELETS_POLAR': from lenstronomy.LightModel.Profiles.shapelets_polar import ShapeletSetPolar self.func_list.append(ShapeletSetPolar(exponential=False)) elif profile_type == 'SHAPELETS_POLAR_EXP': from lenstronomy.LightModel.Profiles.shapelets_polar import ShapeletSetPolar self.func_list.append(ShapeletSetPolar(exponential=True)) elif profile_type == 'HERNQUIST': from lenstronomy.LightModel.Profiles.hernquist import Hernquist self.func_list.append(Hernquist()) elif profile_type == 'HERNQUIST_ELLIPSE': from lenstronomy.LightModel.Profiles.hernquist import HernquistEllipse self.func_list.append(HernquistEllipse()) elif profile_type == 'PJAFFE': from lenstronomy.LightModel.Profiles.p_jaffe import PJaffe self.func_list.append(PJaffe()) elif profile_type == 'PJAFFE_ELLIPSE': from lenstronomy.LightModel.Profiles.p_jaffe import PJaffeEllipse self.func_list.append(PJaffeEllipse()) elif profile_type == 'UNIFORM': from lenstronomy.LightModel.Profiles.uniform import Uniform self.func_list.append(Uniform()) elif profile_type == 'POWER_LAW': from lenstronomy.LightModel.Profiles.power_law import PowerLaw self.func_list.append(PowerLaw()) elif profile_type == 'NIE': from lenstronomy.LightModel.Profiles.nie import NIE self.func_list.append(NIE()) elif profile_type == 'CHAMELEON': from lenstronomy.LightModel.Profiles.chameleon import Chameleon self.func_list.append(Chameleon()) elif profile_type == 'DOUBLE_CHAMELEON': from lenstronomy.LightModel.Profiles.chameleon import DoubleChameleon self.func_list.append(DoubleChameleon()) elif profile_type == 'TRIPLE_CHAMELEON': from lenstronomy.LightModel.Profiles.chameleon import TripleChameleon self.func_list.append(TripleChameleon()) elif profile_type == 'INTERPOL': from lenstronomy.LightModel.Profiles.interpolation import Interpol self.func_list.append(Interpol()) elif profile_type == 'SLIT_STARLETS': from lenstronomy.LightModel.Profiles.starlets import SLIT_Starlets self.func_list.append( SLIT_Starlets(fast_inverse=True, second_gen=False)) elif profile_type == 'SLIT_STARLETS_GEN2': from lenstronomy.LightModel.Profiles.starlets import SLIT_Starlets self.func_list.append(SLIT_Starlets(second_gen=True)) else: raise ValueError( 'No light model of type %s found! Supported are the following models: %s' % (profile_type, _MODELS_SUPPORTED)) self._num_func = len(self.func_list)
class TestSLITStarlets(object): """ class to test SLIT_Starlets light profile """ def setup(self): # different versions of Starlet transforms self.starlets = SLIT_Starlets(fast_inverse=False, second_gen=False, force_no_pysap=_force_no_pysap) self.starlets_fast = SLIT_Starlets(fast_inverse=True, second_gen=False, force_no_pysap=_force_no_pysap) self.starlets_2nd = SLIT_Starlets(second_gen=True, force_no_pysap=_force_no_pysap) # define a test image with gaussian components self.num_pix = 50 self.n_scales = 3 self.n_pixels = self.num_pix**2 self.x, self.y = util.make_grid(self.num_pix, 1) # build a non-trivial positive image from sum of gaussians gaussian = Gaussian() gaussian1 = gaussian.function(self.x, self.y, amp=100, sigma=1, center_x=-7, center_y=-7) gaussian2 = gaussian.function(self.x, self.y, amp=500, sigma=3, center_x=-3, center_y=-3) gaussian3 = gaussian.function(self.x, self.y, amp=2000, sigma=5, center_x=+5, center_y=+5) self.test_image = util.array2image(gaussian1 + gaussian2 + gaussian3) self.test_coeffs = np.zeros( (self.n_scales, self.num_pix, self.num_pix)) self.test_coeffs[0, :, :] = util.array2image(gaussian1) self.test_coeffs[1, :, :] = util.array2image(gaussian2) self.test_coeffs[2, :, :] = util.array2image(gaussian3) def test_reconstructions_2d(self): """ :return: """ # PySAP requires call to decomposition once before anything else self.starlets.decomposition_2d(self.test_image, self.n_scales) self.starlets_fast.decomposition_2d(self.test_image, self.n_scales) self.starlets_2nd.decomposition_2d(self.test_image, self.n_scales) image = self.starlets.function_2d(coeffs=self.test_coeffs, n_scales=self.n_scales, n_pixels=self.n_pixels) image_fast = self.starlets_fast.function_2d(coeffs=self.test_coeffs, n_scales=self.n_scales, n_pixels=self.n_pixels) assert image.shape == (self.num_pix, self.num_pix) assert image_fast.shape == (self.num_pix, self.num_pix) image_2nd = self.starlets_2nd.function_2d(coeffs=self.test_coeffs, n_scales=self.n_scales, n_pixels=self.n_pixels) assert image_2nd.shape == (self.num_pix, self.num_pix) assert np.all(image_2nd >= 0) def test_decompositions_2d(self): """ :return: """ # test equality between fast and std transform (which are identical) coeffs = self.starlets.decomposition_2d(self.test_image, self.n_scales) coeffs_fast = self.starlets_fast.decomposition_2d( self.test_image, self.n_scales) assert coeffs.shape == (self.n_scales, self.num_pix, self.num_pix) assert coeffs_fast.shape == (self.n_scales, self.num_pix, self.num_pix) npt.assert_almost_equal(coeffs, coeffs_fast, decimal=3) # test non-negativity of second generation starlet transform coeffs_2nd = self.starlets_2nd.decomposition_2d( self.test_image, self.n_scales) assert coeffs_2nd.shape == (self.n_scales, self.num_pix, self.num_pix) def test_function(self): """ :return: """ # PySAP requires call to decomposition once before anything else self.starlets.decomposition(self.test_image, self.n_scales) self.starlets_fast.decomposition(self.test_image, self.n_scales) self.starlets_2nd.decomposition(self.test_image, self.n_scales) # test with a 1D input self.starlets.decomposition(util.image2array(self.test_image), self.n_scales) coeffs_1d = self.test_coeffs.reshape(self.n_scales * self.num_pix**2) image_1d = self.starlets.function(self.x, self.y, amp=coeffs_1d, n_scales=self.n_scales, n_pixels=self.n_pixels) assert image_1d.shape == (self.num_pix**2, ) image_1d_fast = self.starlets_fast.function(self.x, self.y, amp=coeffs_1d, n_scales=self.n_scales, n_pixels=self.n_pixels) assert image_1d_fast.shape == (self.num_pix**2, ) image_1d_2nd = self.starlets_2nd.function(self.x, self.y, amp=coeffs_1d, n_scales=self.n_scales, n_pixels=self.n_pixels) assert image_1d_2nd.shape == (self.num_pix**2, ) def test_identity_operations_fast(self): """ test the decomposition/reconstruction :return: """ coeffs = self.starlets_fast.decomposition_2d(self.test_image, self.n_scales) test_image_recon = self.starlets_fast.function_2d( coeffs=coeffs, n_scales=self.n_scales, n_pixels=self.n_pixels) npt.assert_almost_equal(self.test_image, test_image_recon, decimal=5) def test_identity_operations_2nd(self): """ test the decomposition/reconstruction :return: """ coeffs = self.starlets_2nd.decomposition_2d(self.test_image, self.n_scales) test_image_recon = self.starlets_2nd.function_2d( coeffs=coeffs, n_scales=self.n_scales, n_pixels=self.n_pixels) npt.assert_almost_equal(self.test_image, test_image_recon, decimal=5) def test_delete_cache(self): amp = self.test_coeffs.reshape(self.n_scales * self.num_pix**2) kwargs_starlets = dict(amp=amp, n_scales=self.n_scales, n_pixels=self.n_pixels, center_x=0, center_y=0, scale=1) output = self.starlets_fast.function(self.x, self.y, **kwargs_starlets) assert hasattr(self.starlets_fast.interpol, '_image_interp') self.starlets_fast.delete_cache() assert not hasattr(self.starlets_fast.interpol, '_image_interp') def test_coeffs2pysap(self): n_scales = 3 num_pix = 20 coeffs = np.ones((n_scales, num_pix, num_pix)) pysap_list = self.starlets._coeffs2pysap(coeffs) assert len(pysap_list) == n_scales for i in range(n_scales): assert pysap_list[i].shape == coeffs[i].shape def test_pysap2coeffs(self): n_scales = 3 num_pix = 20 pysap_list = n_scales * [np.ones((num_pix, num_pix))] coeffs = self.starlets._pysap2coeffs(pysap_list) assert coeffs.shape == (n_scales, num_pix, num_pix) for i in range(n_scales): assert pysap_list[i].shape == coeffs[i].shape