def test_save_data_data2d(tmp_path): """Does save_data work for Data2D?""" from sherpa.astro.io import backend y, x = np.mgrid[20:22, 10:13] x = x.flatten() y = y.flatten() z = (x - 15)**2 + (y - 12)**2 ui.load_arrays(1, x, y, z, (2, 3), ui.Data2D) out = tmp_path / "data.dat" outfile = str(out) ui.save_data(outfile) cts = out.read_text() # the output depends on the backend, and neither seems ideal # if backend.__name__ == 'sherpa.astro.io.crates_backend': expected = ["#TEXT/SIMPLE", "# X0 X1 Y SHAPE"] s = [2, 3, 0, 0, 0, 0] for xi, yi, zi, si in zip(x, y, z, s): expected.append(f"{xi} {yi} {zi} {si}") expected = "\n".join(expected) + "\n" elif backend.__name__ == 'sherpa.astro.io.pyfits_backend': expected = "\n".join([str(zz) for zz in z]) + "\n" else: raise RuntimeError(f"UNKNOWN I/O BACKEND: {backend.__name__}") assert cts == expected
def test_warnings_are_gone_arrays(self): ui.load_arrays(1, [1, 2, 3], [4, 5, 6]) # We now have logic in conftest.py to catch white-listed warnings and fail on unexpected ones. # We just need to make any warnings bubble up, here and in the following test. with NamedTemporaryFile() as f: ui.save_data(1, f.name, ascii=True, clobber=True) with NamedTemporaryFile() as f: ui.save_data(1, f.name, ascii=False, clobber=True)
def test_warnings_are_gone_pha(self): pha = self.make_path("3c273.pi") with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") with NamedTemporaryFile() as f: ui.load_pha(pha) ui.save_data(1, f.name, ascii=False, clobber=True) assert len(w) == 0
def test_warnings_are_gone_arrays(self): with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") with NamedTemporaryFile() as f: ui.load_arrays(1, [1, 2, 3], [4, 5, 6]) ui.save_data(1, f.name, ascii=True, clobber=True) with NamedTemporaryFile() as f: ui.save_data(1, f.name, ascii=False, clobber=True) assert len(w) == 0
def test_warnings_are_gone_arrays(self): with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") with NamedTemporaryFile() as f: ui.load_arrays(1, [1,2,3], [4,5,6]) ui.save_data(1, f.name, ascii=True, clobber=True) with NamedTemporaryFile() as f: ui.save_data(1, f.name, ascii=False, clobber=True) assert len(w) == 0
def test_save_data_data1dint(tmp_path): """Does save_data work for Data1DInt?""" ui.load_arrays(1, [1, 2, 4], [2, 3, 5], [5, 4, 3], ui.Data1DInt) out = tmp_path / "data.dat" outfile = str(out) ui.save_data(outfile) cts = out.read_text() check_output(cts, ['XLO', 'XHI', 'Y'], [[1, 2, 5], [2, 3, 4], [4, 5, 3]])
def test_save_data_data1d_clobber(tmp_path): """save_data: does clobber=True work?""" ui.load_arrays(1, [1], [5], ui.Data1D) out = tmp_path / "data.dat" outfile = str(out) out.write_text('some text') ui.save_data(outfile, clobber=True) cts = out.read_text() check_output(cts, ['X', 'Y'], [[1, 5]])
def test_save_data_data1d_fits(tmp_path): """Does save_data work for Data1D? FITS""" from sherpa.astro.io import read_table_blocks ui.load_arrays(1, [1, 2, 3], [5, 4, 3], ui.Data1D) out = tmp_path / "data.dat" outfile = str(out) ui.save_data(outfile, ascii=False) ans = read_table_blocks(outfile) blocks = ans[1] assert len(blocks) == 2 check_table(blocks[2], {'X': [1, 2, 3], 'Y': [5, 4, 3]})
def test_save_data_datapha(tmp_path): """Does save_data work for DataPHA?""" # This import requires an I/O backend hence it is done here # from sherpa.astro.io.meta import Meta ui.load_arrays(1, [1, 2, 3], [5, 4, 3], ui.DataPHA) # The code requires DataPHA to have a "valid" header so # fake one. Ideally we would not require it. # hdr = Meta() ui.get_data().header = hdr out = tmp_path / "data.dat" outfile = str(out) ui.save_data(outfile) cts = out.read_text() check_output(cts, ['CHANNEL', 'COUNTS'], [[1, 5], [2, 4], [3, 3]])
def test_save_data_dataimg(tmp_path): """Does save_data work for DataIMG? ASCII""" # Can not write out an ASCII image with crates from sherpa.astro.io import backend if backend.__name__ == 'sherpa.astro.io.crates_backend': pytest.skip('ASCII not supported for images with pycrates') y, x = np.mgrid[0:2, 0:3] x = x.flatten() y = y.flatten() z = (x - 1)**2 + y**2 ui.load_arrays(1, x, y, z, (2, 3), ui.DataIMG) out = tmp_path / "data.dat" outfile = str(out) ui.save_data(outfile) cts = out.read_text() expected = "\n".join([str(zz) for zz in z]) + "\n" assert cts == expected
def containment_fraction(self, theta, npix=1000): """Compute fraction of PSF contained inside theta.""" import sherpa.astro.ui as sau sau.dataspace2d((npix, npix)) self.set() # x_center = get_psf().kernel.pars.xpos # y_center = get_psf().kernel.pars.ypos x_center, y_center = sau.get_psf().model.center x_center, y_center = x_center + 0.5, y_center + 0.5 # shift seen on image. x, y = sau.get_data().x0, sau.get_data().x1 # @note Here we have to use the source image, before I used # get_model_image(), which returns the PSF-convolved PSF image, # which is a factor of sqrt(2) ~ 1.4 too wide!!! p = sau.get_source_image().y.flatten() p /= np.nansum(p) mask = (x - x_center) ** 2 + (y - y_center) ** 2 < theta ** 2 fraction = np.nansum(p[mask]) if 0: # debug sau.get_data().y = p sau.save_data('psf_sherpa.fits', clobber=True) sau.get_data().y = mask.astype('int') sau.save_data('mask_sherpa.fits', clobber=True) return fraction
def containment_fraction(self, theta, npix=1000): """Compute fraction of PSF contained inside theta.""" import sherpa.astro.ui as sau sau.dataspace2d((npix, npix)) self.set() # x_center = get_psf().kernel.pars.xpos # y_center = get_psf().kernel.pars.ypos x_center, y_center = sau.get_psf().model.center x_center, y_center = x_center + 0.5, y_center + 0.5 # shift seen on image. x, y = sau.get_data().x0, sau.get_data().x1 # Note: Here we have to use the source image, before I used # get_model_image(), which returns the PSF-convolved PSF image, # which is a factor of sqrt(2) ~ 1.4 too wide!!! p = sau.get_source_image().y.flatten() p /= np.nansum(p) mask = (x - x_center)**2 + (y - y_center)**2 < theta**2 fraction = np.nansum(p[mask]) if 0: # debug sau.get_data().y = p sau.save_data('psf_sherpa.fits', clobber=True) sau.get_data().y = mask.astype('int') sau.save_data('mask_sherpa.fits', clobber=True) return fraction
def test_save_data_dataimg_fits(tmp_path): """Does save_data work for DataIMG? FITS""" from sherpa.astro.io import read_image y, x = np.mgrid[10:12, 20:23] x = x.flatten() y = y.flatten() z = (x - 11)**2 + (y - 21)**2 ui.load_arrays(1, x, y, z, (2, 3), ui.DataIMG) out = tmp_path / "data.dat" outfile = str(out) ui.save_data(outfile, ascii=False) ans = read_image(outfile) assert ans.shape == (2, 3) # Is this correct? yl, xl = np.mgrid[1:3, 1:4] xl = xl.flatten() yl = yl.flatten() assert ans.x0 == pytest.approx(xl) assert ans.x1 == pytest.approx(yl) assert ans.y == pytest.approx(z)
def test_warnings_are_gone_pha(self): pha = self.make_path("3c273.pi") ui.load_pha(pha) with NamedTemporaryFile() as f: ui.save_data(1, f.name, ascii=False, clobber=True)
import sherpa.astro.ui as sau # Define width of the source and the PSF sigma_psf, sigma_source = 3, 4 # for relation of sigma and fwhm see # http://cxc.harvard.edu/sherpa/ahelp/gauss2d.html sigma_to_fwhm = np.sqrt(8 * np.log(2)) # ~ 2.35 sigma = np.sqrt(sigma_psf**2 + sigma_source**2) fwhm = sigma_to_fwhm * sigma # Seed the random number generator to make the output reproducible np.random.seed(0) sau.dataspace2d((200, 200)) sau.set_source('normgauss2d.source + const2d.background') sau.set_par('source.xpos', 100) sau.set_par('source.ypos', 100) sau.set_par('source.ampl', 1e3) sau.set_par('source.fwhm', fwhm) sau.set_par('background.c0', 1) sau.fake() sau.save_model('model.fits.gz', clobber=True) sau.save_data('counts.fits.gz', clobber=True) sau.set_source('source') sau.save_model('source.fits.gz', clobber=True) sau.set_source('background') sau.save_model('background.fits.gz', clobber=True)
import sherpa.astro.ui as sau # Define width of the source and the PSF sigma_psf, sigma_source = 3, 4 # for relation of sigma and fwhm see # http://cxc.harvard.edu/sherpa/ahelp/gauss2d.html sigma_to_fwhm = np.sqrt(8 * np.log(2)) # ~ 2.35 sigma = np.sqrt(sigma_psf ** 2 + sigma_source ** 2) fwhm = sigma_to_fwhm * sigma # Seed the random number generator to make the output reproducible np.random.seed(0) sau.dataspace2d((200, 200)) sau.set_source('normgauss2d.source + const2d.background') sau.set_par('source.xpos', 100) sau.set_par('source.ypos', 100) sau.set_par('source.ampl', 1e3) sau.set_par('source.fwhm', fwhm) sau.set_par('background.c0', 1) sau.fake() sau.save_model('model.fits.gz', clobber=True) sau.save_data('counts.fits.gz', clobber=True) sau.set_source('source') sau.save_model('source.fits.gz', clobber=True) sau.set_source('background') sau.save_model('background.fits.gz', clobber=True)