def make_arf2(): """Create two ARFs that overlap""" elo, ehi, dset = get_egrid() y1, y2 = expected_arf2() arf1 = create_arf(elo, ehi, specresp=y1) arf2 = create_arf(elo, ehi, specresp=y2) return arf1, arf2, dset
def test_save_model_pha_ascii(clean_astro_ui, tmp_path): """Can we write out data for save_model? DataPHA and ASCII""" ui.load_arrays(1, [1, 2], [5, 10], ui.DataPHA) # we need a response egrid = np.asarray([0.1, 0.2, 0.4]) elo = egrid[:-1] ehi = egrid[1:] rmf = create_delta_rmf(elo, ehi, e_min=elo, e_max=ehi) ui.set_rmf(rmf) yarf = np.asarray([10, 20]) arf = create_arf(elo, ehi, yarf) ui.set_arf(arf) ui.set_source(ui.const1d.cmdl) cmdl.c0 = 2 out = tmp_path / 'model.dat' ui.save_model(str(out), ascii=True) cts = out.read_text() check_output(cts, ['XLO', 'XHI', 'MODEL'], [[0.1, 0.2, 20], [0.2, 0.4, 40]])
def test_save_resid_datapha_fits(tmp_path): """Residual, DataPHA, FITS""" from sherpa.astro.io import read_table_blocks ui.load_arrays(1, [1, 2], [5, 10], ui.DataPHA) # we need a response egrid = np.asarray([0.1, 0.2, 0.4]) elo = egrid[:-1] ehi = egrid[1:] rmf = create_delta_rmf(elo, ehi, e_min=elo, e_max=ehi) ui.set_rmf(rmf) yarf = np.asarray([10, 20]) arf = create_arf(elo, ehi, yarf) ui.set_arf(arf) ui.set_source(ui.const1d.cmdl) cmdl.c0 = 2 out = tmp_path / 'resid.out' outfile = str(out) ui.save_resid(outfile) ans = read_table_blocks(outfile) blocks = ans[1] assert len(blocks) == 2 check_table(blocks[2], {'X': [0.15, 0.3], 'RESID': [30, 10]})
def test_save_resid_datapha(tmp_path): """Residual, DataPHA, ASCII""" ui.load_arrays(1, [1, 2], [5, 10], ui.DataPHA) # we need a response egrid = np.asarray([0.1, 0.2, 0.4]) elo = egrid[:-1] ehi = egrid[1:] rmf = create_delta_rmf(elo, ehi, e_min=elo, e_max=ehi) ui.set_rmf(rmf) yarf = np.asarray([10, 20]) arf = create_arf(elo, ehi, yarf) ui.set_arf(arf) ui.set_source(ui.const1d.cmdl) cmdl.c0 = 2 out = tmp_path / 'resid.out' outfile = str(out) ui.save_resid(outfile, ascii=True) cts = out.read_text() check_output(cts, ['X', 'RESID'], [[0.15, 30], [0.3, 10]])
def test_cstat_rsppha(): """What does CSTAT calculate when there is an RSP+PHA instrument model. This includes the AREASCAL when evaluating the model. See Also -------- test_cstat_nophamodel, test_cstat_arfpha, test_cstat_rmfpha """ dset, mdl, expected = setup_likelihood(scale=True) # use the full channel grid; the energy grid has to be # "the same" as the channel values since the model # has a dependency on the independent axis # egrid = 1.0 * np.concatenate((dset.channel, [dset.channel.max() + 1])) arf = create_arf(egrid[:-1], egrid[1:]) rmf = create_delta_rmf(egrid[:-1], egrid[1:]) mdl_ascal = RSPModelPHA(arf, rmf, dset, mdl) stat = CStat() sval_ascal = stat.calc_stat(dset, mdl_ascal) assert sval_ascal[0] == pytest.approx(expected)
def test_save_source_pha_fits(clean_astro_ui, tmp_path): """Can we write out data for save_source? DataPHA and FITS """ from sherpa.astro.io import read_table_blocks ui.load_arrays(1, [1, 2], [5, 10], ui.DataPHA) # we need a response egrid = np.asarray([0.1, 0.2, 0.4]) elo = egrid[:-1] ehi = egrid[1:] rmf = create_delta_rmf(elo, ehi, e_min=elo, e_max=ehi) ui.set_rmf(rmf) yarf = np.asarray([10, 20]) arf = create_arf(elo, ehi, yarf) ui.set_arf(arf) ui.set_source(ui.const1d.cmdl) cmdl.c0 = 2 out = tmp_path / 'model.dat' outfile = str(out) ui.save_source(outfile) ans = read_table_blocks(outfile) blocks = ans[1] assert len(blocks) == 2 check_table(blocks[2], { 'XLO': [0.1, 0.2], 'XHI': [0.2, 0.4], 'SOURCE': [2, 2] })
def test_rsp_normf_error(analysis): """Check that an error is raised on set_analysis """ exposure = 200.1 # rdata is only used to define the grids rdata = create_non_delta_rmf() specresp = create_non_delta_specresp() adata = create_arf(rdata.energ_lo, rdata.energ_hi, specresp, exposure=exposure) nchans = rdata.e_min.size channels = np.arange(1, nchans + 1, dtype=np.int16) counts = np.ones(nchans, dtype=np.int16) pha = DataPHA('test-pha', channel=channels, counts=counts, exposure=exposure) pha.set_arf(adata) with pytest.raises(DataErr) as exc: pha.set_analysis(analysis) emsg = "response incomplete for dataset test-pha, " + \ "check the instrument model" assert str(exc.value) == emsg
def test_rspmodelnopha_delta_call(): "What happens calling an RMF (delta)+ARF with no pha?" exposure = 200.1 egrid = np.arange(0.01, 0.06, 0.01) elo = egrid[:-1] ehi = egrid[1:] specresp = np.asarray([1.2, 0.0, 0.5, 4.3]) rdata = create_delta_rmf(elo, ehi) adata = create_arf(elo, ehi, specresp, exposure=exposure) constant = 2.3 mdl = Const1D('flat') mdl.c0 = constant wrapped = RSPModelNoPHA(adata, rdata, mdl) # The model is evaluated on the RMF grid, not whatever # is sent in. It is also integrated across the bins, # which is why there is a multiplication by the # grid width (for this constant model). # de = egrid[1:] - egrid[:-1] expected = constant * specresp * de out = wrapped([4, 5]) assert_allclose(out, expected)
def test_has_pha_response(): """Check the examples from the docstring""" exposure = 200.1 rdata = create_non_delta_rmf() specresp = create_non_delta_specresp() adata = create_arf(rdata.energ_lo, rdata.energ_hi, specresp, exposure=exposure) nchans = rdata.e_min.size channels = np.arange(1, nchans + 1, dtype=np.int16) counts = np.ones(nchans, dtype=np.int16) pha = DataPHA('test-pha', channel=channels, counts=counts, exposure=exposure) pha.set_arf(adata) pha.set_rmf(rdata) rsp = Response1D(pha) m1 = Gauss1D() m2 = PowLaw1D() assert not has_pha_response(m1) assert has_pha_response(rsp(m1)) assert not has_pha_response(m1 + m2) assert has_pha_response(rsp(m1 + m2)) assert has_pha_response(m1 + rsp(m2)) # reflexivity check assert has_pha_response(rsp(m1) + m2) assert has_pha_response(rsp(m1) + rsp(m2))
def test_arfmodelnopha_call(): "What happens calling an arf with no pha?" # Note: the exposure is set in the ARF, but should not be # used when evaluating the model; it's value has been # set to a value that the test will fail it it is. # egrid = np.arange(0.01, 0.06, 0.01) svals = [1.1, 1.2, 1.3, 1.4] specresp = np.asarray(svals) adata = create_arf(egrid[:-1], egrid[1:], specresp, exposure=200.1) constant = 2.3 mdl = Const1D('flat') mdl.c0 = constant wrapped = ARFModelNoPHA(adata, mdl) # The model is evaluated on the ARF grid, not whatever # is sent in. It is also integrated across the bins, # which is why there is a multiplication by the # grid width (for this constant model). # de = egrid[1:] - egrid[:-1] expected = constant * np.asarray(svals) * de out = wrapped([4, 5]) assert_allclose(out, expected)
def test_rspmodelnopha_matrix_call(): "What happens calling an RMF (matrix)+ARF with no pha?" rdata = create_non_delta_rmf() exposure = 200.1 specresp = np.asarray([200.0, 100.0, 0.0, 175.0, 300.0, 400.0, 350.0, 200.0, 250.0, 300.0, 200.0, 100.0, 100.0, 150.0, 175.0, 125.0, 100.0, 90.0, 80.0, 0.0]) adata = create_arf(rdata.energ_lo, rdata.energ_hi, specresp, exposure=exposure) constant = 2.3 slope = -0.25 mdl = Polynom1D('mdl') mdl.c0 = constant mdl.c1 = slope wrapped = RSPModelNoPHA(adata, rdata, mdl) # Calculate the model analytically. Note that the exposure # value is ignored. # modvals = specresp * mdl(rdata.energ_lo, rdata.energ_hi) matrix = get_non_delta_matrix() expected = np.matmul(modvals, matrix) out = wrapped([4, 5]) assert_allclose(out, expected)
def test_rspmodelnopha_matrix_call(): "What happens calling an RMF (matrix)+ARF with no pha?" rdata = create_non_delta_rmf() exposure = 200.1 specresp = np.asarray([ 200.0, 100.0, 0.0, 175.0, 300.0, 400.0, 350.0, 200.0, 250.0, 300.0, 200.0, 100.0, 100.0, 150.0, 175.0, 125.0, 100.0, 90.0, 80.0, 0.0 ]) adata = create_arf(rdata.energ_lo, rdata.energ_hi, specresp, exposure=exposure) constant = 2.3 slope = -0.25 mdl = Polynom1D('mdl') mdl.c0 = constant mdl.c1 = slope wrapped = RSPModelNoPHA(adata, rdata, mdl) # Calculate the model analytically. Note that the exposure # value is ignored. # modvals = specresp * mdl(rdata.energ_lo, rdata.energ_hi) matrix = get_non_delta_matrix() expected = np.matmul(modvals, matrix) out = wrapped([4, 5]) assert_allclose(out, expected)
def test_arfmodelnopha_call(): "What happens calling an arf with no pha?" # Note: the exposure is set in the ARF, but should not be # used when evaluating the model; it's value has been # set to a value that the test will fail it it is. # egrid = np.arange(0.01, 0.06, 0.01) svals = [1.1, 1.2, 1.3, 1.4] specresp = np.asarray(svals) adata = create_arf(egrid[:-1], egrid[1:], specresp, exposure=200.1) constant = 2.3 mdl = Const1D('flat') mdl.c0 = constant wrapped = ARFModelNoPHA(adata, mdl) # The model is evaluated on the ARF grid, not whatever # is sent in. It is also integrated across the bins, # which is why there is a multiplication by the # grid width (for this constant model). # de = egrid[1:] - egrid[:-1] expected = constant * np.asarray(svals) * de out = wrapped([4, 5]) assert_allclose(out, expected)
def test_arf1d_no_pha_no_exposure_call(exposure): "Can we call an ARF (no PHA)" egrid = np.arange(0.1, 0.6, 0.1) specresp = np.asarray([1.1, 1.2, 1.3, 1.4]) adata = create_arf(egrid[:-1], egrid[1:], specresp, exposure=exposure) arf = ARF1D(adata) mdl = Const1D('flat') mdl.c0 = 2.3 wrapped = arf(mdl) assert isinstance(wrapped, ARFModelNoPHA) wmdl = wrapped.model if exposure is None: assert wmdl == mdl else: # It looks like equality is not well defined for the model # classes, since the following assertion fails # assert wmdl == (exposure * mdl) # so manually check # assert isinstance(wmdl, BinaryOpModel) assert wmdl.op == np.multiply assert wmdl.rhs == mdl assert isinstance(wmdl.lhs, ArithmeticConstantModel) assert wmdl.lhs.val == pytest.approx(exposure)
def test_arf1d_no_pha_zero_energy_bin_replace(): "What happens when the first bin starts at 0, with replacement" ethresh = 1e-5 exposure = 0.1 egrid = np.asarray([0.0, 0.1, 0.2, 0.4, 0.5, 0.7, 0.8]) elo = egrid[:-1] ehi = egrid[1:] specresp = np.asarray([10.2, 9.8, 10.0, 12.0, 8.0, 10.0]) with warnings.catch_warnings(record=True) as ws: warnings.simplefilter("always") adata = create_arf(elo, ehi, specresp, exposure=exposure, ethresh=ethresh) validate_zero_replacement(ws, 'ARF', 'user-arf', ethresh) arf = ARF1D(adata) mdl = MyPowLaw1D() tmdl = PowLaw1D() wrapped = arf(mdl) out = wrapped([0.1, 0.2]) elo[0] = ethresh expected = exposure * specresp * tmdl(elo, ehi) assert_allclose(out, expected) assert not np.isnan(out[0])
def test_arfmodelpha_call(ignore): """What happens calling an arf with a pha? The ignore value indicates what channel to ignore (0 means nothing is ignored). The aim is to check edge effects, and as there are only a few channels, it was decided to test all channels. """ # Note: the exposure is set in the PHA and ARF, but should not be # used when evaluating the model; it's value has been # set to a value that the test will fail it it is. # exposure = 200.1 estep = 0.01 egrid = np.arange(0.01, 0.06, estep) svals = [1.1, 1.2, 1.3, 1.4] specresp = np.asarray(svals) adata = create_arf(egrid[:-1], egrid[1:], specresp, exposure=exposure) constant = 2.3 mdl = Const1D('flat') mdl.c0 = constant channels = np.arange(1, 5, dtype=np.int16) counts = np.asarray([10, 5, 12, 7], dtype=np.int16) pha = DataPHA('test-pha', channel=channels, counts=counts, exposure=exposure) pha.set_arf(adata) # force energy units (only needed if ignore is set) pha.set_analysis('energy') if ignore is not None: de = estep * 0.9 e0 = egrid[ignore] pha.notice(lo=e0, hi=e0 + de, ignore=True) # The assert are intended to help people reading this # code rather than being a useful check that the code # is working. mask = [True, True, True, True] mask[ignore] = False assert (pha.mask == mask).all() wrapped = ARFModelPHA(adata, pha, mdl) # The model is evaluated on the ARF grid, not whatever # is sent in. It is also integrated across the bins, # which is why there is a multiplication by the # grid width (for this constant model). # # Note that the filter doesn't change the grid. # de = egrid[1:] - egrid[:-1] expected = constant * np.asarray(svals) * de out = wrapped([4, 5]) assert_allclose(out, expected)
def test_rmf1d_matrix_arf_no_pha_call(): "Can we call an RMF () with ARF (no PHA)" # NOTE: there is no check that the grids are compatible # so this is probably not that useful a test # rdata = create_non_delta_rmf() elo = rdata.e_min ehi = rdata.e_max adata = create_arf(elo, ehi) rmf = RMF1D(rdata, arf=adata) mdl = Const1D('flat') mdl.c0 = 2.3 wrapped = rmf(mdl) # It seems like the wrapper should match the following: # assert isinstance(wrapped, RSPModelNoPHA) # but at the time the test was written (June 2017) it # does not. # assert isinstance(wrapped, RMFModelNoPHA) wmdl = wrapped.model assert wmdl == mdl
def test_rsp_normf_error(analysis): """Check that an error is raised on set_analysis """ exposure = 200.1 # rdata is only used to define the grids rdata = create_non_delta_rmf() specresp = create_non_delta_specresp() adata = create_arf(rdata.energ_lo, rdata.energ_hi, specresp, exposure=exposure) nchans = rdata.e_min.size channels = np.arange(1, nchans + 1, dtype=np.int16) counts = np.ones(nchans, dtype=np.int16) pha = DataPHA('test-pha', channel=channels, counts=counts, exposure=exposure) pha.set_arf(adata) with pytest.raises(DataErr) as exc: pha.set_analysis(analysis) emsg = "response incomplete for dataset test-pha, " + \ "check the instrument model" assert str(exc.value) == emsg
def test_arf1d_no_pha_no_exposure_call(exposure): "Can we call an ARF (no PHA)" egrid = np.arange(0.1, 0.6, 0.1) specresp = np.asarray([1.1, 1.2, 1.3, 1.4]) adata = create_arf(egrid[:-1], egrid[1:], specresp, exposure=exposure) arf = ARF1D(adata) mdl = Const1D('flat') mdl.c0 = 2.3 wrapped = arf(mdl) assert isinstance(wrapped, ARFModelNoPHA) wmdl = wrapped.model if exposure is None: assert wmdl == mdl else: # It looks like equality is not well defined for the model # classes, since the following assertion fails # assert wmdl == (exposure * mdl) # so manually check # assert isinstance(wmdl, BinaryOpModel) assert wmdl.op == np.multiply assert wmdl.rhs == mdl assert isinstance(wmdl.lhs, ArithmeticConstantModel) assert wmdl.lhs.val == pytest.approx(exposure)
def test_rmf1d_matrix_arf_no_pha_call(): "Can we call an RMF () with ARF (no PHA)" # NOTE: there is no check that the grids are compatible # so this is probably not that useful a test # rdata = create_non_delta_rmf() elo = rdata.e_min ehi = rdata.e_max adata = create_arf(elo, ehi) rmf = RMF1D(rdata, arf=adata) mdl = Const1D('flat') mdl.c0 = 2.3 wrapped = rmf(mdl) # It seems like the wrapper should match the following: # assert isinstance(wrapped, RSPModelNoPHA) # but at the time the test was written (June 2017) it # does not. # assert isinstance(wrapped, RMFModelNoPHA) wmdl = wrapped.model assert wmdl == mdl
def test_arf1d_no_pha_zero_energy_bin_replace(): "What happens when the first bin starts at 0, with replacement" ethresh = 1e-5 exposure = 0.1 egrid = np.asarray([0.0, 0.1, 0.2, 0.4, 0.5, 0.7, 0.8]) elo = egrid[:-1] ehi = egrid[1:] specresp = np.asarray([10.2, 9.8, 10.0, 12.0, 8.0, 10.0]) with warnings.catch_warnings(record=True) as ws: warnings.simplefilter("always") adata = create_arf(elo, ehi, specresp, exposure=exposure, ethresh=ethresh) validate_zero_replacement(ws, 'ARF', 'user-arf', ethresh) arf = ARF1D(adata) mdl = MyPowLaw1D() tmdl = PowLaw1D() wrapped = arf(mdl) out = wrapped([0.1, 0.2]) elo[0] = ethresh expected = exposure * specresp * tmdl(elo, ehi) assert_allclose(out, expected) assert not np.isnan(out[0])
def test_rspmodelnopha_delta_call(): "What happens calling an RMF (delta)+ARF with no pha?" exposure = 200.1 egrid = np.arange(0.01, 0.06, 0.01) elo = egrid[:-1] ehi = egrid[1:] specresp = np.asarray([1.2, 0.0, 0.5, 4.3]) rdata = create_delta_rmf(elo, ehi) adata = create_arf(elo, ehi, specresp, exposure=exposure) constant = 2.3 mdl = Const1D('flat') mdl.c0 = constant wrapped = RSPModelNoPHA(adata, rdata, mdl) # The model is evaluated on the RMF grid, not whatever # is sent in. It is also integrated across the bins, # which is why there is a multiplication by the # grid width (for this constant model). # de = egrid[1:] - egrid[:-1] expected = constant * specresp * de out = wrapped([4, 5]) assert_allclose(out, expected)
def test_arfmodelpha_call(ignore): """What happens calling an arf with a pha? The ignore value indicates what channel to ignore (0 means nothing is ignored). The aim is to check edge effects, and as there are only a few channels, it was decided to test all channels. """ # Note: the exposure is set in the PHA and ARF, but should not be # used when evaluating the model; it's value has been # set to a value that the test will fail it it is. # exposure = 200.1 estep = 0.01 egrid = np.arange(0.01, 0.06, estep) svals = [1.1, 1.2, 1.3, 1.4] specresp = np.asarray(svals) adata = create_arf(egrid[:-1], egrid[1:], specresp, exposure=exposure) constant = 2.3 mdl = Const1D('flat') mdl.c0 = constant channels = np.arange(1, 5, dtype=np.int16) counts = np.asarray([10, 5, 12, 7], dtype=np.int16) pha = DataPHA('test-pha', channel=channels, counts=counts, exposure=exposure) pha.set_arf(adata) # force energy units (only needed if ignore is set) pha.set_analysis('energy') if ignore is not None: de = estep * 0.9 e0 = egrid[ignore] pha.notice(lo=e0, hi=e0 + de, ignore=True) # The assert are intended to help people reading this # code rather than being a useful check that the code # is working. mask = [True, True, True, True] mask[ignore] = False assert (pha.mask == mask).all() wrapped = ARFModelPHA(adata, pha, mdl) # The model is evaluated on the ARF grid, not whatever # is sent in. It is also integrated across the bins, # which is why there is a multiplication by the # grid width (for this constant model). # # Note that the filter doesn't change the grid. # de = egrid[1:] - egrid[:-1] expected = constant * np.asarray(svals) * de out = wrapped([4, 5]) assert_allclose(out, expected)
def test_rspmodelpha_delta_call(ignore): """What happens calling a rsp with a pha (RMF is a delta fn)? The ignore value gives the channel to ignore (counting from 0). """ exposure = 200.1 estep = 0.025 egrid = np.arange(0.1, 0.8, estep) elo = egrid[:-1] ehi = egrid[1:] specresp = 2.4 * np.ones(elo.size, dtype=np.float32) specresp[2:5] = 0.0 specresp[16:19] = 3.2 adata = create_arf(elo, ehi, specresp, exposure=exposure) rdata = create_delta_rmf(elo, ehi, e_min=elo, e_max=ehi) nchans = elo.size constant = 2.3 mdl = Const1D('flat') mdl.c0 = constant channels = np.arange(1, nchans + 1, dtype=np.int16) counts = np.ones(nchans, dtype=np.int16) pha = DataPHA('test-pha', channel=channels, counts=counts, exposure=exposure) pha.set_rmf(rdata) # force energy units (only needed if ignore is set) pha.set_analysis('energy') if ignore is not None: de = estep * 0.9 e0 = egrid[ignore] pha.notice(lo=e0, hi=e0 + de, ignore=True) # The assert are intended to help people reading this # code rather than being a useful check that the code # is working. mask = [True] * nchans mask[ignore] = False assert (pha.mask == mask).all() wrapped = RSPModelPHA(adata, rdata, pha, mdl) # The model is evaluated on the RMF grid, not whatever # is sent in. It is also integrated across the bins, # which is why there is a multiplication by the # grid width (for this constant model). # # Note that the filter doesn't change the grid. # de = egrid[1:] - egrid[:-1] expected = constant * specresp * de out = wrapped([4, 5]) assert_allclose(out, expected)
def test_arf1d_no_pha_zero_energy_bin(): """What happens when the first bin starts at 0, no replacement This replicates a test in test_data.py; note that this test is left here, but other tests below only include the "with replacement" version, to avoid duplication. """ exposure = 0.1 egrid = np.asarray([0.0, 0.1, 0.2, 0.4, 0.5, 0.7, 0.8]) elo = egrid[:-1] ehi = egrid[1:] specresp = np.asarray([10.2, 9.8, 10.0, 12.0, 8.0, 10.0]) with pytest.raises(DataErr) as exc: create_arf(elo, ehi, specresp, exposure=exposure) emsg = "The ARF 'user-arf' has an ENERG_LO value <= 0" assert str(exc.value) == emsg
def test_arf1d_no_pha_zero_energy_bin(): """What happens when the first bin starts at 0, no replacement This replicates a test in test_data.py; note that this test is left here, but other tests below only include the "with replacement" version, to avoid duplication. """ exposure = 0.1 egrid = np.asarray([0.0, 0.1, 0.2, 0.4, 0.5, 0.7, 0.8]) elo = egrid[:-1] ehi = egrid[1:] specresp = np.asarray([10.2, 9.8, 10.0, 12.0, 8.0, 10.0]) with pytest.raises(DataErr) as exc: create_arf(elo, ehi, specresp, exposure=exposure) emsg = "The ARF 'user-arf' has an ENERG_LO value <= 0" assert str(exc.value) == emsg
def test_rspmodelpha_delta_call(ignore): """What happens calling a rsp with a pha (RMF is a delta fn)? The ignore value gives the channel to ignore (counting from 0). """ exposure = 200.1 estep = 0.025 egrid = np.arange(0.1, 0.8, estep) elo = egrid[:-1] ehi = egrid[1:] specresp = 2.4 * np.ones(elo.size, dtype=np.float32) specresp[2:5] = 0.0 specresp[16:19] = 3.2 adata = create_arf(elo, ehi, specresp, exposure=exposure) rdata = create_delta_rmf(elo, ehi, e_min=elo, e_max=ehi) nchans = elo.size constant = 2.3 mdl = Const1D('flat') mdl.c0 = constant channels = np.arange(1, nchans + 1, dtype=np.int16) counts = np.ones(nchans, dtype=np.int16) pha = DataPHA('test-pha', channel=channels, counts=counts, exposure=exposure) pha.set_rmf(rdata) # force energy units (only needed if ignore is set) pha.set_analysis('energy') if ignore is not None: de = estep * 0.9 e0 = egrid[ignore] pha.notice(lo=e0, hi=e0 + de, ignore=True) # The assert are intended to help people reading this # code rather than being a useful check that the code # is working. mask = [True] * nchans mask[ignore] = False assert (pha.mask == mask).all() wrapped = RSPModelPHA(adata, rdata, pha, mdl) # The model is evaluated on the RMF grid, not whatever # is sent in. It is also integrated across the bins, # which is why there is a multiplication by the # grid width (for this constant model). # # Note that the filter doesn't change the grid. # de = egrid[1:] - egrid[:-1] expected = constant * specresp * de out = wrapped([4, 5]) assert_allclose(out, expected)
def test_rsp1d_matrix_pha_zero_energy_bin(): """What happens when the first bin starts at 0, with replacement. Unlike test_rsp1d_delta_pha_zero_energy_bin this directly calls Response1D to create the model. """ ethresh = 1.0e-5 rdata = create_non_delta_rmf() # hack the first bin to have 0 energy rdata.energ_lo[0] = 0.0 # PHA and ARF have different exposure ties exposure_arf = 0.1 exposure_pha = 2.4 specresp = create_non_delta_specresp() with warnings.catch_warnings(record=True) as ws: warnings.simplefilter("always") adata = create_arf(rdata.energ_lo, rdata.energ_hi, specresp, exposure=exposure_arf, ethresh=ethresh) validate_zero_replacement(ws, 'ARF', 'user-arf', ethresh) nchans = rdata.e_min.size channels = np.arange(1, nchans + 1, dtype=np.int16) counts = np.ones(nchans, dtype=np.int16) pha = DataPHA('test-pha', channel=channels, counts=counts, exposure=exposure_pha) pha.set_rmf(rdata) pha.set_arf(adata) pha.set_analysis('energy') mdl = MyPowLaw1D() rsp = Response1D(pha) wrapped = rsp(mdl) # Evaluate the statistic / model. The value was calculated using # commit a65fb94004664eab219cc09652172ffe1dad80a6 on a linux # system (Ubuntu 17.04). # f = Fit(pha, wrapped) ans = f.calc_stat() assert ans == pytest.approx(37971.8716151947)
def test_rspmodelpha_matrix_call(ignore): """What happens calling a rsp with a pha (RMF is a matrix)? The ignore value gives the channel to ignore (counting from 0). """ exposure = 200.1 rdata = create_non_delta_rmf() specresp = create_non_delta_specresp() elo = rdata.energ_lo ehi = rdata.energ_hi adata = create_arf(elo, ehi, specresp, exposure=exposure) nchans = rdata.e_min.size constant = 22.3 slope = -1.2 mdl = Polynom1D('sloped') mdl.c0 = constant mdl.c1 = slope channels = np.arange(1, nchans + 1, dtype=np.int16) counts = np.ones(nchans, dtype=np.int16) pha = DataPHA('test-pha', channel=channels, counts=counts, exposure=exposure) pha.set_rmf(rdata) # force energy units (only needed if ignore is set) pha.set_analysis('energy') if ignore is not None: e0 = rdata.e_min[ignore] e1 = rdata.e_max[ignore] de = 0.9 * (e1 - e0) pha.notice(lo=e0, hi=e0 + de, ignore=True) # The assert are intended to help people reading this # code rather than being a useful check that the code # is working. mask = [True] * nchans mask[ignore] = False assert (pha.mask == mask).all() wrapped = RSPModelPHA(adata, rdata, pha, mdl) # The filter does not change the grid modvals = specresp * mdl(rdata.energ_lo, rdata.energ_hi) matrix = get_non_delta_matrix() expected = np.matmul(modvals, matrix) out = wrapped([4, 5]) assert_allclose(out, expected)
def test_rsp1d_matrix_pha_zero_energy_bin(): """What happens when the first bin starts at 0, with replacement. Unlike test_rsp1d_delta_pha_zero_energy_bin this directly calls Response1D to create the model. """ ethresh = 1.0e-5 rdata = create_non_delta_rmf() # hack the first bin to have 0 energy rdata.energ_lo[0] = 0.0 # PHA and ARF have different exposure ties exposure_arf = 0.1 exposure_pha = 2.4 specresp = create_non_delta_specresp() with warnings.catch_warnings(record=True) as ws: warnings.simplefilter("always") adata = create_arf(rdata.energ_lo, rdata.energ_hi, specresp, exposure=exposure_arf, ethresh=ethresh) validate_zero_replacement(ws, 'ARF', 'user-arf', ethresh) nchans = rdata.e_min.size channels = np.arange(1, nchans + 1, dtype=np.int16) counts = np.ones(nchans, dtype=np.int16) pha = DataPHA('test-pha', channel=channels, counts=counts, exposure=exposure_pha) pha.set_rmf(rdata) pha.set_arf(adata) pha.set_analysis('energy') mdl = MyPowLaw1D() rsp = Response1D(pha) wrapped = rsp(mdl) # Evaluate the statistic / model. The value was calculated using # commit a65fb94004664eab219cc09652172ffe1dad80a6 on a linux # system (Ubuntu 17.04). # f = Fit(pha, wrapped) ans = f.calc_stat() assert ans == pytest.approx(37971.8716151947)
def test_rspmodelpha_matrix_call(ignore): """What happens calling a rsp with a pha (RMF is a matrix)? The ignore value gives the channel to ignore (counting from 0). """ exposure = 200.1 rdata = create_non_delta_rmf() specresp = create_non_delta_specresp() elo = rdata.energ_lo ehi = rdata.energ_hi adata = create_arf(elo, ehi, specresp, exposure=exposure) nchans = rdata.e_min.size constant = 22.3 slope = -1.2 mdl = Polynom1D('sloped') mdl.c0 = constant mdl.c1 = slope channels = np.arange(1, nchans + 1, dtype=np.int16) counts = np.ones(nchans, dtype=np.int16) pha = DataPHA('test-pha', channel=channels, counts=counts, exposure=exposure) pha.set_rmf(rdata) # force energy units (only needed if ignore is set) pha.set_analysis('energy') if ignore is not None: e0 = rdata.e_min[ignore] e1 = rdata.e_max[ignore] de = 0.9 * (e1 - e0) pha.notice(lo=e0, hi=e0 + de, ignore=True) # The assert are intended to help people reading this # code rather than being a useful check that the code # is working. mask = [True] * nchans mask[ignore] = False assert (pha.mask == mask).all() wrapped = RSPModelPHA(adata, rdata, pha, mdl) # The filter does not change the grid modvals = specresp * mdl(rdata.energ_lo, rdata.energ_hi) matrix = get_non_delta_matrix() expected = np.matmul(modvals, matrix) out = wrapped([4, 5]) assert_allclose(out, expected)
def test_rsp1d_delta_pha_zero_energy_bin(): "What happens when the first bin starts at 0, with replacement" ethresh = 2.0e-7 # PHA and ARF have different exposure ties exposure1 = 0.1 exposure2 = 2.4 egrid = np.asarray([0.0, 0.1, 0.2, 0.4, 0.5, 0.7, 0.8]) elo = egrid[:-1] ehi = egrid[1:] specresp = np.asarray([10.2, 9.8, 10.0, 12.0, 8.0, 10.0]) with warnings.catch_warnings(record=True) as ws: warnings.simplefilter("always") adata = create_arf(elo, ehi, specresp, exposure=exposure1, ethresh=ethresh) validate_zero_replacement(ws, 'ARF', 'user-arf', ethresh) with warnings.catch_warnings(record=True) as ws: warnings.simplefilter("always") rdata = create_delta_rmf(elo, ehi, ethresh=ethresh) validate_zero_replacement(ws, 'RMF', 'delta-rmf', ethresh) channels = np.arange(1, 7, dtype=np.int16) counts = np.ones(6, dtype=np.int16) pha = DataPHA('test-pha', channel=channels, counts=counts, exposure=exposure2) pha.set_rmf(rdata) pha.set_arf(adata) pha.set_analysis('energy') mdl = MyPowLaw1D() tmdl = PowLaw1D() wrapped = RSPModelPHA(adata, rdata, pha, mdl) out = wrapped([0.1, 0.2]) elo[0] = ethresh expected = specresp * tmdl(elo, ehi) assert_allclose(out, expected) assert not np.isnan(out[0])
def test_rspmodelpha_matrix_call_xspec(): """Check XSPEC constant is invariant to wavelength/energy setting. As XSPEC models internally convert from Angstrom to keV, do a simple check here. """ exposure = 200.1 rdata = create_non_delta_rmf() specresp = create_non_delta_specresp() adata = create_arf(rdata.energ_lo, rdata.energ_hi, specresp, exposure=exposure) constant = 2.3 mdl = XSconstant('flat') mdl.factor = constant nchans = rdata.e_min.size channels = np.arange(1, nchans + 1, dtype=np.int16) counts = np.ones(nchans, dtype=np.int16) pha = DataPHA('test-pha', channel=channels, counts=counts, exposure=exposure) # The set_arf call isn't necessary, but leave in pha.set_arf(adata) pha.set_rmf(rdata) # The XSPEC models are evaluated on an energy grid, even when # the analysis setting is wavelength. Also, unlike the Sherpa # Constant model, the XSPEC XSconstant model is defined # over the integrated bin, so no correction is needed for the # bin width. # modvals = constant * specresp matrix = get_non_delta_matrix() expected = np.matmul(modvals, matrix) wrapped = RSPModelPHA(adata, rdata, pha, mdl) pha.set_analysis('wave') out_wl = wrapped([4, 5]) assert_allclose(out_wl, expected) pha.set_analysis('energy') out_en = wrapped([4, 5]) assert_allclose(out_en, expected)
def test_rspmodelpha_matrix_call_xspec(): """Check XSPEC constant is invariant to wavelength/energy setting. As XSPEC models internally convert from Angstrom to keV, do a simple check here. """ exposure = 200.1 rdata = create_non_delta_rmf() specresp = create_non_delta_specresp() adata = create_arf(rdata.energ_lo, rdata.energ_hi, specresp, exposure=exposure) constant = 2.3 mdl = XSconstant('flat') mdl.factor = constant nchans = rdata.e_min.size channels = np.arange(1, nchans + 1, dtype=np.int16) counts = np.ones(nchans, dtype=np.int16) pha = DataPHA('test-pha', channel=channels, counts=counts, exposure=exposure) # The set_arf call isn't necessary, but leave in pha.set_arf(adata) pha.set_rmf(rdata) # The XSPEC models are evaluated on an energy grid, even when # the analysis setting is wavelength. Also, unlike the Sherpa # Constant model, the XSPEC XSconstant model is defined # over the integrated bin, so no correction is needed for the # bin width. # modvals = constant * specresp matrix = get_non_delta_matrix() expected = np.matmul(modvals, matrix) wrapped = RSPModelPHA(adata, rdata, pha, mdl) pha.set_analysis('wave') out_wl = wrapped([4, 5]) assert_allclose(out_wl, expected) pha.set_analysis('energy') out_en = wrapped([4, 5]) assert_allclose(out_en, expected)
def test_arf1d_pha_zero_energy_bin(): "What happens when the first bin starts at 0, with replacement" ethresh = 1.0e-10 # Note: the two exposures are different to check which is # used (the answer is neither, which seems surprising) # exposure1 = 0.1 egrid = np.asarray([0.0, 0.1, 0.2, 0.4, 0.5, 0.7, 0.8]) elo = egrid[:-1] ehi = egrid[1:] specresp = np.asarray([10.2, 9.8, 10.0, 12.0, 8.0, 10.0]) with warnings.catch_warnings(record=True) as ws: warnings.simplefilter("always") adata = create_arf(elo, ehi, specresp, exposure=exposure1, ethresh=ethresh) validate_zero_replacement(ws, 'ARF', 'user-arf', ethresh) arf = ARF1D(adata) exposure2 = 2.4 channels = np.arange(1, 7, dtype=np.int16) counts = np.ones(6, dtype=np.int16) pha = DataPHA('test-pha', channel=channels, counts=counts, exposure=exposure2) pha.set_arf(adata) pha.set_analysis('energy') mdl = MyPowLaw1D() tmdl = PowLaw1D() wrapped = ARFModelPHA(arf, pha, mdl) out = wrapped([0.1, 0.2]) elo[0] = ethresh expected = specresp * tmdl(elo, ehi) assert_allclose(out, expected) assert not np.isnan(out[0])
def test_rsp1d_delta_pha_zero_energy_bin(): "What happens when the first bin starts at 0, with replacement" ethresh = 2.0e-7 # PHA and ARF have different exposure ties exposure1 = 0.1 exposure2 = 2.4 egrid = np.asarray([0.0, 0.1, 0.2, 0.4, 0.5, 0.7, 0.8]) elo = egrid[:-1] ehi = egrid[1:] specresp = np.asarray([10.2, 9.8, 10.0, 12.0, 8.0, 10.0]) with warnings.catch_warnings(record=True) as ws: warnings.simplefilter("always") adata = create_arf(elo, ehi, specresp, exposure=exposure1, ethresh=ethresh) validate_zero_replacement(ws, 'ARF', 'user-arf', ethresh) with warnings.catch_warnings(record=True) as ws: warnings.simplefilter("always") rdata = create_delta_rmf(elo, ehi, ethresh=ethresh) validate_zero_replacement(ws, 'RMF', 'delta-rmf', ethresh) channels = np.arange(1, 7, dtype=np.int16) counts = np.ones(6, dtype=np.int16) pha = DataPHA('test-pha', channel=channels, counts=counts, exposure=exposure2) pha.set_rmf(rdata) pha.set_arf(adata) pha.set_analysis('energy') mdl = MyPowLaw1D() tmdl = PowLaw1D() wrapped = RSPModelPHA(adata, rdata, pha, mdl) out = wrapped([0.1, 0.2]) elo[0] = ethresh expected = specresp * tmdl(elo, ehi) assert_allclose(out, expected) assert not np.isnan(out[0])
def test_rspmodelpha_delta_call_wave(): """What happens calling a rsp with a pha (RMF is a delta fn)? Wavelength. Unlike the energy case no bins are ignored, as this code path has already been tested. """ exposure = 200.1 estep = 0.025 egrid = np.arange(0.1, 0.8, estep) elo = egrid[:-1] ehi = egrid[1:] specresp = 2.4 * np.ones(elo.size, dtype=np.float32) specresp[2:5] = 0.0 specresp[16:19] = 3.2 adata = create_arf(elo, ehi, specresp, exposure=exposure) rdata = create_delta_rmf(elo, ehi, e_min=elo, e_max=ehi) nchans = elo.size constant = 2.3 mdl = Const1D('flat') mdl.c0 = constant channels = np.arange(1, nchans + 1, dtype=np.int16) counts = np.ones(nchans, dtype=np.int16) pha = DataPHA('test-pha', channel=channels, counts=counts, exposure=exposure) pha.set_rmf(rdata) pha.set_analysis('wave') wrapped = RSPModelPHA(adata, rdata, pha, mdl) # Note that this is a Sherpa model, so it's normalization is # per unit x axis, so when integrated here the bins are in # Angstroms, so the bin width to multiply by is # Angstroms, not keV. # dl = (DataPHA._hc / elo) - (DataPHA._hc / ehi) expected = constant * specresp * dl out = wrapped([4, 5]) assert_allclose(out, expected)
def test_arf1d_pha_zero_energy_bin(): "What happens when the first bin starts at 0, with replacement" ethresh = 1.0e-10 # Note: the two exposures are different to check which is # used (the answer is neither, which seems surprising) # exposure1 = 0.1 egrid = np.asarray([0.0, 0.1, 0.2, 0.4, 0.5, 0.7, 0.8]) elo = egrid[:-1] ehi = egrid[1:] specresp = np.asarray([10.2, 9.8, 10.0, 12.0, 8.0, 10.0]) with warnings.catch_warnings(record=True) as ws: warnings.simplefilter("always") adata = create_arf(elo, ehi, specresp, exposure=exposure1, ethresh=ethresh) validate_zero_replacement(ws, 'ARF', 'user-arf', ethresh) arf = ARF1D(adata) exposure2 = 2.4 channels = np.arange(1, 7, dtype=np.int16) counts = np.ones(6, dtype=np.int16) pha = DataPHA('test-pha', channel=channels, counts=counts, exposure=exposure2) pha.set_arf(adata) pha.set_analysis('energy') mdl = MyPowLaw1D() tmdl = PowLaw1D() wrapped = ARFModelPHA(arf, pha, mdl) out = wrapped([0.1, 0.2]) elo[0] = ethresh expected = specresp * tmdl(elo, ehi) assert_allclose(out, expected) assert not np.isnan(out[0])
def test_rspmodelpha_delta_call_wave(): """What happens calling a rsp with a pha (RMF is a delta fn)? Wavelength. Unlike the energy case no bins are ignored, as this code path has already been tested. """ exposure = 200.1 estep = 0.025 egrid = np.arange(0.1, 0.8, estep) elo = egrid[:-1] ehi = egrid[1:] specresp = 2.4 * np.ones(elo.size, dtype=np.float32) specresp[2:5] = 0.0 specresp[16:19] = 3.2 adata = create_arf(elo, ehi, specresp, exposure=exposure) rdata = create_delta_rmf(elo, ehi, e_min=elo, e_max=ehi) nchans = elo.size constant = 2.3 mdl = Const1D('flat') mdl.c0 = constant channels = np.arange(1, nchans + 1, dtype=np.int16) counts = np.ones(nchans, dtype=np.int16) pha = DataPHA('test-pha', channel=channels, counts=counts, exposure=exposure) pha.set_rmf(rdata) pha.set_analysis('wave') wrapped = RSPModelPHA(adata, rdata, pha, mdl) # Note that this is a Sherpa model, so it's normalization is # per unit x axis, so when integrated here the bins are in # Angstroms, so the bin width to multiply by is # Angstroms, not keV. # dl = (DataPHA._hc / elo) - (DataPHA._hc / ehi) expected = constant * specresp * dl out = wrapped([4, 5]) assert_allclose(out, expected)
def test_rspmodelpha_delta_call_channel(): """What happens calling a rsp with a pha (RMF is a delta fn)? Channels. I am not convinced I understand the bin width calculation here, as it doesn't seem to match the wavelength case. """ exposure = 200.1 estep = 0.025 egrid = np.arange(0.1, 0.8, estep) elo = egrid[:-1] ehi = egrid[1:] specresp = 2.4 * np.ones(elo.size, dtype=np.float32) specresp[2:5] = 0.0 specresp[16:19] = 3.2 adata = create_arf(elo, ehi, specresp, exposure=exposure) rdata = create_delta_rmf(elo, ehi, e_min=elo, e_max=ehi) nchans = elo.size constant = 2.3 mdl = Const1D('flat') mdl.c0 = constant channels = np.arange(1, nchans + 1, dtype=np.int16) counts = np.ones(nchans, dtype=np.int16) pha = DataPHA('test-pha', channel=channels, counts=counts, exposure=exposure) pha.set_rmf(rdata) pha.set_analysis('channel') wrapped = RSPModelPHA(adata, rdata, pha, mdl) # Since this is channels you might expect the bin width to be 1, # but it is actually still dE. # de = ehi - elo expected = constant * specresp * de out = wrapped([4, 5]) assert_allclose(out, expected)
def test_arf1d_no_pha_no_exposure_basic(): "Can we create an ARF with no PHA?" egrid = np.arange(0.1, 0.6, 0.1) adata = create_arf(egrid[:-1], egrid[1:]) arf = ARF1D(adata) assert arf._arf == adata assert arf._pha is None # Does the ARF1D pass through functionality to the DataARF? assert arf.name == 'user-arf' assert arf.exposure is None assert str(arf) == str(adata) assert dir(arf) == dir(adata) # Should be exact specresp = np.ones(egrid.size - 1, dtype=np.float32) assert (specresp == arf.specresp).all()
def test_arf1d_no_pha_no_exposure_basic(): "Can we create an ARF with no PHA?" egrid = np.arange(0.1, 0.6, 0.1) adata = create_arf(egrid[:-1], egrid[1:]) arf = ARF1D(adata) assert arf._arf == adata assert arf._pha is None # Does the ARF1D pass through functionality to the DataARF? assert arf.name == 'user-arf' assert arf.exposure is None assert str(arf) == str(adata) assert dir(arf) == dir(adata) # Should be exact specresp = np.ones(egrid.size - 1, dtype=np.float32) assert (specresp == arf.specresp).all()
def test_rspmodelpha_delta_call_channel(): """What happens calling a rsp with a pha (RMF is a delta fn)? Channels. I am not convinced I understand the bin width calculation here, as it doesn't seem to match the wavelength case. """ exposure = 200.1 estep = 0.025 egrid = np.arange(0.1, 0.8, estep) elo = egrid[:-1] ehi = egrid[1:] specresp = 2.4 * np.ones(elo.size, dtype=np.float32) specresp[2:5] = 0.0 specresp[16:19] = 3.2 adata = create_arf(elo, ehi, specresp, exposure=exposure) rdata = create_delta_rmf(elo, ehi, e_min=elo, e_max=ehi) nchans = elo.size constant = 2.3 mdl = Const1D('flat') mdl.c0 = constant channels = np.arange(1, nchans + 1, dtype=np.int16) counts = np.ones(nchans, dtype=np.int16) pha = DataPHA('test-pha', channel=channels, counts=counts, exposure=exposure) pha.set_rmf(rdata) pha.set_analysis('channel') wrapped = RSPModelPHA(adata, rdata, pha, mdl) # Since this is channels you might expect the bin width to be 1, # but it is actually still dE. # de = ehi - elo expected = constant * specresp * de out = wrapped([4, 5]) assert_allclose(out, expected)
def test_cstat_arfpha(): """What does CSTAT calculate when there is an ARF+PHA instrument model. The value here is technically wrong, in that the AREASCAL value is not being included in the calculation, but is included as a test to validate this use case. See Also -------- test_cstat_nophamodel, test_cstat_rmfpha, test_cstat_rsppha """ dset, mdl, expected = setup_likelihood(scale=True) # Use the channel grid as the "energy axis". # arf = create_arf(dset.channel, dset.channel + 1) mdl_ascal = ARFModelPHA(arf, dset, mdl) stat = CStat() sval_ascal = stat.calc_stat(dset, mdl_ascal) assert sval_ascal[0] == pytest.approx(expected)
def test_rmf1d_delta_arf_no_pha_call(): "Can we call an RMF (delta function) with ARF (no PHA)" egrid = np.arange(0.1, 0.6, 0.1) elo = egrid[:-1] ehi = egrid[1:] rdata = create_delta_rmf(elo, ehi) adata = create_arf(elo, ehi) rmf = RMF1D(rdata, arf=adata) mdl = Const1D('flat') mdl.c0 = 2.3 wrapped = rmf(mdl) # It seems like the wrapper should match the following: # assert isinstance(wrapped, RSPModelNoPHA) # but at the time the test was written (June 2017) it # does not. # assert isinstance(wrapped, RMFModelNoPHA) wmdl = wrapped.model assert wmdl == mdl
def test_rmf1d_delta_arf_no_pha_call(): "Can we call an RMF (delta function) with ARF (no PHA)" egrid = np.arange(0.1, 0.6, 0.1) elo = egrid[:-1] ehi = egrid[1:] rdata = create_delta_rmf(elo, ehi) adata = create_arf(elo, ehi) rmf = RMF1D(rdata, arf=adata) mdl = Const1D('flat') mdl.c0 = 2.3 wrapped = rmf(mdl) # It seems like the wrapper should match the following: # assert isinstance(wrapped, RSPModelNoPHA) # but at the time the test was written (June 2017) it # does not. # assert isinstance(wrapped, RMFModelNoPHA) wmdl = wrapped.model assert wmdl == mdl
from sherpa.astro.instrument import create_arf, create_delta_rmf from sherpa.astro.data import DataPHA from sherpa.astro.fake import fake_pha from sherpa.astro import io from sherpa.models import Const1D from sherpa.utils.testing import requires_data, requires_fits channels = np.arange(1, 4, dtype=np.int16) counts = np.ones(3, dtype=np.int16) bcounts = 1000 * counts ebins = np.asarray([1.1, 1.2, 1.4, 1.6]) elo = ebins[:-1] ehi = ebins[1:] arf = create_arf(elo, ehi) rmf = create_delta_rmf(elo, ehi, e_min=elo, e_max=ehi) @pytest.mark.parametrize("has_bkg", [True, False]) @pytest.mark.parametrize("is_source", [True, False]) def test_fake_pha_basic(has_bkg, is_source, reset_seed): """No background. See also test_fake_pha_add_background For simplicity we use perfect responses. A background dataset can be added, but it should not be used in the simulation with default settings """
def test_rsp_normf_call(arfexp, phaexp): """Check out Response1D with no RMF. analysis is the analysis setting arfexp determines whether the arf has an exposure time phaexp determines whether the PHA has an exposure time This only uses the channel setting """ # Chose different exposure times for ARF and PHA to see which # gets picked up. # if arfexp: arf_exposure = 200.1 else: arf_exposure = None if phaexp: pha_exposure = 220.9 else: pha_exposure = None if phaexp: exposure = pha_exposure mdl_label = '({} * flat)'.format(exposure) elif arfexp: exposure = arf_exposure mdl_label = '({} * flat)'.format(exposure) else: exposure = 1.0 mdl_label = 'flat' # rdata is only used to define the grids rdata = create_non_delta_rmf() specresp = create_non_delta_specresp() adata = create_arf(rdata.energ_lo, rdata.energ_hi, specresp, exposure=arf_exposure) constant = 2.3 mdl = Const1D('flat') mdl.c0 = constant # Turn off integration on this model, so that it is not integrated # across the bin width. # mdl.integrate = False nchans = rdata.e_min.size channels = np.arange(1, nchans + 1, dtype=np.int16) counts = np.ones(nchans, dtype=np.int16) pha = DataPHA('test-pha', channel=channels, counts=counts, exposure=pha_exposure) pha.set_arf(adata) rsp = Response1D(pha) wrapped = rsp(mdl) assert isinstance(wrapped, ArithmeticModel) expname = 'apply_arf({})'.format(mdl_label) assert wrapped.name == expname expected = exposure * constant * specresp pha.set_analysis('channel') out = wrapped([4, 5]) assert_allclose(out, expected)
def test_rsp_normf_call(arfexp, phaexp): """Check out Response1D with no RMF. analysis is the analysis setting arfexp determines whether the arf has an exposure time phaexp determines whether the PHA has an exposure time This only uses the channel setting """ # Chose different exposure times for ARF and PHA to see which # gets picked up. # if arfexp: arf_exposure = 200.1 else: arf_exposure = None if phaexp: pha_exposure = 220.9 else: pha_exposure = None if phaexp: exposure = pha_exposure mdl_label = '({} * flat)'.format(exposure) elif arfexp: exposure = arf_exposure mdl_label = '({} * flat)'.format(exposure) else: exposure = 1.0 mdl_label = 'flat' # rdata is only used to define the grids rdata = create_non_delta_rmf() specresp = create_non_delta_specresp() adata = create_arf(rdata.energ_lo, rdata.energ_hi, specresp, exposure=arf_exposure) constant = 2.3 mdl = Const1D('flat') mdl.c0 = constant # Turn off integration on this model, so that it is not integrated # across the bin width. # mdl.integrate = False nchans = rdata.e_min.size channels = np.arange(1, nchans + 1, dtype=np.int16) counts = np.ones(nchans, dtype=np.int16) pha = DataPHA('test-pha', channel=channels, counts=counts, exposure=pha_exposure) pha.set_arf(adata) rsp = Response1D(pha) wrapped = rsp(mdl) assert isinstance(wrapped, ArithmeticModel) expname = 'apply_arf({})'.format(mdl_label) assert wrapped.name == expname expected = exposure * constant * specresp pha.set_analysis('channel') out = wrapped([4, 5]) assert_allclose(out, expected)