From b9fc49caa1d092528d56c8e7a205971dadf4eb75 Mon Sep 17 00:00:00 2001 From: Wilfred Gee Date: Fri, 23 Nov 2018 15:30:39 +1100 Subject: [PATCH] Removing dithering from huntsman-pocs as these items have been merged upstream --- huntsman/observatory.py | 2 +- huntsman/scheduler/dispatch.py | 2 +- huntsman/tests/test_dither.py | 186 --------------------------------- huntsman/utils/dither.py | 107 ------------------- huntsman/utils/hdr.py | 2 +- 5 files changed, 3 insertions(+), 296 deletions(-) delete mode 100644 huntsman/tests/test_dither.py delete mode 100644 huntsman/utils/dither.py diff --git a/huntsman/observatory.py b/huntsman/observatory.py index b566277e..29dbbf62 100644 --- a/huntsman/observatory.py +++ b/huntsman/observatory.py @@ -11,11 +11,11 @@ from pocs.scheduler.observation import Field from pocs.utils import error from pocs import utils +from pocs.utils import dither from pocs.utils.images import fits as fits_utils from huntsman.guide.bisque import Guide from huntsman.scheduler.observation import DitheredObservation -from huntsman.utils import dither from huntsman.utils import load_config diff --git a/huntsman/scheduler/dispatch.py b/huntsman/scheduler/dispatch.py index dcd0678e..f06b6ea9 100644 --- a/huntsman/scheduler/dispatch.py +++ b/huntsman/scheduler/dispatch.py @@ -4,9 +4,9 @@ from pocs.scheduler.field import Field from pocs.utils import current_time from pocs.scheduler.observation import Observation +from pocs.utils import dither from huntsman.scheduler.observation import DitheredObservation -from huntsman.utils import dither class Scheduler(dispatch.Scheduler): diff --git a/huntsman/tests/test_dither.py b/huntsman/tests/test_dither.py deleted file mode 100644 index f00bb9c1..00000000 --- a/huntsman/tests/test_dither.py +++ /dev/null @@ -1,186 +0,0 @@ -import pytest -import astropy.units as u -from astropy.coordinates import SkyCoord, Angle - -from huntsman.utils import dither - - -def test_dice9_SkyCoord(): - base = SkyCoord("16h52m42.2s -38d37m12s") - - positions = dither.get_dither_positions(base_position=base, - n_positions=12, - pattern=dither.dice9, - pattern_offset=30 * u.arcminute) - - assert isinstance(positions, SkyCoord) - assert len(positions) == 12 - # postion 0 should be the base position - assert positions[0].separation(base) < Angle(1e12 * u.degree) - # With no random offset positions 9, 10, 11 should be the same as 0, 1, 2 - assert positions[0:3].to_string() == positions[9:12].to_string() - # Position 1 should be 30 arcminute offset from base, in declination direction only - assert base.spherical_offsets_to( - positions[1])[0].radian == pytest.approx(Angle(0 * u.degree).radian) - assert base.spherical_offsets_to( - positions[1])[1].radian == pytest.approx(Angle(0.5 * u.degree).radian) - # Position 3 should be 30 arcminute offset from base in RA only. - assert base.spherical_offsets_to( - positions[3])[0].radian == pytest.approx(Angle(0.5 * u.degree).radian) - assert base.spherical_offsets_to( - positions[3])[1].radian == pytest.approx(Angle(0 * u.degree).radian) - - -def test_dice9_string(): - base = "16h52m42.2s -38d37m12s" - - positions = dither.get_dither_positions(base_position=base, - n_positions=12, - pattern=dither.dice9, - pattern_offset=30 * u.arcminute) - - base = SkyCoord(base) - - assert isinstance(positions, SkyCoord) - assert len(positions) == 12 - # postion 0 should be the base position - assert positions[0].separation(base) < Angle(1e12 * u.degree) - # With no random offset positions 9, 10, 11 should be the same as 0, 1, 2 - assert positions[0:3].to_string() == positions[9:12].to_string() - # Position 1 should be 30 arcminute offset from base, in declination direction only - assert base.spherical_offsets_to( - positions[1])[0].radian == pytest.approx(Angle(0 * u.degree).radian) - assert base.spherical_offsets_to( - positions[1])[1].radian == pytest.approx(Angle(0.5 * u.degree).radian) - # Position 3 should be 30 arcminute offset from base in RA only. - assert base.spherical_offsets_to( - positions[3])[0].radian == pytest.approx(Angle(0.5 * u.degree).radian) - assert base.spherical_offsets_to( - positions[3])[1].radian == pytest.approx(Angle(0 * u.degree).radian) - - -def test_dice9_bad(): - with pytest.raises(ValueError): - dither.get_dither_positions(base_position=42, - n_positions=42, - pattern=dither.dice9, - pattern_offset=300 * u.arcsecond) - - with pytest.raises(ValueError): - dither.get_dither_positions(base_position="16h52m42.2s -38d37m12s", - n_positions=42, - pattern=dither.dice9) - - -def test_dice9_random(): - base = SkyCoord("16h52m42.2s -38d37m12s") - - positions = dither.get_dither_positions(base_position=base, - n_positions=12, - pattern=dither.dice9, - pattern_offset=30 * u.arcminute, - random_offset=30 * u.arcsecond) - - assert isinstance(positions, SkyCoord) - assert len(positions) == 12 - # postion 0 should be the base position - assert positions[0].separation(base) < Angle(30 * 2**0.5 * u.arcsecond) - # Position 1 should be 30 arcminute offset from base, in declination direction only - assert base.spherical_offsets_to(positions[1])[0].radian == pytest.approx(Angle(0 * u.degree).radian, - abs=Angle(30 * u.arcsecond).radian) - assert base.spherical_offsets_to(positions[1])[1].radian == pytest.approx(Angle(0.5 * u.degree).radian, - abs=Angle(30 * u.arcsecond).radian) - # Position 3 should be 30 arcminute offset from base in RA only. - assert base.spherical_offsets_to(positions[3])[0].radian == pytest.approx(Angle(0.5 * u.degree).radian, - abs=Angle(30 * u.arcsecond).radian) - assert base.spherical_offsets_to(positions[3])[1].radian == pytest.approx(Angle(0 * u.degree).radian, - abs=Angle(30 * u.arcsecond).radian) - - -def test_random(): - base = SkyCoord("16h52m42.2s -38d37m12s") - - positions = dither.get_dither_positions(base_position=base, - n_positions=12, - random_offset=30 * u.arcsecond) - assert isinstance(positions, SkyCoord) - assert len(positions) == 12 - - assert base.spherical_offsets_to(positions[0])[0].radian == pytest.approx(Angle(0 * u.degree).radian, - abs=Angle(30 * u.arcsecond).radian) - assert base.spherical_offsets_to(positions[0])[1].radian == pytest.approx(Angle(0 * u.degree).radian, - abs=Angle(30 * u.arcsecond).radian) - - assert base.spherical_offsets_to(positions[1])[0].radian == pytest.approx(Angle(0 * u.degree).radian, - abs=Angle(30 * u.arcsecond).radian) - assert base.spherical_offsets_to(positions[1])[1].radian == pytest.approx(Angle(0 * u.degree).radian, - abs=Angle(30 * u.arcsecond).radian) - - -def test_dice5(): - base = SkyCoord("16h52m42.2s -38d37m12s") - - positions = dither.get_dither_positions(base_position=base, - n_positions=12, - pattern=dither.dice5, - pattern_offset=30 * u.arcminute) - - assert isinstance(positions, SkyCoord) - assert len(positions) == 12 - # postion 0 should be the base position - assert positions[0].separation(base) < Angle(1e12 * u.degree) - # With no random offset positions 5, 6, 7 should be the same as 0, 1, 2 - assert positions[0:3].to_string() == positions[5:8].to_string() - # Position 1 should be 30 arcminute offset from base, in RA and dec - assert base.spherical_offsets_to( - positions[1])[0].radian == pytest.approx(Angle(0.5 * u.degree).radian) - assert base.spherical_offsets_to( - positions[1])[1].radian == pytest.approx(Angle(0.5 * u.degree).radian) - # Position 3 should be 30 arcminute offset from base in RA and dec - assert base.spherical_offsets_to(positions[3])[0].radian == pytest.approx( - Angle(-0.5 * u.degree).radian) - assert base.spherical_offsets_to(positions[3])[1].radian == pytest.approx( - Angle(-0.5 * u.degree).radian) - - -def test_custom_pattern(): - base = SkyCoord("16h52m42.2s -38d37m12s") - cross = ((0, 0), - (0, 1), - (1, 0), - (0, -1), - (-1, 0)) - - positions = dither.get_dither_positions(base_position=base, - n_positions=12, - pattern=cross, - pattern_offset=1800 * u.arcsecond) - - assert isinstance(positions, SkyCoord) - assert len(positions) == 12 - # postion 0 should be the base position - assert positions[0].separation(base) < Angle(1e12 * u.degree) - # With no random offset positions 5, 6, 7 should be the same as 0, 1, 2 - assert positions[0:3].to_string() == positions[5:8].to_string() - # Position 3 should be 30 arcminute offset from base, in declination direction only - assert base.spherical_offsets_to( - positions[3])[0].radian == pytest.approx(Angle(0 * u.degree).radian) - assert base.spherical_offsets_to(positions[3])[1].radian == pytest.approx( - Angle(-0.5 * u.degree).radian) - # Position 4 should be 30 arcminute offset from base in RA only. - assert base.spherical_offsets_to(positions[4])[0].radian == pytest.approx( - Angle(-0.5 * u.degree).radian) - assert base.spherical_offsets_to( - positions[4])[1].radian == pytest.approx(Angle(0 * u.degree).radian) - - -def test_plot(tmpdir): - base = SkyCoord("16h52m42.2s -38d37m12s") - plot_path = tmpdir.join('dither_test.png') - - positions = dither.get_dither_positions(base_position=base, - n_positions=12, - pattern=dither.dice9, - pattern_offset=30 * u.arcminute, - plot=plot_path.strpath) - assert plot_path.check() diff --git a/huntsman/utils/dither.py b/huntsman/utils/dither.py deleted file mode 100644 index a1b7f58a..00000000 --- a/huntsman/utils/dither.py +++ /dev/null @@ -1,107 +0,0 @@ -import numpy as np -import astropy.units as u -from astropy.coordinates import SkyCoord, SkyOffsetFrame, ICRS -from astropy.wcs import WCS - -import matplotlib.pyplot as plt - -# Pattern for dice 9 3x3 grid (sequence of (RA offset, dec offset) pairs) -dice9 = ((0, 0), - (0, 1), - (1, 1), - (1, 0), - (1, -1), - (0, -1), - (-1, -1), - (-1, 0), - (-1, 1)) - - -# Pattern for dice 5 grid (sequence of (RA offset, dec offset) pairs) -dice5 = ((0, 0), - (1, 1), - (1, -1), - (-1, -1), - (-1, 1)) - - -def get_dither_positions(base_position, n_positions, pattern=None, pattern_offset=None, random_offset=None, plot=False): - """ - Given a base position creates a SkyCoord list of dithered sky positions, applying a dither pattern and/or - random dither offsets. - - Args: - base_position (SkyCoord or compatible): base position for the dither pattern, either a SkyCoord or an object - that can be converted to one by the SkyCoord constructor (e.g. string) - n_positions (int): number of dithered sky positions to generate - pattern (sequence of 2-tuples, optional): sequence of (RA offset, dec offset) tuples, in units of the - pattern_offset. If given pattern_offset must also be specified. - pattern_offset (Quantity, optional): scale for the dither pattern. Should be a Quantity with angular - units, if a numeric type is passed instead it will be assumed to be in arceconds. If pattern offset is - given pattern must be given too. - random_offset (Quantity, optional): scale of the random offset to apply to both RA and dec. Should be a - Quantity with angular units, if numeric type passed instead it will be assumed to be in arcseconds. - plots (optional, default False): If False no plots will be created, otherwise plots will be generated and - written to filename `plots`. - - Returns: - SkyCoord: list of n_positions dithered sky positions - """ - if not isinstance(base_position, SkyCoord): - try: - base_position = SkyCoord(base_position) - except ValueError: - raise ValueError( - "Base position '{}' could not be converted to a SkyCoord object!".format(base_position)) - - if pattern: - if not pattern_offset: - raise ValueError("`pattern` specified but no `pattern_offset` given!") - - if not isinstance(pattern_offset, u.Quantity): - pattern_offset = pattern_offset * u.arcsec - - pattern_length = len(pattern) - - RA_offsets = [pattern[count % pattern_length][0] - for count in range(n_positions)] * pattern_offset - dec_offsets = [pattern[count % pattern_length][1] - for count in range(n_positions)] * pattern_offset - - else: - RA_offsets = np.zeros(n_positions) * u.arcsec - dec_offsets = np.zeros(n_positions) * u.arcsec - - if random_offset: - if not isinstance(random_offset, u.Quantity): - random_offset = random_offset * u.arcsec - - RA_offsets += np.random.uniform(low=-1, high=+1, size=RA_offsets.shape) * random_offset - dec_offsets += np.random.uniform(low=-1, high=+1, size=dec_offsets.shape) * random_offset - - offsets = SkyOffsetFrame(lon=RA_offsets, lat=dec_offsets, origin=base_position) - positions = offsets.transform_to(ICRS) - - if plot: - dummy_wcs = WCS(naxis=2) - dummy_wcs.wcs.ctype = ['RA---TAN', 'DEC--TAN'] - dummy_wcs.wcs.crval = [base_position.ra.value, base_position.dec.value] - - ax = plt.subplot(projection=dummy_wcs) - ax.plot(positions.ra, positions.dec, 'b*-', transform=ax.get_transform('world')) - ax.plot([base_position.ra.value], [base_position.dec.value], - 'rx', transform=ax.get_transform('world')) - ax.set_aspect('equal', adjustable='datalim') - ax.coords[0].set_axislabel('Right Ascension') - ax.coords[0].set_major_formatter('hh:mm') - ax.coords[1].set_axislabel('declination') - ax.coords[1].set_major_formatter('dd:mm') - ax.grid() - plt.title('base position: {},\nnumber of positions: {}\npattern offset: {},\nrandom offset: {}'.format(base_position.to_string('hmsdms'), - n_positions, - pattern_offset, - random_offset)) - plt.gcf().set_size_inches(8, 8.5) - plt.savefig(plot) - - return SkyCoord(positions) diff --git a/huntsman/utils/hdr.py b/huntsman/utils/hdr.py index d780b955..484fcb8b 100644 --- a/huntsman/utils/hdr.py +++ b/huntsman/utils/hdr.py @@ -1,4 +1,4 @@ -from huntsman.utils import dither +from pocs.utils import dither from astropy import units as u from astropy.coordinates import SkyCoord