Skip to content

Commit

Permalink
Merge 990a330 into 8c2e5da
Browse files Browse the repository at this point in the history
  • Loading branch information
eheinrich committed Jun 14, 2019
2 parents 8c2e5da + 990a330 commit 2530ee4
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 52 deletions.
120 changes: 73 additions & 47 deletions observation_portal/common/rise_set_utils.py
Expand Up @@ -3,8 +3,10 @@
from datetime import datetime, timedelta

from time_intervals.intervals import Intervals
from rise_set.astrometry import make_ra_dec_target, make_satellite_target, make_minor_planet_target, mean_to_apparent
from rise_set.astrometry import make_comet_target, make_major_planet_target, angular_distance_between, date_to_tdb
from rise_set.astrometry import (
make_ra_dec_target, make_satellite_target, make_hour_angle_target, make_minor_planet_target, mean_to_apparent,
make_comet_target, make_major_planet_target, angular_distance_between, date_to_tdb
)
from rise_set.angle import Angle
from rise_set.rates import ProperMotion
from rise_set.visibility import Visibility
Expand Down Expand Up @@ -57,7 +59,9 @@ def get_rise_set_intervals_by_site(request: dict) -> dict:
visibility.get_observable_intervals(
rise_set_target,
airmass=request['configurations'][0]['constraints']['max_airmass'],
moon_distance=Angle(degrees=request['configurations'][0]['constraints']['min_lunar_distance'])
moon_distance=Angle(
degrees=request['configurations'][0]['constraints']['min_lunar_distance']
)
)
)
except MovingViolation:
Expand All @@ -80,7 +84,9 @@ def get_filtered_rise_set_intervals_by_site(request_dict, site=''):
return intervals

intervals_by_site = get_rise_set_intervals_by_site(request_dict)
intervalsets_by_telescope = intervals_by_site_to_intervalsets_by_telescope(intervals_by_site, telescope_details.keys())
intervalsets_by_telescope = intervals_by_site_to_intervalsets_by_telescope(
intervals_by_site, telescope_details.keys()
)
filtered_intervalsets_by_telescope = filter_out_downtime_from_intervalsets(intervalsets_by_telescope)
filtered_intervals_by_site = intervalsets_by_telescope_to_intervals_by_site(filtered_intervalsets_by_telescope)
return filtered_intervals_by_site
Expand Down Expand Up @@ -138,60 +144,80 @@ def filter_out_downtime_from_intervalsets(intervalsets_by_telescope: dict) -> di
if telescope not in downtime_intervals:
filtered_intervalsets_by_telescope[telescope] = intervalsets_by_telescope[telescope]
else:
filtered_intervalsets_by_telescope[telescope] = intervalsets_by_telescope[telescope].subtract(downtime_intervals[telescope])
filtered_intervalsets_by_telescope[telescope] = intervalsets_by_telescope[telescope].subtract(
downtime_intervals[telescope]
)
return filtered_intervalsets_by_telescope


def get_rise_set_target(target_dict):
if target_dict['type'] == 'ICRS':
if target_dict['type'] in ['ICRS', 'HOUR_ANGLE']:
pmra = (target_dict['proper_motion_ra'] / 1000.0 / cos(radians(target_dict['dec']))) / 3600.0
pmdec = (target_dict['proper_motion_dec'] / 1000.0) / 3600.0
return make_ra_dec_target(ra=Angle(degrees=target_dict['ra']),
dec=Angle(degrees=target_dict['dec']),
ra_proper_motion=ProperMotion(Angle(degrees=pmra, units='arc'), time='year'),
dec_proper_motion=ProperMotion(Angle(degrees=pmdec, units='arc'), time='year'),
parallax=target_dict['parallax'], rad_vel=0.0, epoch=target_dict['epoch'])

if target_dict['type'] == 'ICRS':
return make_ra_dec_target(
ra=Angle(degrees=target_dict['ra']),
dec=Angle(degrees=target_dict['dec']),
ra_proper_motion=ProperMotion(Angle(degrees=pmra, units='arc'), time='year'),
dec_proper_motion=ProperMotion(Angle(degrees=pmdec, units='arc'), time='year'),
parallax=target_dict['parallax'],
rad_vel=0.0,
epoch=target_dict['epoch']
)
elif target_dict['type'] == 'HOUR_ANGLE':
return make_hour_angle_target(
hour_angle=Angle(degrees=target_dict['hour_angle']),
dec=Angle(degrees=target_dict['dec']),
ra_proper_motion=ProperMotion(Angle(degrees=pmra, units='arc'), time='year'),
dec_proper_motion=ProperMotion(Angle(degrees=pmdec, units='arc'), time='year'),
parallax=target_dict['parallax'],
epoch=target_dict['epoch']
)
elif target_dict['type'] == 'SATELLITE':
return make_satellite_target(alt=target_dict['altitude'], az=target_dict['azimuth'],
diff_alt_rate=target_dict['diff_altitude_rate'],
diff_az_rate=target_dict['diff_azimuth_rate'],
diff_alt_accel=target_dict['diff_altitude_acceleration'],
diff_az_accel=target_dict['diff_azimuth_acceleration'],
diff_epoch_rate=target_dict['diff_epoch'])

return make_satellite_target(
alt=target_dict['altitude'],
az=target_dict['azimuth'],
diff_alt_rate=target_dict['diff_altitude_rate'],
diff_az_rate=target_dict['diff_azimuth_rate'],
diff_alt_accel=target_dict['diff_altitude_acceleration'],
diff_az_accel=target_dict['diff_azimuth_acceleration'],
diff_epoch_rate=target_dict['diff_epoch']
)
elif target_dict['type'] == 'ORBITAL_ELEMENTS':
if target_dict['scheme'] == 'MPC_MINOR_PLANET':
return make_minor_planet_target(target_type=target_dict['scheme'],
epoch=target_dict['epochofel'],
inclination=target_dict['orbinc'],
long_node=target_dict['longascnode'],
arg_perihelion=target_dict['argofperih'],
semi_axis=target_dict['meandist'],
eccentricity=target_dict['eccentricity'],
mean_anomaly=target_dict['meananom']
)
return make_minor_planet_target(
target_type=target_dict['scheme'],
epoch=target_dict['epochofel'],
inclination=target_dict['orbinc'],
long_node=target_dict['longascnode'],
arg_perihelion=target_dict['argofperih'],
semi_axis=target_dict['meandist'],
eccentricity=target_dict['eccentricity'],
mean_anomaly=target_dict['meananom']
)
elif target_dict['scheme'] == 'MPC_COMET':
return make_comet_target(target_type=target_dict['scheme'],
epoch=target_dict['epochofel'],
epochofperih=target_dict['epochofperih'],
inclination=target_dict['orbinc'],
long_node=target_dict['longascnode'],
arg_perihelion=target_dict['argofperih'],
perihdist=target_dict['perihdist'],
eccentricity=target_dict['eccentricity'],
)
return make_comet_target(
target_type=target_dict['scheme'],
epoch=target_dict['epochofel'],
epochofperih=target_dict['epochofperih'],
inclination=target_dict['orbinc'],
long_node=target_dict['longascnode'],
arg_perihelion=target_dict['argofperih'],
perihdist=target_dict['perihdist'],
eccentricity=target_dict['eccentricity'],
)
elif target_dict['scheme'] == 'JPL_MAJOR_PLANET':
return make_major_planet_target(target_type=target_dict['scheme'],
epochofel=target_dict['epochofel'],
inclination=target_dict['orbinc'],
long_node=target_dict['longascnode'],
arg_perihelion=target_dict['argofperih'],
semi_axis=target_dict['meandist'],
eccentricity=target_dict['eccentricity'],
mean_anomaly=target_dict['meananom'],
dailymot=target_dict['dailymot']
)
return make_major_planet_target(
target_type=target_dict['scheme'],
epochofel=target_dict['epochofel'],
inclination=target_dict['orbinc'],
long_node=target_dict['longascnode'],
arg_perihelion=target_dict['argofperih'],
semi_axis=target_dict['meandist'],
eccentricity=target_dict['eccentricity'],
mean_anomaly=target_dict['meananom'],
dailymot=target_dict['dailymot']
)
else:
raise TypeError('Invalid scheme ' + target_dict['scheme'])
else:
Expand Down
2 changes: 1 addition & 1 deletion observation_portal/requestgroups/request_utils.py
Expand Up @@ -86,7 +86,7 @@ def get_airmasses_for_request_at_sites(request_dict):
rs_target = get_rise_set_target(request_dict['configurations'][0]['target'])

data = {'airmass_data': {}}
if request_dict['configurations'][0]['target']['type'].upper() != 'SATELLITE':
if request_dict['configurations'][0]['target']['type'].upper() not in ['SATELLITE', 'HOUR_ANGLE']:
for site_id, site_details in site_data.items():
night_times = []
site_lat = Angle(degrees=site_details['latitude'])
Expand Down
47 changes: 45 additions & 2 deletions observation_portal/requestgroups/test/test_api.py
Expand Up @@ -1047,8 +1047,8 @@ def setUp(self):
end=datetime(2016, 12, 31, tzinfo=timezone.utc)
)
self.time_allocation_1m0 = mixer.blend(
TimeAllocation, proposal=self.proposal, semester=semester, telescope_class='1m0', std_allocation=100.0,
std_time_used=0.0, instrument_type='1M0-SCICAM-SBIG', rr_allocation=10, rr_time_used=0.0, ipp_limit=10.0,
TimeAllocation, proposal=self.proposal, semester=semester, std_allocation=100.0, std_time_used=0.0,
instrument_type='1M0-SCICAM-SBIG', rr_allocation=10, rr_time_used=0.0, ipp_limit=10.0,
ipp_time_available=5.0
)
mixer.blend(Membership, user=self.user, proposal=self.proposal)
Expand Down Expand Up @@ -1084,6 +1084,49 @@ def test_post_requestgroup_satellite_missing_fields(self):
self.assertIn('diff_altitude_acceleration', str(response.content))


class TestHourAngleTarget(SetTimeMixin, APITestCase):
def setUp(self):
super().setUp()
self.proposal = mixer.blend(Proposal)
self.user = mixer.blend(User)
self.client.force_login(self.user)

semester = mixer.blend(
Semester, id='2016B', start=datetime(2016, 9, 1, tzinfo=timezone.utc),
end=datetime(2016, 12, 31, tzinfo=timezone.utc)
)
self.time_allocation_1m0 = mixer.blend(
TimeAllocation, proposal=self.proposal, semester=semester, std_allocation=100.0, std_time_used=0.0,
instrument_type='1M0-SCICAM-SBIG', rr_allocation=10, rr_time_used=0.0, ipp_limit=10.0,
ipp_time_available=5.0
)
mixer.blend(Membership, user=self.user, proposal=self.proposal)
self.generic_payload = copy.deepcopy(generic_payload)
self.generic_payload['proposal'] = self.proposal.id
self.generic_payload['requests'][0]['configurations'][0]['target'] = {
'name': 'fake target',
'type': 'HOUR_ANGLE',
'hour_angle': 20.0,
'dec': 30.0,
'parallax': 0.1,
'proper_motion_ra': 0.01,
'proper_motion_dec': 0.02,
'epoch': 2000
}

def test_post_requestgroup_hour_angle_target(self):
good_data = self.generic_payload.copy()
response = self.client.post(reverse('api:request_groups-list'), data=good_data)
self.assertEqual(response.status_code, 201)

def test_post_requestgroup_hour_angle_missing_required_fields(self):
bad_data = self.generic_payload.copy()
del bad_data['requests'][0]['configurations'][0]['target']['dec']
response = self.client.post(reverse('api:request_groups-list'), data=bad_data)
self.assertEqual(response.status_code, 400)
self.assertIn('dec', str(response.content))


class TestLocationApi(SetTimeMixin, APITestCase):
def setUp(self):
super().setUp()
Expand Down
22 changes: 21 additions & 1 deletion observation_portal/requestgroups/test/test_request_utils.py
Expand Up @@ -310,6 +310,26 @@ def test_airmass_calculation_empty(self):

self.assertFalse(airmasses['airmass_data'])

def test_satellite_target_types_airmass_calc_is_empty(self):
self.configuration.target.type = 'SATELLITE'
self.configuration.target.altitude = 90
self.configuration.target.azimuth = 0
self.configuration.target.diff_altitude_rate = 0.01
self.configuration.target.diff_azimuth_rate = 0.01
self.configuration.target.diff_epoch = 15000
self.configuration.target.diff_altitude_acceleration = 0.001
self.configuration.target.diff_azimuth_acceleration = 0.001
self.configuration.target.save()
airmasses = get_airmasses_for_request_at_sites(self.request.as_dict())
self.assertFalse(airmasses['airmass_data'])

def test_hour_angle_target_types_airmass_calc_is_empty(self):
self.configuration.target.type = 'HOUR_ANGLE'
self.configuration.target.hour_angle = 0
self.configuration.target.save()
airmasses = get_airmasses_for_request_at_sites(self.request.as_dict())
self.assertFalse(airmasses['airmass_data'])


class TestRequestTelescopeStates(TelescopeStatesFakeInput):
def setUp(self):
Expand Down Expand Up @@ -362,7 +382,7 @@ def test_telescope_states_calculation(self):
self.assertIn(self.tk1, telescope_states)
self.assertIn(self.tk2, telescope_states)

expected_start_of_night = datetime(2016, 10, 1, 18, 45, 2, 760910, tzinfo=timezone.utc)
expected_start_of_night = datetime(2016, 10, 1, 18, 45, 49, 461652, tzinfo=timezone.utc)

# These are the same states tested for similar times in the telescope_states test class
doma_expected_available_state = {'telescope': 'tst.doma.1m0a',
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Expand Up @@ -14,7 +14,7 @@ django-bootstrap4
django-dramatiq
django-storages
time_intervals
rise_set
rise-set==0.4.11
elasticsearch<6.0
WeasyPrint
PyPDF2
Expand Down

0 comments on commit 2530ee4

Please sign in to comment.