diff --git a/generate/template/astronomy.py b/generate/template/astronomy.py index f093048f..d8ec8ca8 100644 --- a/generate/template/astronomy.py +++ b/generate/template/astronomy.py @@ -1451,15 +1451,13 @@ def SearchMaxElongation(body, startTime): rlon_hi = -s1 t_start = startTime.AddDays(adjust_days) - search1 = SearchRelativeLongitude(body, rlon_lo, t_start) - if search1 is None: + t1 = SearchRelativeLongitude(body, rlon_lo, t_start) + if t1 is None: return None - t1 = search1.time - search2 = SearchRelativeLongitude(body, rlon_hi, t1) - if search2 is None: + t2 = SearchRelativeLongitude(body, rlon_hi, t1) + if t2 is None: return None - t2 = search2.time # Now we have a time range [t1,t2] that brackets a maximum elongation event. # Confirm the bracketing. @@ -1472,12 +1470,12 @@ def SearchMaxElongation(body, startTime): raise InternalError() # there is a bug in the bracketing algorithm! # Use the generic search algorithm to home in on where the slope crosses from negative to positive. - searchx = Search(neg_elong_slope, body, t1, t2, 10.0) - if searchx is None: + tx = Search(_neg_elong_slope, body, t1, t2, 10.0) + if tx is None: return None - if searchx.time.tt >= startTime.tt: - return Elongation(body, searchx.time) + if tx.tt >= startTime.tt: + return Elongation(body, tx) # This event is in the past (earlier than startTime). # We need to search forward from t2 to find the next possible window. @@ -1982,15 +1980,9 @@ def NextLunarApsis(apsis): # + Ecliptic # + EclipticLongitude # + AngleFromSun -# + SearchMaxElongation -# + _neg_elong_slope -# + SearchRelativeLongitude -# + Elongation # + SearchHourAngle # + SearchRiseSet # + Illumination # + SearchPeakMagnitude # + SearchLunarApsis -# + _distance_slope -# + _MoonDistance # + NextLunarApsis diff --git a/generate/test.py b/generate/test.py index d766b45b..6de31074 100644 --- a/generate/test.py +++ b/generate/test.py @@ -304,20 +304,133 @@ def TestPlanetLongitudes(body, outFileName, zeroLonEventName): return 1 return 0 +ElongTestData = [ + # Max elongation data obtained from: + # http://www.skycaramba.com/greatest_elongations.shtml + ( astronomy.BODY_MERCURY, "2010-01-17T05:22Z", "2010-01-27T05:22Z", 24.80, 'morning' ), + ( astronomy.BODY_MERCURY, "2010-05-16T02:15Z", "2010-05-26T02:15Z", 25.10, 'morning' ), + ( astronomy.BODY_MERCURY, "2010-09-09T17:24Z", "2010-09-19T17:24Z", 17.90, 'morning' ), + ( astronomy.BODY_MERCURY, "2010-12-30T14:33Z", "2011-01-09T14:33Z", 23.30, 'morning' ), + ( astronomy.BODY_MERCURY, "2011-04-27T19:03Z", "2011-05-07T19:03Z", 26.60, 'morning' ), + ( astronomy.BODY_MERCURY, "2011-08-24T05:52Z", "2011-09-03T05:52Z", 18.10, 'morning' ), + ( astronomy.BODY_MERCURY, "2011-12-13T02:56Z", "2011-12-23T02:56Z", 21.80, 'morning' ), + ( astronomy.BODY_MERCURY, "2012-04-08T17:22Z", "2012-04-18T17:22Z", 27.50, 'morning' ), + ( astronomy.BODY_MERCURY, "2012-08-06T12:04Z", "2012-08-16T12:04Z", 18.70, 'morning' ), + ( astronomy.BODY_MERCURY, "2012-11-24T22:55Z", "2012-12-04T22:55Z", 20.60, 'morning' ), + ( astronomy.BODY_MERCURY, "2013-03-21T22:02Z", "2013-03-31T22:02Z", 27.80, 'morning' ), + ( astronomy.BODY_MERCURY, "2013-07-20T08:51Z", "2013-07-30T08:51Z", 19.60, 'morning' ), + ( astronomy.BODY_MERCURY, "2013-11-08T02:28Z", "2013-11-18T02:28Z", 19.50, 'morning' ), + ( astronomy.BODY_MERCURY, "2014-03-04T06:38Z", "2014-03-14T06:38Z", 27.60, 'morning' ), + ( astronomy.BODY_MERCURY, "2014-07-02T18:22Z", "2014-07-12T18:22Z", 20.90, 'morning' ), + ( astronomy.BODY_MERCURY, "2014-10-22T12:36Z", "2014-11-01T12:36Z", 18.70, 'morning' ), + ( astronomy.BODY_MERCURY, "2015-02-14T16:20Z", "2015-02-24T16:20Z", 26.70, 'morning' ), + ( astronomy.BODY_MERCURY, "2015-06-14T17:10Z", "2015-06-24T17:10Z", 22.50, 'morning' ), + ( astronomy.BODY_MERCURY, "2015-10-06T03:20Z", "2015-10-16T03:20Z", 18.10, 'morning' ), + ( astronomy.BODY_MERCURY, "2016-01-28T01:22Z", "2016-02-07T01:22Z", 25.60, 'morning' ), + ( astronomy.BODY_MERCURY, "2016-05-26T08:45Z", "2016-06-05T08:45Z", 24.20, 'morning' ), + ( astronomy.BODY_MERCURY, "2016-09-18T19:27Z", "2016-09-28T19:27Z", 17.90, 'morning' ), + ( astronomy.BODY_MERCURY, "2017-01-09T09:42Z", "2017-01-19T09:42Z", 24.10, 'morning' ), + ( astronomy.BODY_MERCURY, "2017-05-07T23:19Z", "2017-05-17T23:19Z", 25.80, 'morning' ), + ( astronomy.BODY_MERCURY, "2017-09-02T10:14Z", "2017-09-12T10:14Z", 17.90, 'morning' ), + ( astronomy.BODY_MERCURY, "2017-12-22T19:48Z", "2018-01-01T19:48Z", 22.70, 'morning' ), + ( astronomy.BODY_MERCURY, "2018-04-19T18:17Z", "2018-04-29T18:17Z", 27.00, 'morning' ), + ( astronomy.BODY_MERCURY, "2018-08-16T20:35Z", "2018-08-26T20:35Z", 18.30, 'morning' ), + ( astronomy.BODY_MERCURY, "2018-12-05T11:34Z", "2018-12-15T11:34Z", 21.30, 'morning' ), + ( astronomy.BODY_MERCURY, "2019-04-01T19:40Z", "2019-04-11T19:40Z", 27.70, 'morning' ), + ( astronomy.BODY_MERCURY, "2019-07-30T23:08Z", "2019-08-09T23:08Z", 19.00, 'morning' ), + ( astronomy.BODY_MERCURY, "2019-11-18T10:31Z", "2019-11-28T10:31Z", 20.10, 'morning' ), + ( astronomy.BODY_MERCURY, "2010-03-29T23:32Z", "2010-04-08T23:32Z", 19.40, 'evening' ), + ( astronomy.BODY_MERCURY, "2010-07-28T01:03Z", "2010-08-07T01:03Z", 27.40, 'evening' ), + ( astronomy.BODY_MERCURY, "2010-11-21T15:42Z", "2010-12-01T15:42Z", 21.50, 'evening' ), + ( astronomy.BODY_MERCURY, "2011-03-13T01:07Z", "2011-03-23T01:07Z", 18.60, 'evening' ), + ( astronomy.BODY_MERCURY, "2011-07-10T04:56Z", "2011-07-20T04:56Z", 26.80, 'evening' ), + ( astronomy.BODY_MERCURY, "2011-11-04T08:40Z", "2011-11-14T08:40Z", 22.70, 'evening' ), + ( astronomy.BODY_MERCURY, "2012-02-24T09:39Z", "2012-03-05T09:39Z", 18.20, 'evening' ), + ( astronomy.BODY_MERCURY, "2012-06-21T02:00Z", "2012-07-01T02:00Z", 25.70, 'evening' ), + ( astronomy.BODY_MERCURY, "2012-10-16T21:59Z", "2012-10-26T21:59Z", 24.10, 'evening' ), + ( astronomy.BODY_MERCURY, "2013-02-06T21:24Z", "2013-02-16T21:24Z", 18.10, 'evening' ), + ( astronomy.BODY_MERCURY, "2013-06-02T16:45Z", "2013-06-12T16:45Z", 24.30, 'evening' ), + ( astronomy.BODY_MERCURY, "2013-09-29T09:59Z", "2013-10-09T09:59Z", 25.30, 'evening' ), + ( astronomy.BODY_MERCURY, "2014-01-21T10:00Z", "2014-01-31T10:00Z", 18.40, 'evening' ), + ( astronomy.BODY_MERCURY, "2014-05-15T07:06Z", "2014-05-25T07:06Z", 22.70, 'evening' ), + ( astronomy.BODY_MERCURY, "2014-09-11T22:20Z", "2014-09-21T22:20Z", 26.40, 'evening' ), + ( astronomy.BODY_MERCURY, "2015-01-04T20:26Z", "2015-01-14T20:26Z", 18.90, 'evening' ), + ( astronomy.BODY_MERCURY, "2015-04-27T04:46Z", "2015-05-07T04:46Z", 21.20, 'evening' ), + ( astronomy.BODY_MERCURY, "2015-08-25T10:20Z", "2015-09-04T10:20Z", 27.10, 'evening' ), + ( astronomy.BODY_MERCURY, "2015-12-19T03:11Z", "2015-12-29T03:11Z", 19.70, 'evening' ), + ( astronomy.BODY_MERCURY, "2016-04-08T14:00Z", "2016-04-18T14:00Z", 19.90, 'evening' ), + ( astronomy.BODY_MERCURY, "2016-08-06T21:24Z", "2016-08-16T21:24Z", 27.40, 'evening' ), + ( astronomy.BODY_MERCURY, "2016-12-01T04:36Z", "2016-12-11T04:36Z", 20.80, 'evening' ), + ( astronomy.BODY_MERCURY, "2017-03-22T10:24Z", "2017-04-01T10:24Z", 19.00, 'evening' ), + ( astronomy.BODY_MERCURY, "2017-07-20T04:34Z", "2017-07-30T04:34Z", 27.20, 'evening' ), + ( astronomy.BODY_MERCURY, "2017-11-14T00:32Z", "2017-11-24T00:32Z", 22.00, 'evening' ), + ( astronomy.BODY_MERCURY, "2018-03-05T15:07Z", "2018-03-15T15:07Z", 18.40, 'evening' ), + ( astronomy.BODY_MERCURY, "2018-07-02T05:24Z", "2018-07-12T05:24Z", 26.40, 'evening' ), + ( astronomy.BODY_MERCURY, "2018-10-27T15:25Z", "2018-11-06T15:25Z", 23.30, 'evening' ), + ( astronomy.BODY_MERCURY, "2019-02-17T01:23Z", "2019-02-27T01:23Z", 18.10, 'evening' ), + ( astronomy.BODY_MERCURY, "2019-06-13T23:14Z", "2019-06-23T23:14Z", 25.20, 'evening' ), + ( astronomy.BODY_MERCURY, "2019-10-10T04:00Z", "2019-10-20T04:00Z", 24.60, 'evening' ), + ( astronomy.BODY_VENUS, "2010-12-29T15:57Z", "2011-01-08T15:57Z", 47.00, 'morning' ), + ( astronomy.BODY_VENUS, "2012-08-05T08:59Z", "2012-08-15T08:59Z", 45.80, 'morning' ), + ( astronomy.BODY_VENUS, "2014-03-12T19:25Z", "2014-03-22T19:25Z", 46.60, 'morning' ), + ( astronomy.BODY_VENUS, "2015-10-16T06:57Z", "2015-10-26T06:57Z", 46.40, 'morning' ), + ( astronomy.BODY_VENUS, "2017-05-24T13:09Z", "2017-06-03T13:09Z", 45.90, 'morning' ), + ( astronomy.BODY_VENUS, "2018-12-27T04:24Z", "2019-01-06T04:24Z", 47.00, 'morning' ), + ( astronomy.BODY_VENUS, "2010-08-10T03:19Z", "2010-08-20T03:19Z", 46.00, 'evening' ), + ( astronomy.BODY_VENUS, "2012-03-17T08:03Z", "2012-03-27T08:03Z", 46.00, 'evening' ), + ( astronomy.BODY_VENUS, "2013-10-22T08:00Z", "2013-11-01T08:00Z", 47.10, 'evening' ), + ( astronomy.BODY_VENUS, "2015-05-27T18:46Z", "2015-06-06T18:46Z", 45.40, 'evening' ), + ( astronomy.BODY_VENUS, "2017-01-02T13:19Z", "2017-01-12T13:19Z", 47.10, 'evening' ), + ( astronomy.BODY_VENUS, "2018-08-07T17:02Z", "2018-08-17T17:02Z", 45.90, 'evening' ) +] + +def ParseDate(text): + m = re.match(r'^(\d+)-(\d+)-(\d+)T(\d+):(\d+)Z$', text) + if not m: + print('ParseDate: invalid date text "{}"'.format(text)) + raise Exception('Bad elongation test data') + year = int(m.group(1)) + month = int(m.group(2)) + day = int(m.group(3)) + hour = int(m.group(4)) + minute = int(m.group(5)) + return astronomy.Time.Make(year, month, day, hour, minute, 0) + +def TestMaxElong(body, searchText, eventText, angle, visiblity): + name = astronomy.BodyName[body] + searchTime = ParseDate(searchText) + eventTime = ParseDate(eventText) + evt = astronomy.SearchMaxElongation(body, searchTime) + if evt is None: + print('TestMaxElong({} {}): SearchMaxElongation failed.'.format(name, searchText)) + return 1 + hour_diff = 24.0 * abs(evt.time.tt - eventTime.tt) + arcmin_diff = 60.0 * abs(evt.elongation - angle) + print('TestMaxElong: {:<7s} {:<7s} elong={:5.2f} ({:4.2f} arcmin, {:5.3f} hours)'.format(name, visiblity, evt.elongation, arcmin_diff, hour_diff)) + if hour_diff > 0.6: + print('TestMaxElong({} {}): EXCESSIVE HOUR ERROR.'.format(name, searchText)) + return 1 + if arcmin_diff > 3.4: + print('TestMaxElong({} {}): EXCESSIVE ARCMIN ERROR.'.format(name, searchText)) + return 1 + return 0 + def SearchElongTest(): - print('SearchElongTest: not yet implemented') - return 1 + for (body, searchText, eventText, angle, visibility) in ElongTestData: + if 0 != TestMaxElong(body, searchText, eventText, angle, visibility): + return 1 + return 0 def Test_Elongation(): if 0 != TestElongFile('longitude/opposition_2018.txt', 0.0): return 1 - if 0 != TestPlanetLongitudes(astronomy.BODY_MERCURY, "temp/c_longitude_Mercury.txt", "inf"): return 1 - if 0 != TestPlanetLongitudes(astronomy.BODY_VENUS, "temp/c_longitude_Venus.txt", "inf"): return 1 - if 0 != TestPlanetLongitudes(astronomy.BODY_MARS, "temp/c_longitude_Mars.txt", "opp"): return 1 - if 0 != TestPlanetLongitudes(astronomy.BODY_JUPITER, "temp/c_longitude_Jupiter.txt", "opp"): return 1 - if 0 != TestPlanetLongitudes(astronomy.BODY_SATURN, "temp/c_longitude_Saturn.txt", "opp"): return 1 - if 0 != TestPlanetLongitudes(astronomy.BODY_URANUS, "temp/c_longitude_Uranus.txt", "opp"): return 1 - if 0 != TestPlanetLongitudes(astronomy.BODY_NEPTUNE, "temp/c_longitude_Neptune.txt", "opp"): return 1 - if 0 != TestPlanetLongitudes(astronomy.BODY_PLUTO, "temp/c_longitude_Pluto.txt", "opp"): return 1 + if 0 != TestPlanetLongitudes(astronomy.BODY_MERCURY, "temp/py_longitude_Mercury.txt", "inf"): return 1 + if 0 != TestPlanetLongitudes(astronomy.BODY_VENUS, "temp/py_longitude_Venus.txt", "inf"): return 1 + if 0 != TestPlanetLongitudes(astronomy.BODY_MARS, "temp/py_longitude_Mars.txt", "opp"): return 1 + if 0 != TestPlanetLongitudes(astronomy.BODY_JUPITER, "temp/py_longitude_Jupiter.txt", "opp"): return 1 + if 0 != TestPlanetLongitudes(astronomy.BODY_SATURN, "temp/py_longitude_Saturn.txt", "opp"): return 1 + if 0 != TestPlanetLongitudes(astronomy.BODY_URANUS, "temp/py_longitude_Uranus.txt", "opp"): return 1 + if 0 != TestPlanetLongitudes(astronomy.BODY_NEPTUNE, "temp/py_longitude_Neptune.txt", "opp"): return 1 + if 0 != TestPlanetLongitudes(astronomy.BODY_PLUTO, "temp/py_longitude_Pluto.txt", "opp"): return 1 if 0 != SearchElongTest(): return 1 return 0 diff --git a/source/python/astronomy.py b/source/python/astronomy.py index 9e61b647..7536716e 100644 --- a/source/python/astronomy.py +++ b/source/python/astronomy.py @@ -2289,15 +2289,13 @@ def SearchMaxElongation(body, startTime): rlon_hi = -s1 t_start = startTime.AddDays(adjust_days) - search1 = SearchRelativeLongitude(body, rlon_lo, t_start) - if search1 is None: + t1 = SearchRelativeLongitude(body, rlon_lo, t_start) + if t1 is None: return None - t1 = search1.time - search2 = SearchRelativeLongitude(body, rlon_hi, t1) - if search2 is None: + t2 = SearchRelativeLongitude(body, rlon_hi, t1) + if t2 is None: return None - t2 = search2.time # Now we have a time range [t1,t2] that brackets a maximum elongation event. # Confirm the bracketing. @@ -2310,12 +2308,12 @@ def SearchMaxElongation(body, startTime): raise InternalError() # there is a bug in the bracketing algorithm! # Use the generic search algorithm to home in on where the slope crosses from negative to positive. - searchx = Search(neg_elong_slope, body, t1, t2, 10.0) - if searchx is None: + tx = Search(_neg_elong_slope, body, t1, t2, 10.0) + if tx is None: return None - if searchx.time.tt >= startTime.tt: - return Elongation(body, searchx.time) + if tx.tt >= startTime.tt: + return Elongation(body, tx) # This event is in the past (earlier than startTime). # We need to search forward from t2 to find the next possible window. @@ -2820,15 +2818,9 @@ def NextLunarApsis(apsis): # + Ecliptic # + EclipticLongitude # + AngleFromSun -# + SearchMaxElongation -# + _neg_elong_slope -# + SearchRelativeLongitude -# + Elongation # + SearchHourAngle # + SearchRiseSet # + Illumination # + SearchPeakMagnitude # + SearchLunarApsis -# + _distance_slope -# + _MoonDistance # + NextLunarApsis