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_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_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 = make_arf(energ_lo=dset.channel, energ_hi=dset.channel + 1) mdl_ascal = ARFModelPHA(arf, dset, mdl) stat = CStat() sval_ascal = stat.calc_stat(dset, mdl_ascal) assert_allclose(sval_ascal[0], expected)