def test_psf1d_model_show(): """What happens when the kernel is a model?""" box1 = make_1d_model() m = PSFModel("pmodel1", box1) dfold = Data1D('fold', np.arange(10), np.zeros(10)) m.fold(dfold) out = str(m).split("\n") assert len(out) == 8 assert out[0] == "pmodel1" assert out[ 1] == " Param Type Value Min Max Units" assert out[ 2] == " ----- ---- ----- --- --- -----" assert out[3] == " pmodel1.kernel frozen box1" assert out[ 4] == " pmodel1.size frozen 10 10 10" assert out[ 5] == " pmodel1.center frozen 5 5 5" assert out[ 6] == " pmodel1.radial frozen 0 0 1 " assert out[ 7] == " pmodel1.norm frozen 1 0 1 "
def test_psf1d_data_given_2d_dataset(): """Do we error out or not? This is a regression test. """ psf = PSFModel('psf', make_1d_data()) d = make_2d_data() # Does this error out? psf.fold(d) smdl = StepLo1D() smdl.xcut = 100 smdl.ampl = 10 cmdl = Const1D() cmdl.c0 = -500 imdl = smdl + cmdl # Or maybe this errors out? smoothed = psf(imdl) with pytest.raises(TypeError) as err: smoothed(np.arange(1, 7)) assert str( err.value ) == "input array sizes do not match, dims_src: 2 vs dims_kern: 1"
def test_psf1d_combined(): """This is based on sherpa.models.tests.test_regrid_unit.test_regrid1_works_with_convolution_style but I wanted to make sure we have an explicit check of the underlying code. """ smdl = StepLo1D() smdl.xcut = 12.5 smdl.ampl = 10 cmdl = Const1D() cmdl.c0 = -500 imdl = smdl + cmdl gsmooth = Gauss1D() gsmooth.fwhm = 3 psf = PSFModel('psf', gsmooth) x = np.arange(5, 23, 3) d = Data1D('fake', x, x * 0) psf.fold(d) smoothed = psf(imdl) y = smoothed(x) assert y == pytest.approx([-490, -490, -490, -500, -500, -500], rel=7e-3)
def test_psf1d_combined_v2(): """See test_psf1d_step_v2""" smdl = StepLo1D() smdl.xcut = 100 smdl.ampl = 10 cmdl = Const1D() cmdl.c0 = -500 imdl = smdl + cmdl gsmooth = Gauss1D() psf = PSFModel('psf', gsmooth) x = np.arange(0, 200, 0.5) d = Data1D('fake', x, x * 0) psf.fold(d) smoothed = psf(imdl) y = smoothed(x) # So the output is not easy to describe analytically, hence # we just check parts of it. # assert y[(x >= 19.5) & (x <= 100)] == pytest.approx([-490] * 162, abs=1e-4) assert y[x >= 119] == pytest.approx([-500] * 162, abs=1e-4) # check that the x <= 19 values are in ascending order y1 = y[x <= 19] assert (y1[1:] > y1[:-1]).all()
def fold(self, data): _PSFModel.fold(self, data) # Set WCS coordinates of kernel data set to match source data set. if (isinstance(data, DataIMG) and isinstance(self.kernel, DataIMG)): self.kernel.set_coord(data.coord)
def test_psf1d_step_v2(): """Trying to track down why we have seen different behavior in test_regrid_unit.py. """ smdl = StepLo1D() smdl.xcut = 100 smdl.ampl = 10 gsmooth = Gauss1D() psf = PSFModel('psf', gsmooth) x = np.arange(0, 200, 0.5) d = Data1D('fake', x, x * 0) psf.fold(d) smoothed = psf(smdl) y = smoothed(x) # So the output is not easy to describe analytically, hence # we just check parts of it. # assert y[(x >= 19.5) & (x <= 100)] == pytest.approx([10] * 162, abs=1e-4) assert y[x >= 119] == pytest.approx([0] * 162, abs=1e-4) # check that the x <= 19 values are in ascending order y1 = y[x <= 19] assert (y1[1:] > y1[:-1]).all()
def test_psf2d_model_show(): """What happens when the kernel is a model?""" m = PSFModel("pmodel2", make_2d_model()) yy, xx = np.mgrid[1:10, 1:9] xx = xx.flatten() yy = yy.flatten() zz = np.arange(xx.size) dfold = Data2D('fold', xx, yy, zz) m.fold(dfold) print(m) out = str(m).split("\n") assert len(out) == 8 assert out[0] == "pmodel2" assert out[ 1] == " Param Type Value Min Max Units" assert out[ 2] == " ----- ---- ----- --- --- -----" assert out[3] == " pmodel2.kernel frozen box2" assert out[ 4] == " pmodel2.size frozen (72, 72) (72, 72) (72, 72)" assert out[ 5] == " pmodel2.center frozen (36, 36) (36, 36) (36, 36)" assert out[ 6] == " pmodel2.radial frozen 0 0 1 " assert out[ 7] == " pmodel2.norm frozen 1 0 1 "
def test_psf2d_data_show(): """What happens when the kernel is a Data2D instance?""" y, x = np.mgrid[1:4, 1:3] x = x.flatten() y = y.flatten() z = np.ones(x.size) data2 = Data2D('data2', x, y, z) m = PSFModel("pdata2", data2) yy, xx = np.mgrid[1:10, 1:9] xx = xx.flatten() yy = yy.flatten() zz = np.arange(xx.size) dfold = Data2D('fold', xx, yy, zz) m.fold(dfold) out = str(m).split("\n") assert len(out) == 8 assert out[0] == "pdata2" assert out[ 1] == " Param Type Value Min Max Units" assert out[ 2] == " ----- ---- ----- --- --- -----" assert out[3] == " pdata2.kernel frozen data2" assert out[ 4] == " pdata2.size frozen (6, 6) (6, 6) (6, 6)" assert out[ 5] == " pdata2.center frozen (3, 3) (3, 3) (3, 3)" assert out[ 6] == " pdata2.radial frozen 0 0 1 " assert out[ 7] == " pdata2.norm frozen 1 0 1 "
def test_psf2d_data_given_1d_dataset(): """Do we error out or not? This is a regression test. """ psf = PSFModel('psf', make_2d_data()) d = make_1d_data() # Does this error out? psf.fold(d) smdl = Gauss2D() smdl.ampl = 1000 cmdl = Const2D() cmdl.c0 = -500 imdl = smdl + cmdl # Or maybe this errors out? smoothed = psf(imdl) with pytest.raises(TypeError) as err: smoothed(np.arange(1, 7)) assert str( err.value) == "function missing required argument 'x1lo' (pos 3)"
def test_psf1d_model_given_2d_dataset(): """Do we error out or not? This is a regression test. """ psf = PSFModel('psf', make_1d_model()) d = make_2d_data() # Does this error out? psf.fold(d) smdl = StepLo1D() smdl.xcut = 100 smdl.ampl = 10 cmdl = Const1D() cmdl.c0 = -500 imdl = smdl + cmdl # Or maybe this errors out? smoothed = psf(imdl) with pytest.raises(TypeError) as err: smoothed(np.arange(1, 7)) # It is not at all obvious why we have 36 for the source dim. # assert str( err.value ) == "input array sizes do not match dimensions, source size: 6 vs source dim: 36"
def test_psf1d_show(): """Test the __str__ method Loop through basic data and then add in the options (but not all possible combinations). """ def check(x, n, ans): toks = x[n].split() assert toks == ans NAME = ['psfmodel'] PARAMS = ['Param', 'Type', 'Value', 'Min', 'Max', 'Units'] LINES = ['-----', '----', '-----', '---', '---', '-----'] KERNEL = ['psfmodel.kernel', 'frozen', 'oned'] SIZE = ['psfmodel.size', 'frozen', '7', '7', '7'] CENTER = ['psfmodel.center', 'frozen', '3', '3', '3'] RADIAL = ['psfmodel.radial', 'frozen', '0', '0', '1'] NORM = ['psfmodel.norm', 'frozen', '1', '0', '1'] m = PSFModel() # basic settings out = str(m).split('\n') assert len(out) == 5 check(out, 0, NAME) check(out, 1, PARAMS) check(out, 2, LINES) check(out, 3, RADIAL) check(out, 4, NORM) m.kernel = make_1d_data() # before a fold you don't get the size and center parameters out = str(m).split('\n') assert len(out) == 6 check(out, 0, NAME) check(out, 1, PARAMS) check(out, 2, LINES) check(out, 3, KERNEL) check(out, 4, RADIAL) check(out, 5, NORM) dfold = Data1D('fold', np.arange(10), np.zeros(10)) m.fold(dfold) out = str(m).split('\n') assert len(out) == 8 check(out, 0, NAME) check(out, 1, PARAMS) check(out, 2, LINES) check(out, 3, KERNEL) check(out, 4, SIZE) check(out, 5, CENTER) check(out, 6, RADIAL) check(out, 7, NORM)
def test_psf1d_fold_no_kernel(): """Error out if there's no kernel""" m = PSFModel('bob') dfold = Data1D('fold', np.arange(10), np.zeros(10)) with pytest.raises(PSFErr) as exc: m.fold(dfold) assert "model 'bob' does not have an associated PSF function" == str(exc.value)
def test_psf1d_flat(): """This is based on sherpa.models.tests.test_regrid_unit.test_regrid1_works_with_convolution_style but I wanted to make sure we have an explicit check of the underlying code. """ cmdl = Const1D() cmdl.c0 = -500 gsmooth = Gauss1D() gsmooth.fwhm = 3 psf = PSFModel('psf', gsmooth) x = np.arange(5, 23, 3) d = Data1D('fake', x, x * 0) psf.fold(d) smoothed = psf(cmdl) y = smoothed(x) assert y == pytest.approx([-500] * 6)
def test_psf1d_step(): """This is based on sherpa.models.tests.test_regrid_unit.test_regrid1_works_with_convolution_style but I wanted to make sure we have an explicit check of the underlying code. """ smdl = StepLo1D() smdl.xcut = 12.5 smdl.ampl = 10 gsmooth = Gauss1D() gsmooth.fwhm = 3 psf = PSFModel('psf', gsmooth) x = np.arange(5, 23, 3) d = Data1D('fake', x, x * 0) psf.fold(d) smoothed = psf(smdl) y = smoothed(x) assert y == pytest.approx([10.0, 10.0, 10.0, 0, 0, 0], abs=1e-4)
def test_regrid1d_works_with_convolution_style(): """This doesn't really test more than the previous model-evaluation tests. """ smdl = StepLo1D() smdl.xcut = 100 smdl.ampl = 10 cmdl = Const1D() cmdl.c0 = -500 imdl = smdl + cmdl # Set up the convolution kernel # gsmooth = Gauss1D() psf = PSFModel('psf', gsmooth) smoothed = psf(imdl) # This is the model that will be evaluated # regrid = ModelDomainRegridder1D() smoothed_regrid = regrid.apply_to(smoothed) # Ignoring edge effects, the smoothed step function drops from # x=100 down to x~120 (it is not clear why it doesn't smooth # below x=100, but maybe I've set up the convolution wrong). # So, if the regrid model evaluates x=0 to 200 but the requested # grid is from x=102 ro 180, then we should see a difference # to evaluating without regrid. # xfull = np.arange(0, 200, 0.5) xout = np.arange(101, 180, 0.5) regrid.grid = xfull # fake up a data object for the fold method # TODO: it is not clear to me what grid should be used here; # xfull or xout # d = Data1D('fake', xfull, xfull * 0) psf.fold(d) y_regrid = smoothed_regrid(xout) # calculate the expected values y_full = smoothed(xfull) # since the grids have the same binning, it is a simple extraction idx0, = np.where(xfull == xout[0]) idx1, = np.where(xfull == xout[-1]) y_expected = y_full[idx0[0]:idx1[0] + 1] assert_allclose(y_regrid, y_expected, atol=1e-10, rtol=0) # check that this is all worth it; i.e. that without regrid # you just get the constant term. If this fails then it does not # mean that the regrid code is broken, but it implies that # something fundamental has changed with the basic model # evaluation. # d = Data1D('fake', xout, xout * 0) psf.fold(d) y_check = smoothed(xout) y_expected = np.zeros(xout.size) + cmdl.c0.val assert_allclose(y_check, y_expected, rtol=0, atol=1e-7)
from sherpa.models.basic import Const2D bgnd = Const2D('bgnd') bgnd.c0 = 0.25 final_mdl = convolved_mdl + bgnd print("# print(final_mdl)") print(final_mdl) yg, xg = np.mgrid[:10, :10] xg1d, yg1d = xg.flatten(), yg.flatten() m1 = unconvolved_mdl(xg1d, yg1d).reshape(xg.shape) blank = Data2D('blank', xg1d, yg1d, np.ones(xg1d.shape), xg.shape) m1 = blank.eval_model(unconvolved_mdl).reshape(xg.shape) psf.fold(blank) m2 = blank.eval_model(convolved_mdl).reshape(xg.shape) # TODO: set the axes? Actually, be design they are the same as # that shown by matplotlib # plt.imshow(m1, origin='lower', cmap='viridis') plt.colorbar() plt.title('Unconvolved') plt.savefig('convolution_psf2d_evaluate_unconv.png') plt.clf() plt.imshow(m2, origin='lower', cmap='viridis', vmin=0, vmax=10) plt.colorbar() plt.title('Convolved') plt.savefig('convolution_psf2d_evaluate_conv.png')
def fold(self, data): _PSFModel.fold(self, data) # Set WCS coordinates of kernel data set to match source data set. if hasattr(self.kernel, "set_coord"): self.kernel.set_coord(data.coord)