Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Observable_interval function added and months_observable aliased #531

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 77 additions & 16 deletions astroplan/constraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
_current_year = time.localtime().tm_year # needed for backward compatibility
_current_year_time_range = Time( # needed for backward compatibility
[str(_current_year) + '-01-01',
str(_current_year) + '-12-31']
str(_current_year + 1) + '-01-01']
)


Expand Down Expand Up @@ -1093,12 +1093,14 @@ def is_event_observable(constraints, observer, target, times=None,
return constraint_arr


def months_observable(constraints, observer, targets,
time_range=_current_year_time_range,
time_grid_resolution=0.5*u.hour):
def observable_interval(constraints, observer, targets,
time_range=_current_year_time_range,
time_grid_resolution=0.5*u.hour,
interval='months'):
"""
Determines which month the specified ``targets`` are observable for a
specific ``observer``, given the supplied ``constraints``.
Determines which ``intervals`` in ``time_range`` the specified ``targets``
are observable for a specific ``observer``,
given the supplied ``constraints``.

Parameters
----------
Expand All @@ -1121,18 +1123,26 @@ def months_observable(constraints, observer, targets,
linearly-spaced times separated by ``time_resolution``. Default is 0.5
hours.

interval : str; ('days','weeks','months') (optional)
Defines the interval of what dates to calculate ``constraints`` on.
Default is 'months'.


Returns
-------
observable_months : list
List of sets of unique integers representing each month that a target is
observability : list
List of sets of unique integers representing each interval that a target is
observable, one set per target. These integers are 1-based so that
January maps to 1, February maps to 2, etc.
January maps to 1, Feburary maps to 2, etc., and it is a similar structure
for day and week intervals.

"""
# TODO: This method could be sped up a lot by dropping to the trigonometric
# altitude calculations.
if not hasattr(constraints, '__len__'):
constraints = [constraints]
if interval not in ['days', 'weeks', 'months']:
raise ValueError('Interval is of an incorrect type. Please choose days, weeks, or months')

times = time_grid_from_range(time_range, time_grid_resolution)

Expand All @@ -1142,24 +1152,75 @@ def months_observable(constraints, observer, targets,
[isinstance(constraint, AltitudeConstraint) for constraint in constraints]
)
if not altitude_constraint_supplied:
message = ("months_observable usually expects an AltitudeConstraint or "
message = ("observable_interval usually expects an AltitudeConstraint or "
"AirmassConstraint to ensure targets are above horizon.")
warnings.warn(message, MissingConstraintWarning)

# TODO: This method could be sped up a lot by dropping to the trigonometric
# altitude calculations.
applied_constraints = [constraint(observer, targets,
times=times,
grid_times_targets=True)
for constraint in constraints]
constraint_arr = np.logical_and.reduce(applied_constraints)

months_observable = []
observability = []

method_dic = {'days': lambda t: t.datetime.timetuple().tm_yday,
'weeks': lambda t: t.datetime.isocalendar()[1],
'months': lambda t: t.datetime.month}

for target, observable in zip(targets, constraint_arr):
s = set([t.datetime.month for t in times[observable]])
months_observable.append(s)
if observable.any():
s = set([method_dic[interval](t) for t in times[observable]])
else:
s = {}
observability.append(s)

return observability


def months_observable(constraints, observer, targets,
time_range=_current_year_time_range,
time_grid_resolution=0.5*u.hour):
"""
Determines which months in ``time_range`` the specified ``targets``
are observable for a specific ``observer``,
given the supplied ``constraints``.

This is an alias of observable_interval(..., interval = 'months')
"""

return observable_interval(constraints, observer, targets, time_range,
time_grid_resolution, interval='months')


def weeks_observable(constraints, observer, targets,
time_range=_current_year_time_range,
time_grid_resolution=0.5*u.hour):
"""
Determines which weeks in ``time_range`` the specified ``targets``
are observable for a specific ``observer``,
given the supplied ``constraints``.

This is an alias of observable_interval(..., interval = 'weeks')
"""

return observable_interval(constraints, observer, targets, time_range,
time_grid_resolution, interval='weeks')


def days_observable(constraints, observer, targets,
time_range=_current_year_time_range,
time_grid_resolution=0.5*u.hour):
"""
Determines which days in ``time_range`` the specified ``targets``
are observable for a specific ``observer``,
given the supplied ``constraints``.

This is an alias of observable_interval(..., interval = 'days')
"""

return months_observable
return observable_interval(constraints, observer, targets, time_range,
time_grid_resolution, interval='days')


def observability_table(constraints, observer, targets, times=None,
Expand Down