diff --git a/doc/release_notes.rst b/doc/release_notes.rst index 68c45e2..18e59d5 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -2,16 +2,16 @@ desimodel Release Notes ======================= -0.8.1 (unreleased) +0.9.0 (unreleased) ------------------ -() + * Added desimodel.focalplane.radec2xy, which converts RA, Dec coordinates to x, y coordinates on the focal plane, which accepts vector inputs. * Added desimodel.focalplane.on_gfa() and its respective helper functions to check if a target is on a GFA of arbitrary telescope pointing * Added desimodel.focalplane.on_tile_gfa() to check return a list of indices of targets on a specific tile * Added desimodel.focalplane.get_gfa_targets() to return a table with added columns GFA_LOC and TILEID that consists of all targets on any GFA on any tile satisfying a minimum flux in the r-band. * Unittests for the desimodel.focalplane functions were updated accordingly. * Added desimodel.footprint.find_points_in_tel_range() to return a list of indices withnin a radius of an arbitray telescope pointing, unaware of tiles (Added respective unittest) - +* Updates tests to work with trimmed data subset 0.8.0 (2017-08-07) ------------------ diff --git a/py/desimodel/focalplane.py b/py/desimodel/focalplane.py index d970c58..809a463 100644 --- a/py/desimodel/focalplane.py +++ b/py/desimodel/focalplane.py @@ -622,7 +622,7 @@ def on_gfa(telra, teldec, ra, dec, buffer_arcsec = 100): newtargetindices = np.where(targetarea < AREA_BOUNDARY) targetindices.extend(newtargetindices[0]) gfaindices.extend([int(gfaid / 4)] * len(newtargetindices[0])) - return inrangeindices[targetindices], gfaindices + return inrangeindices[targetindices], np.asarray(gfaindices) def _retrieve_minimum_boundary(x_tolerance, y_tolerance): """ diff --git a/py/desimodel/footprint.py b/py/desimodel/footprint.py index 9dacc4a..e2b6926 100644 --- a/py/desimodel/footprint.py +++ b/py/desimodel/footprint.py @@ -500,13 +500,11 @@ def find_points_radec(telra, teldec, ra, dec, radius = None): def get_tile_radec(tileid): """Return (ra, dec) in degrees for the requested tileid. - If tileid is not in DESI, return (0.0, 0.0) - TODO: should it raise and exception instead? + Raises ValueError if tileid is not in list of known tiles """ tiles = io.load_tiles() if tileid in tiles['TILEID']: i = np.where(tiles['TILEID'] == tileid)[0][0] return tiles[i]['RA'], tiles[i]['DEC'] else: - return (0.0, 0.0) - + raise ValueError('Unknown tileid {}'.format(tileid)) diff --git a/py/desimodel/io.py b/py/desimodel/io.py index a33d668..6c0ee80 100644 --- a/py/desimodel/io.py +++ b/py/desimodel/io.py @@ -209,6 +209,17 @@ def load_platescale(): _platescale = np.loadtxt(infile, usecols=[0,1,6,7], dtype=columns) return _platescale +def reset_cache(): + '''Reset I/O cache''' + global _thru, _psf, _params, _gfa, _fiberpos, _tiles, _platescale + _thru = dict() + _psf = dict() + _params = None + _gfa = None + _fiberpos = None + _tiles = dict() + _platescale = None + def load_target_info(): ''' Loads data/targets/targets.yaml and returns the nested dictionary diff --git a/py/desimodel/test/test_focalplane.py b/py/desimodel/test/test_focalplane.py index 51c16f9..b92eb44 100644 --- a/py/desimodel/test/test_focalplane.py +++ b/py/desimodel/test/test_focalplane.py @@ -6,7 +6,8 @@ import numpy as np from ..focalplane import FocalPlane, generate_random_centroid_offsets, xy2radec, get_radius_mm, get_radius_deg, radec2xy from ..focalplane import fiber_area_arcsec2, on_gfa, on_tile_gfa, get_gfa_targets - +from .. import io +from astropy.table import Table class TestFocalplane(unittest.TestCase): """Test desimodel.focalplane. @@ -113,32 +114,34 @@ def test_on_gfa(self): def test_on_tile_gfa(self): """Tests if on_tile_gfa returns two lists as it is supposed to""" - tiles = np.zeros((4,), dtype=[('TILEID', 'i2'), - ('RA', 'f8'), - ('DEC', 'f8'), - ]) - tiles['TILEID'] = np.array([23658] * 4) - tiles['RA'] = np.array([0.0, 1.0, 2.0, 3.0]) - tiles['DEC'] = np.array([-2.0, -1.0, 1.0, 2.0]) - targetindices, gfaid = on_tile_gfa(23658, tiles, 120) - self.assertEqual(0, targetindices.size) - self.assertEqual(0, gfaid.size) + #- Generate some targets near a tile; some should land on the GFAs + tile = io.load_tiles()[0] + targets = Table() + ntargets = 1000 + ra = np.random.uniform(tile['RA']-1.61, tile['RA']+1.61, size=ntargets) + dec = np.random.uniform(tile['DEC']-1.61, tile['DEC']+1.61, size=ntargets) + targets['RA'] = (ra+360) % 360 + targets['DEC'] = dec + targetindices, gfaid = on_tile_gfa(tile['TILEID'], targets, 120) self.assertEqual(targetindices.size, gfaid.size) - - def test_get_gfa_targets(self): - """Tests if get_gfa_targets returns a table of targets on gfa""" - tiles = np.zeros((4,), dtype=[('TILEID', 'i2'), - ('RA', 'f8'), - ('DEC', 'f8'), - ('FLUX_R', 'f8') - ]) - tiles['TILEID'] = np.array([23658] * 4) - tiles['RA'] = [0.0, 1.0, 2.0, 3.0] - tiles['DEC'] = [-2.0, -1.0, 1.0, 2.0] - tiles['FLUX_R'] = [50, 50, 50, 100] - targets = get_gfa_targets(tiles) - self.assertEqual(len(targets), 0) - + self.assertGreater(targetindices.size, 0) + self.assertLess(np.max(targetindices), ntargets) + self.assertLess(np.max(gfaid), 10) + self.assertGreaterEqual(np.min(gfaid), 0) + + #- Test higher level get_gfa_targets + targets['FLUX_R'] = 2000 + gfatargets = get_gfa_targets(targets, rfluxlim=1000) + self.assertGreater(len(gfatargets), 0) + self.assertLess(np.max(gfatargets['GFA_LOC']), 10) + self.assertGreaterEqual(np.min(gfatargets['GFA_LOC']), 0) + self.assertTrue(tile['TILEID'] in gfatargets['TILEID']) + + #- Shift +60 deg and verify that none are found for that tile + targets['RA'] = (targets['RA'] + 60) % 360 + targetindices, gfaid = on_tile_gfa(tile['TILEID'], targets, 120) + self.assertEqual(targetindices.size, 0) + self.assertEqual(gfaid.size, 0) def test_suite(): diff --git a/py/desimodel/test/test_footprint.py b/py/desimodel/test/test_footprint.py index 0bd72b9..3d048f5 100644 --- a/py/desimodel/test/test_footprint.py +++ b/py/desimodel/test/test_footprint.py @@ -16,16 +16,13 @@ class TestFootprint(unittest.TestCase): def setUp(self): - pass + io.reset_cache() def test_get_tile_radec(self): """Test grabbing tile information by tileID. """ - io_tile_cache = io._tiles - io._tiles = dict() tx = io.load_tiles() tilefile = list(io._tiles.keys())[0] - tiles = np.zeros((4,), dtype=[('TILEID', 'i2'), ('RA', 'f8'), ('DEC', 'f8'), @@ -39,11 +36,14 @@ def test_get_tile_radec(self): tiles['IN_DESI'] = [0, 1, 1, 0] tiles['PROGRAM'] = 'DARK' io._tiles[tilefile] = tiles - ra, dec = footprint.get_tile_radec(1) - self.assertEqual((ra, dec), (0.0, 0.0)) + + #- TILEID 1 should be filtered out as not in DESI + with self.assertRaises(ValueError): + ra, dec = footprint.get_tile_radec(1) + + #- But TILEID 2 should be there with correct redshift ra, dec, = footprint.get_tile_radec(2) self.assertEqual((ra, dec), (1.0, -1.0)) - io._tiles = io_tile_cache def test_is_point_in_desi_mock(self): tiles = np.zeros((4,), dtype=[('TILEID', 'i2'), diff --git a/py/desimodel/test/test_io.py b/py/desimodel/test/test_io.py index 5cc7380..f4e9bbb 100644 --- a/py/desimodel/test/test_io.py +++ b/py/desimodel/test/test_io.py @@ -54,18 +54,29 @@ def setUp(self): """Ensure that any desimodel.io caches are clear before running any test. """ - io._thru = dict() - io._psf = dict() - io._params = None - io._gfa = None - io._fiberpos = None - io._tiles = dict() + io.reset_cache() if os.path.exists(self.testfile): os.remove(self.testfile) def tearDown(self): pass + def test_reset_cache(self): + """Test cache reset (two examples at least) + """ + self.assertTrue(io._fiberpos is None) + self.assertTrue(isinstance(io._tiles, dict)) + self.assertEqual(len(io._tiles), 0) + fiberpos = io.load_fiberpos() + tiles = io.load_tiles() + self.assertTrue(io._fiberpos is not None) + self.assertTrue(isinstance(io._tiles, dict)) + self.assertEqual(len(io._tiles), 1) + io.reset_cache() + self.assertTrue(io._fiberpos is None) + self.assertTrue(isinstance(io._tiles, dict)) + self.assertEqual(len(io._tiles), 0) + @unittest.skipUnless(specter_available, specter_message) def test_load_throughput(self): """Test loading of throughput files. diff --git a/py/desimodel/trim.py b/py/desimodel/trim.py index cee6647..e40ff94 100644 --- a/py/desimodel/trim.py +++ b/py/desimodel/trim.py @@ -62,7 +62,8 @@ def trim_footprint(indir, outdir): infile, outfile = inout(indir, outdir, 'desi-tiles.fits') with fits.open(infile) as hdulist: t = Table(hdulist[1].data) - ii = (110 < t['RA']) & (t['RA'] < 140) & (-10 < t['DEC']) & (t['DEC'] < 20) + #- Pick a subset on edge of footprint where healpix testing is done + ii = (35 < t['RA']) & (t['RA'] < 55) & (-10 < t['DEC']) & (t['DEC'] < 20) tx = t[ii] tx.write(outfile, format='fits') tx.write(outfile.replace('.fits', '.ecsv'), format='ascii.ecsv')