From db1188137ff0aed1c50a6b91e8457cc61ae6cf88 Mon Sep 17 00:00:00 2001 From: ramonefoster Date: Fri, 9 Aug 2024 15:57:08 -0300 Subject: [PATCH 1/6] add near meridian constraint --- astroplan/constraints.py | 42 ++++++++++++++++++++++++++++- astroplan/tests/test_constraints.py | 17 ++++++++++-- 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/astroplan/constraints.py b/astroplan/constraints.py index f9857fe9..30df8145 100644 --- a/astroplan/constraints.py +++ b/astroplan/constraints.py @@ -35,7 +35,7 @@ "LocalTimeConstraint", "PrimaryEclipseConstraint", "SecondaryEclipseConstraint", "Constraint", "TimeConstraint", "observability_table", "months_observable", "max_best_rescale", - "min_best_rescale", "PhaseConstraint", "is_event_observable"] + "min_best_rescale", "PhaseConstraint", "is_event_observable", "NearMeridianConstraint"] _current_year = time.localtime().tm_year # needed for backward compatibility _current_year_time_range = Time( # needed for backward compatibility @@ -938,6 +938,46 @@ def compute_constraint(self, times, observer=None, targets=None): return mask +class NearMeridianConstraint(Constraint): + """ + Constraint near the Meridian. + """ + def __init__(self, min=None, boolean_constraint=True): + """ + Parameters + ---------- + min : `~astropy.units.Quantity` or `None`, optional + Minimum acceptable distance to meridian. + `None` indicates no limit. + + boolean_constraint : bool + + Examples + -------- + Constrain observations to targets that are 3 degrees away from the meridian. + >>> import astropy.units as u + >>> constraint = NearMeridianConstraint(min=3*u.deg) + + This can be useful for observations using German-Equatorial Mounts, to avoid + flipping the side of the pier during exposures. + """ + self.min = min if min is not None else 0*u.hourangle + self.boolean_constraint = boolean_constraint + + def compute_constraint(self, times, observer, targets): + lst = observer.local_sidereal_time(times) + meridian = SkyCoord(ra=lst, dec=targets.dec) + + meridian_separation = meridian.separation(targets) + + if self.boolean_constraint: + mask = (self.min < meridian_separation) + return mask + else: + rescale = min_best_rescale(meridian_separation, self.min, less_than_min=0) + return rescale + + def is_always_observable(constraints, observer, targets, times=None, time_range=None, time_grid_resolution=0.5*u.hour): """ diff --git a/astroplan/tests/test_constraints.py b/astroplan/tests/test_constraints.py index c0f66f39..4d1e5ebc 100644 --- a/astroplan/tests/test_constraints.py +++ b/astroplan/tests/test_constraints.py @@ -5,7 +5,7 @@ import numpy as np import astropy.units as u from astropy.time import Time -from astropy.coordinates import Galactic, SkyCoord, get_sun, get_body +from astropy.coordinates import Galactic, SkyCoord, EarthLocation, get_sun, get_body from astropy.utils import minversion import pytest @@ -20,7 +20,7 @@ TimeConstraint, LocalTimeConstraint, months_observable, max_best_rescale, min_best_rescale, PhaseConstraint, PrimaryEclipseConstraint, SecondaryEclipseConstraint, - is_event_observable) + is_event_observable, NearMeridianConstraint) from ..periodic import EclipsingSystem from ..exceptions import MissingConstraintWarning @@ -200,6 +200,18 @@ def test_sun_separation(): assert np.all(is_constraint_met == [False, True, True]) +def test_near_meridian(): + time_range = Time(["2024-10-08 20:28", "2024-10-08 22:30"]) + target = FixedTarget(coord=SkyCoord(ra=19.75*u.hour, dec=-22.05*u.deg), name="name") + + # Pico dos Dias Observatory (Brazil) + opd = Observer(location=EarthLocation(lat=-22.53, lon=-45.58, height=1864)) + constraint = NearMeridianConstraint(min=3*u.deg) + + results = constraint(opd, target, times=time_grid_from_range(time_range)) + assert np.all(results == [True, True, False, True, True]) + + def test_moon_separation(): time = Time('2003-04-05 06:07:08') apo = Observer.at_site("APO") @@ -419,6 +431,7 @@ def test_rescale_minmax(): AtNightConstraint(), SunSeparationConstraint(min=90*u.deg), MoonSeparationConstraint(min=20*u.deg), + NearMeridianConstraint(min=3*u.deg), LocalTimeConstraint(min=dt.time(23, 50), max=dt.time(4, 8)), TimeConstraint(*Time(["2015-08-28 03:30", "2015-09-05 10:30"])) ] From c391d8b4ba9467acd08be929b941625596e179c5 Mon Sep 17 00:00:00 2001 From: ramonefoster Date: Tue, 13 Aug 2024 10:33:50 -0300 Subject: [PATCH 2/6] changes in MeridianSeparationConstraint --- astroplan/constraints.py | 26 ++++++++++++++++---------- astroplan/tests/test_constraints.py | 14 +++++++------- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/astroplan/constraints.py b/astroplan/constraints.py index 30df8145..9244ad05 100644 --- a/astroplan/constraints.py +++ b/astroplan/constraints.py @@ -35,7 +35,7 @@ "LocalTimeConstraint", "PrimaryEclipseConstraint", "SecondaryEclipseConstraint", "Constraint", "TimeConstraint", "observability_table", "months_observable", "max_best_rescale", - "min_best_rescale", "PhaseConstraint", "is_event_observable", "NearMeridianConstraint"] + "min_best_rescale", "PhaseConstraint", "is_event_observable", "MeridianSeparationConstraint"] _current_year = time.localtime().tm_year # needed for backward compatibility _current_year_time_range = Time( # needed for backward compatibility @@ -938,30 +938,36 @@ def compute_constraint(self, times, observer=None, targets=None): return mask -class NearMeridianConstraint(Constraint): +class MeridianSeparationConstraint(Constraint): """ - Constraint near the Meridian. + Constraint on angular separation from the meridian. """ - def __init__(self, min=None, boolean_constraint=True): + def __init__(self, min=None, max=None, boolean_constraint=True): """ Parameters ---------- min : `~astropy.units.Quantity` or `None`, optional Minimum acceptable distance to meridian. - `None` indicates no limit. + `None` indicates no lower limit. + + max : `~astropy.units.Quantity` or `None`, optional + Maximum acceptable distance to meridian. + `None` indicates no upper limit. boolean_constraint : bool Examples -------- - Constrain observations to targets that are 3 degrees away from the meridian. + Constrain observations to targets that are between 3 and 35 degrees + away from the meridian. >>> import astropy.units as u - >>> constraint = NearMeridianConstraint(min=3*u.deg) + >>> constraint = MeridianSeparationConstraint(min=3*u.deg, max=35*u.deg) This can be useful for observations using German-Equatorial Mounts, to avoid flipping the side of the pier during exposures. """ - self.min = min if min is not None else 0*u.hourangle + self.min = min if min is not None else 0*u.deg + self.max = max if max is not None else 180*u.deg self.boolean_constraint = boolean_constraint def compute_constraint(self, times, observer, targets): @@ -971,10 +977,10 @@ def compute_constraint(self, times, observer, targets): meridian_separation = meridian.separation(targets) if self.boolean_constraint: - mask = (self.min < meridian_separation) + mask = (self.min < meridian_separation) & (meridian_separation < self.max) return mask else: - rescale = min_best_rescale(meridian_separation, self.min, less_than_min=0) + rescale = min_best_rescale(meridian_separation, self.min, self.max, less_than_min=0) return rescale diff --git a/astroplan/tests/test_constraints.py b/astroplan/tests/test_constraints.py index 4d1e5ebc..ee528885 100644 --- a/astroplan/tests/test_constraints.py +++ b/astroplan/tests/test_constraints.py @@ -20,7 +20,7 @@ TimeConstraint, LocalTimeConstraint, months_observable, max_best_rescale, min_best_rescale, PhaseConstraint, PrimaryEclipseConstraint, SecondaryEclipseConstraint, - is_event_observable, NearMeridianConstraint) + is_event_observable, MeridianSeparationConstraint) from ..periodic import EclipsingSystem from ..exceptions import MissingConstraintWarning @@ -200,16 +200,16 @@ def test_sun_separation(): assert np.all(is_constraint_met == [False, True, True]) -def test_near_meridian(): - time_range = Time(["2024-10-08 20:28", "2024-10-08 22:30"]) - target = FixedTarget(coord=SkyCoord(ra=19.75*u.hour, dec=-22.05*u.deg), name="name") +def test_meridian_separation(): + time_range = Time(["2024-10-08 21:00", "2024-10-08 23:00"]) + target = FixedTarget(coord=SkyCoord(ra=19.75*u.hour, dec=-22.50*u.deg), name="name") # Pico dos Dias Observatory (Brazil) opd = Observer(location=EarthLocation(lat=-22.53, lon=-45.58, height=1864)) - constraint = NearMeridianConstraint(min=3*u.deg) + constraint = MeridianSeparationConstraint(min=3*u.deg, max=35*u.deg) results = constraint(opd, target, times=time_grid_from_range(time_range)) - assert np.all(results == [True, True, False, True, True]) + assert np.all(results == [True, False, True, True, True]) def test_moon_separation(): @@ -431,7 +431,7 @@ def test_rescale_minmax(): AtNightConstraint(), SunSeparationConstraint(min=90*u.deg), MoonSeparationConstraint(min=20*u.deg), - NearMeridianConstraint(min=3*u.deg), + MeridianSeparationConstraint(min=3*u.deg), LocalTimeConstraint(min=dt.time(23, 50), max=dt.time(4, 8)), TimeConstraint(*Time(["2015-08-28 03:30", "2015-09-05 10:30"])) ] From a39bd79621e446d4a9d76747285dbf9a63bb0cbc Mon Sep 17 00:00:00 2001 From: ramonefoster Date: Tue, 13 Aug 2024 10:37:38 -0300 Subject: [PATCH 3/6] changes in MeridianSeparationConstraint --- astroplan/constraints.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/astroplan/constraints.py b/astroplan/constraints.py index 9244ad05..bbb74730 100644 --- a/astroplan/constraints.py +++ b/astroplan/constraints.py @@ -35,7 +35,8 @@ "LocalTimeConstraint", "PrimaryEclipseConstraint", "SecondaryEclipseConstraint", "Constraint", "TimeConstraint", "observability_table", "months_observable", "max_best_rescale", - "min_best_rescale", "PhaseConstraint", "is_event_observable", "MeridianSeparationConstraint"] + "min_best_rescale", "PhaseConstraint", "is_event_observable", + "MeridianSeparationConstraint"] _current_year = time.localtime().tm_year # needed for backward compatibility _current_year_time_range = Time( # needed for backward compatibility @@ -949,7 +950,7 @@ def __init__(self, min=None, max=None, boolean_constraint=True): min : `~astropy.units.Quantity` or `None`, optional Minimum acceptable distance to meridian. `None` indicates no lower limit. - + max : `~astropy.units.Quantity` or `None`, optional Maximum acceptable distance to meridian. `None` indicates no upper limit. From 1fc2b15e74832e18cc3b8d7e9f1de12cd7541e95 Mon Sep 17 00:00:00 2001 From: ramonefoster Date: Tue, 13 Aug 2024 10:41:05 -0300 Subject: [PATCH 4/6] changes in MeridianSeparationConstraint --- astroplan/constraints.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/astroplan/constraints.py b/astroplan/constraints.py index bbb74730..cebfbd1c 100644 --- a/astroplan/constraints.py +++ b/astroplan/constraints.py @@ -35,7 +35,7 @@ "LocalTimeConstraint", "PrimaryEclipseConstraint", "SecondaryEclipseConstraint", "Constraint", "TimeConstraint", "observability_table", "months_observable", "max_best_rescale", - "min_best_rescale", "PhaseConstraint", "is_event_observable", + "min_best_rescale", "PhaseConstraint", "is_event_observable", "MeridianSeparationConstraint"] _current_year = time.localtime().tm_year # needed for backward compatibility From 486a6606fc0c4849633d54f5dd3630853f80bbe2 Mon Sep 17 00:00:00 2001 From: Ramon <82529131+ramonefoster@users.noreply.github.com> Date: Tue, 13 Aug 2024 17:16:52 -0300 Subject: [PATCH 5/6] Update astroplan/constraints.py Co-authored-by: Brett M. Morris --- astroplan/constraints.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/astroplan/constraints.py b/astroplan/constraints.py index cebfbd1c..54183560 100644 --- a/astroplan/constraints.py +++ b/astroplan/constraints.py @@ -948,7 +948,7 @@ def __init__(self, min=None, max=None, boolean_constraint=True): Parameters ---------- min : `~astropy.units.Quantity` or `None`, optional - Minimum acceptable distance to meridian. + Minimum acceptable angular distance from the meridian. `None` indicates no lower limit. max : `~astropy.units.Quantity` or `None`, optional From 697ef26acc014020364338e785669f2368d57ebc Mon Sep 17 00:00:00 2001 From: ramonefoster Date: Tue, 13 Aug 2024 17:18:15 -0300 Subject: [PATCH 6/6] update param description --- astroplan/constraints.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/astroplan/constraints.py b/astroplan/constraints.py index cebfbd1c..a734259d 100644 --- a/astroplan/constraints.py +++ b/astroplan/constraints.py @@ -948,11 +948,11 @@ def __init__(self, min=None, max=None, boolean_constraint=True): Parameters ---------- min : `~astropy.units.Quantity` or `None`, optional - Minimum acceptable distance to meridian. + Minimum acceptable angular distance from the meridian. `None` indicates no lower limit. max : `~astropy.units.Quantity` or `None`, optional - Maximum acceptable distance to meridian. + Maximum acceptable angular distance from the meridian. `None` indicates no upper limit. boolean_constraint : bool