#!/usr/bin/python # Tool for requesting data from US Naval Observatory # Copyright 2007, 2008 Brandon Stafford # # This file is part of Pysolar. # # Pysolar is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # Pysolar is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with Pysolar. If not, see . import datetime, random, solar, time, urllib, urllib2 class Ephemeris: def __init__(self, timestamp, latitude, longitude, elevation, azimuth=0, altitude=0): self.timestamp = timestamp self.latitude = latitude self.longitude = longitude self.elevation = float(elevation) self.azimuth = float(azimuth) self.altitude = float(altitude) class EphemerisComparison: def __init__(self, name1, eph1, name2, eph2): self.timestamp = eph1.timestamp self.latitude = eph1.latitude self.longitude = eph1.longitude self.elevation = eph1.elevation self.name1 = name1 self.alt1 = eph1.altitude self.az1 = eph1.azimuth self.name2 = name2 self.alt2 = eph2.altitude self.az2 = eph2.azimuth self.alt_error = abs(eph1.altitude - eph2.altitude) self.az_error = abs(eph1.azimuth - eph2.azimuth) def RequestEphemerisData(datum): data = EncodeRequest(datum.latitude, datum.longitude, datum.timestamp, datum.elevation) url = 'http://aa.usno.navy.mil/cgi-bin/aa_topocentric2.pl' req = urllib2.Request(url, data) response = urllib2.urlopen(req) lines = response.readlines() response.close() #print lines print lines[21] result = lines[21] tokens = filter(lambda x: x not in ' ', result.split(' ')) print 'Tokens: \n', tokens usno_alt = float(tokens[4]) + float(tokens[5])/60.0 + float(tokens[6])/3600.0 usno_az = float(tokens[7]) + float(tokens[8])/60.0 + float(tokens[9])/3600.0 # print usno_alt # print usno_az result = Ephemeris(datum.timestamp, datum.latitude, datum.longitude, datum.elevation, usno_az, usno_alt) return result def ComparePysolarToUSNO(datum): alt = solar.GetAltitude(float(datum.latitude), float(datum.longitude), datum.timestamp, datum.elevation) pysolar_alt = (90.0 - alt) az = solar.GetAzimuth(float(datum.latitude), float(datum.longitude), datum.timestamp, datum.elevation) pysolar_az = (180.0 - az)%360.0 # print pysolar_alt # print pysolar_az pysolar = Ephemeris(datum.timestamp, datum.latitude, datum.longitude, datum.elevation, pysolar_az, pysolar_alt) c = EphemerisComparison('pysolar', pysolar, 'usno', datum) return c def EncodeRequest(latitude, longitude, timestamp, elevation): """Builds a string of arguments to be passed to the Perl script at the USNO Note that the degree arguments must be integers, or the USNO script chokes.""" params = {} params['FFX'] = '2' # use worldwide locations script params['ID'] = 'Pysolar' params['pos'] = '9' params['obj'] = '10' # Sun params['xxy'] = str(timestamp.year) params['xxm'] = str(timestamp.month) params['xxd'] = str(timestamp.day) params['t1'] = str(timestamp.hour) params['t2'] = str(timestamp.minute) params['t3'] = str(timestamp.second) params['intd'] = '1.0' params['unit'] = '1' params['rep'] = '1' params['place'] = 'Name omitted' (deg, rem) = divmod(longitude, 1) (min, sec) = divmod(rem, 1.0/60.0) params['xx0'] = '1' # longitude (1 = east, -1 = west) params['xx1'] = str(deg) # degrees params['xx2'] = str(min) # minutes params['xx3'] = str(sec) # seconds (deg, rem) = divmod(latitude, 1) (min, sec) = divmod(rem, 1.0/60.0) params['yy0'] = '1' # latitude (1 = north, -1 = south) params['yy1'] = str(deg) # degrees params['yy2'] = str(min) # minutes params['yy3'] = str(sec) # seconds params['hh1'] = str(elevation) # height above sea level in meters params['ZZZ'] = 'END' data = urllib.urlencode(params) return data def GatherRandomEphemeris(): latitude = random.randrange(0, 90) longitude = random.randrange(0, 360) elevation = 0.0 t = datetime.datetime(2008, random.randrange(1, 13), random.randrange(1, 28), random.randrange(0, 24), random.randrange(0, 60), random.randrange(0,60)) query = Ephemeris(t, latitude, longitude, elevation) PrintEphemerisDatum(query) d = RequestEphemerisData(query) PrintEphemerisDatum(d) WriteEphemerisDatumToFile(d, 'usno_data.txt') def PrintEphemerisDatum(datum): print datum.timestamp, datum.latitude, datum.longitude, datum.elevation, datum.azimuth, datum.altitude def ReadEphemeridesLog(logname): data = [] log = open(logname, 'r') lines = log.readlines() log.close() for line in lines: args = line.split(' ') d = datetime.datetime(*(time.strptime(args[0] + ' ' + args[1], '%Y-%m-%d %H:%M:%S')[0:6])) e = Ephemeris(d, args[2], args[3], args[4], args[5], args[6]) data.append(e) return data def WriteEphemerisDatumToFile(d, filename): log = open(filename, 'a') log.write('%s %s %s %s %s %s\n' % (d.timestamp, d.latitude, d.longitude, d.elevation, d.azimuth, d.altitude)) log.close() def WriteComparisonsToCSV(comps, filename): out = open(filename, 'a') for c in comps: out.write('%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n' % (c.timestamp, c.latitude, c.longitude, c.elevation, c.alt1, c.alt2, c.alt_error, c.az1, c.az2, c.az_error)) out.close() if __name__ == '__main__': from scipy import stats import sys ephemerides = ReadEphemeridesLog(sys.argv[1]) comps = [] for e in ephemerides: c = ComparePysolarToUSNO(e) comps.append(c) az_errors = [c.az_error for c in comps] alt_errors = [c.alt_error for c in comps] print '---------------------' print 'Azimuth stats' print 'Mean error: ' + str(stats.mean(az_errors)) print 'Std dev: ' + str(stats.std(az_errors)) print 'Min error: ' + str(stats.tmin(az_errors, None)) print 'Max error: ' + str(stats.tmax(az_errors, None)) print '----------------------' print 'Altitude stats' print 'Mean error: ' + str(stats.mean(alt_errors)) print 'Std dev: '+ str(stats.std(alt_errors)) print 'Min error: ' + str(stats.tmin(alt_errors, None)) print 'Max error: ' + str(stats.tmax(alt_errors, None)) WriteComparisonsToCSV(comps, 'pysolar_v_usno.csv')