def elem_to_topocentric_apparent(dt, elements, site, JFORM=2): '''Given a datetime, set of MPC orbital elements and a site, return the apparent topocentric RA/Dec. This is what you'd use for a rise/set calculation, for example. JFORM should be set to 2 (default) for asteroids/minor planets and to 3 for comets''' tdb = date_to_tdb(dt) MINOR_PLANET_JFORM = 2 COMET_JFORM = 3 MAJOR_PLANET_JFORM = 1 MDM_PLACEHOLDER = 0.0 # Only used for major planets MEANANOM_PLACEHOLDER = 0.0 # Not applicable for comets status = 0 if JFORM == MINOR_PLANET_JFORM: # Minor planets (asteroids) ra_app_rads, dec_app_rads, earth_obj_dist, status = sla.sla_plante( tdb, site['longitude'].in_radians(), site['latitude'].in_radians(), JFORM, elements['epoch'], elements['inclination'].in_radians(), elements['long_node'].in_radians(), elements['arg_perihelion'].in_radians(), elements['semi_axis'], elements['eccentricity'], elements['mean_anomaly'].in_radians(), MDM_PLACEHOLDER, ) elif JFORM == COMET_JFORM: # Comets ra_app_rads, dec_app_rads, earth_obj_dist, status = sla.sla_plante( tdb, site['longitude'].in_radians(), site['latitude'].in_radians(), JFORM, elements['epochofperih'], elements['inclination'].in_radians(), elements['long_node'].in_radians(), elements['arg_perihelion'].in_radians(), elements['perihdist'], elements['eccentricity'], MEANANOM_PLACEHOLDER, MDM_PLACEHOLDER, ) elif JFORM == MAJOR_PLANET_JFORM: # JPL Major Planets long_perihelion = Angle(degrees=elements['long_node'].in_degrees() + elements['arg_perihelion'].in_degrees()) mean_long = Angle(degrees=elements['long_node'].in_degrees() + elements['arg_perihelion'].in_degrees() + elements['mean_anomaly'].in_degrees()) ra_app_rads, dec_app_rads, earth_obj_dist, status = sla.sla_plante( tdb, site['longitude'].in_radians(), site['latitude'].in_radians(), JFORM, elements['epochofel'], elements['inclination'].in_radians(), elements['long_node'].in_radians(), long_perihelion.in_radians(), elements['semi_axis'], elements['eccentricity'], mean_long.in_radians(), elements['dailymot'].in_radians(), ) else: status = -1 error = { 0: 'OK', -1: 'illegal JFORM', -2: 'illegal eccentricity', -3: 'illegal mean distance', -4: 'illegal mean daily motion', -5: 'numerical error', } if (status != 0): elem_string = 'Bad Elements:\n' for key in elements.keys(): elem_string += key + ' = ' + str(elements[key]) + '\n' _log.info(elem_string) raise MovingViolation('Error: ' + str(status) + ' (' + error[status] + ')') return Angle(radians=ra_app_rads), Angle(radians=dec_app_rads)
class TestAngle(object): '''Unit tests for the angle.Angle class.''' # Test constructor errors @raises(AngleConfigError) def test_invalid_angle_none(self): self.angle = Angle() @raises(AngleConfigError) def test_invalid_angle_type(self): self.angle = Angle(units = 'time') @raises(AngleConfigError) def test_invalid_angle_units(self): self.angle = Angle(degrees = 45, units = 'kilos') @raises(AngleConfigError) def test_invalid_multiple_angles(self): self.angle = Angle(degrees = 45, radians = pi/4) # Test degree functionality def test_in_degrees(self): self.angle = Angle(degrees=37) assert_equal(self.angle.in_degrees(), 37) def test_in_degrees_rads_provided(self): self.angle = Angle(radians=pi) assert_equal(self.angle.in_degrees(), 180) def test_in_degrees_negative(self): self.angle = Angle(degrees = -37) assert_equal(self.angle.in_degrees(), -37) # Test radian functionality def test_in_radians_rads_provided(self): self.angle = Angle(radians=2*pi) assert_equal(self.angle.in_radians(), 2*pi) def test_in_radians_degrees_provided(self): self.angle = Angle(degrees=180) assert_equal(self.angle.in_radians(), pi) def test_in_radians_degrees_provided_time(self): self.angle = Angle(degrees=12, units = 'time') assert_equal(self.angle.in_radians(), pi) def test_in_radians_negative(self): self.angle = Angle(radians = -pi) assert_equal(self.angle.in_radians(), -pi) # Test valid sexegesimal->degrees conversion given units = time def test_from_sexegesimal_hrs_time(self): self.angle = Angle(degrees='12:00:00', units= 'time') assert_equal(self.angle.in_degrees(), 180) def test_from_sexegesimal_more_hrs_time(self): self.angle = Angle(degrees='120:00:00', units= 'time') assert_equal(self.angle.in_degrees(), 1800) def test_from_sexegesimal_hrs_mins_time(self): self.angle = Angle(degrees='12:30:00', units = 'time') assert_equal(self.angle.in_degrees(), 187.5) def test_from_sexegesimal_hrs_secs_time(self): self.angle = Angle(degrees='12:30:30', units = 'time') assert_equal(self.angle.in_degrees(), 187.625) def test_from_sexegesimal_fractional_secs_time(self): self.angle = Angle(degrees='12:30:30.1', units = 'time') assert_equal(self.angle.in_degrees(), (187.625 + (360/24/36000))) def test_from_sexegesimal_negative_time(self): self.angle = Angle(degrees='-12:00:00', units = 'time') assert_equal(self.angle.in_degrees(), -180) def test_from_sexegesimal_positive_time(self): self.angle = Angle(degrees='+12:00:00', units = 'time') assert_equal(self.angle.in_degrees(), 180) def test_from_sexegesimal_zero_time(self): self.angle = Angle(degrees='0 0 0', units = 'time') assert_equal(self.angle.in_degrees(), 0.0) # Test valid sexegesimal->degrees conversion given units = arc def test_from_sexegesimal_hrs_arc(self): self.angle = Angle(degrees='12:00:00') assert_equal(self.angle.in_degrees(), 12) def test_from_sexegesimal_more_hrs_arc(self): self.angle = Angle(degrees='120:00:00') assert_equal(self.angle.in_degrees(), 120) def test_from_sexegesimal_hrs_mins_arc(self): self.angle = Angle(degrees='12:30:00') assert_equal(self.angle.in_degrees(), 12.5) def test_from_sexegesimal_hrs_secs_arc(self): self.angle = Angle(degrees='12:30:30') assert_almost_equal(self.angle.in_degrees(), 12.50833, 5) def test_from_sexegesimal_fractional_secs_arc(self): self.angle = Angle(degrees='12:30:30.1') assert_almost_equal(self.angle.in_degrees(), 12.50836, 5) def test_from_sexegesimal_negative_arc(self): self.angle = Angle(degrees='-12:00:00') assert_equal(self.angle.in_degrees(), -12.0) def test_from_sexegesimal_positive_arc(self): self.angle = Angle(degrees='+12:00:00') assert_equal(self.angle.in_degrees(), 12.0) def test_from_sexegesimal_zero_arc(self): self.angle = Angle(degrees='0 0 0') assert_equal(self.angle.in_degrees(), 0.0) # Test various valid input forms for sexegesimal def test_from_sexegesimal_valid_format_colons(self): self.angle = Angle(degrees='12:30:30', units = 'time') assert_equal(self.angle.in_degrees(), 187.625) def test_from_sexegesimal_valid_format_one_space(self): self.angle = Angle(degrees='12 30 30', units = 'time') assert_equal(self.angle.in_degrees(), 187.625) def test_from_sexegesimal_valid_format_many_spaces(self): self.angle = Angle(degrees='12 30 30', units = 'time') assert_equal(self.angle.in_degrees(), 187.625) def test_from_sexegesimal_valid_format_weird_delims(self): self.angle = Angle(degrees='12$$30$$30', units = 'time') assert_equal(self.angle.in_degrees(), 187.625) # Test sexegesimal validation on various illegal inputs @raises(InvalidAngleError) def test_from_sexegesimal_invalid_format_number_mins_too_long(self): self.angle = Angle(degrees='12:0120:00') @raises(InvalidAngleError) def test_from_sexegesimal_invalid_format_secs_too_long(self): self.angle = Angle(degrees='12:00:0032') @raises(InvalidAngleError) def test_from_sexegesimal_invalid_format_min_too_small(self): self.angle = Angle(degrees='12:-1:00') @raises(InvalidAngleError) def test_from_sexegesimal_invalid_format_sec_too_small(self): self.angle = Angle(degrees='12:00:-1.0') @raises(InvalidAngleError) def test_from_sexegesimal_invalid_format_no_delimiters(self): self.angle = Angle(degrees = '123030') @raises(InvalidAngleError) def test_from_sexegesimal_invalid_format_minuses(self): self.angle = Angle(degrees = '12-30-30', units = 'time') # Test returning degrees in sexegesimal def test_in_sexegesimal_degrees_str_arc(self): self.angle = Angle(degrees = '12 30 30') assert_equal(self.angle.in_sexegesimal(), '12 30 30') def test_in_sexegesimal_degrees_num_arc(self): self.angle = Angle(degrees = 45) assert_equal(self.angle.in_sexegesimal(), '45 0 0') def test_in_sexegesimal_degrees_negative_num_arc(self): self.angle = Angle(degrees = -90) assert_equal(self.angle.in_sexegesimal(), '-90 0 0') def test_in_sexegesimal_degrees_negative_str_arc(self): self.angle = Angle(degrees = '-12 00 00') assert_equal(self.angle.in_sexegesimal(), '-12 0 0') def test_in_sexegesimal_degrees_str_time(self): self.angle = Angle(degrees = '12 30 30', units = 'time') assert_equal(self.angle.in_sexegesimal(), '12 30 30') def test_in_sexegesimal_degrees_num_time(self): self.angle = Angle(degrees = 12.5, units = 'time') assert_equal(self.angle.in_sexegesimal(), '12 30 0') def test_in_sexegesimal_degrees_negative_num_time(self): self.angle = Angle(degrees = -12.5, units = 'time') assert_equal(self.angle.in_sexegesimal(), '-12 30 0') def test_in_sexegesimal_degrees_negative_str_time(self): self.angle = Angle(degrees = '-12 00 00', units = 'time') assert_equal(self.angle.in_sexegesimal(), '-12 0 0') # Test returning radians in sexegesimal def test_in_sexegesimal_radians_str_arc(self): self.angle = Angle(radians = '12 30 30') assert_equal(self.angle.in_sexegesimal(radians = True), '12 30 30') def test_in_sexegesimal_radians_negative_str_arc(self): self.angle = Angle(radians = '-2 00 00') assert_equal(self.angle.in_sexegesimal(radians = True), '-2 0 0') def test_in_sexegesimal_radians_str_time(self): self.angle = Angle(radians = '12 30 30', units = 'time') assert_equal(self.angle.in_sexegesimal(radians = True), '12 30 30') def test_in_sexegesimal_radians_negative_str_time(self): self.angle = Angle(radians = '-3 00 00', units = 'time') assert_equal(self.angle.in_sexegesimal(radians = True), '-3 0 0') # Test converting degrees to radians sexegesimal def test_in_sexegesimal_degrees_to_radians_arc(self): self.angle = Angle(degrees = 180) assert_equal(self.angle.in_sexegesimal(radians = True), '3 8 29.7335529233') def test_in_sexegesimal__negative_degrees_to_radians_arc(self): self.angle = Angle(degrees = -180) assert_equal(self.angle.in_sexegesimal(radians = True), '-3 8 29.7335529233') def test_in_sexegesimal_degrees_to_radians_time(self): self.angle = Angle(degrees = 12, units = 'time') assert_equal(self.angle.in_sexegesimal(radians = True), '3 8 29.7335529233') def test_in_sexegesimal_negative_degrees_to_radians_time(self): self.angle = Angle(degrees = -12, units = 'time') assert_equal(self.angle.in_sexegesimal(radians = True), '-3 8 29.7335529233') def test_in_sexegesimal_radians_to_degrees_arc(self): self.angle = Angle(radians = pi) assert_equal(self.angle.in_sexegesimal(), '180 0 0') def test_in_sexegesimal_negative_radians_to_degrees_arc(self): self.angle = Angle(radians = -2*pi) assert_equal(self.angle.in_sexegesimal(), '-360 0 0') def test_in_sexegesimal_radians_to_degrees_time(self): self.angle = Angle(radians = pi, units = 'time') assert_equal(self.angle.in_sexegesimal(), '180 0 0') def test_in_sexegesimal_negative_radians_to_degrees_time(self): self.angle = Angle(radians = -2*pi, units = 'time') assert_equal(self.angle.in_sexegesimal(), '-360 0 0')