Bill_Ritchie

Response to KH

Mar 19th, 2022 (edited)
133
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.94 KB | None | 0 0
  1. ''' Ken .. see also https://pastebin.com/Rqb1YBsJ .. late addition.
  2. Modified by 1billritchie@gmail.com from Ken Harris' post https://pastebin.com/5k8bwnHX .
  3. Written for Ken Harris' eyes, but nothing private herein.
  4. Skyfield V1.41 used .... my pip says that 1.41 is latest! (But 1.42 available on some installations)
  5.  
  6. This is my first python attempt, other than Hello World's, etc to grasp the absolute basics.
  7. Not really mine ... mainly rearrangements of Ken's work.
  8. As a python beginner, have changed variables, etc to more verbose ones solely to help my understanding of the code.
  9.  
  10. Purpose is to quantify a difference in arc distance outputs between this and two comparisons,
  11. (a) https://friendsofthevigilance.org.uk/Astron/Astron.html
  12. (b) http://fer3.com/arc / DATA / Analyze Lunars Online
  13. Both written independently, the latter by Frank Reed, probably the world's leading expert on lunars.
  14. Both usually agree within 0.1 arc minutes.
  15.  
  16. OBSERVATIONS.
  17. 1.
  18. Skyview arc distances differ from comparisons.
  19. (Trend to increase difference with increasing arc values, with Markab as exception to this).
  20. Below table illustrates this.
  21. NB The value of Moon radius has been changed trivially to agree with Astron (line 154)
  22.  
  23. Near Limbs Arc Comparison. 2022 March 5th at 03:00:00 from 38.0N 122.0W 0m altitude
  24. ===================================================================================
  25. Skyfield Fer3
  26. Moon - Body Skyfield reformatted Astron Lunars Analyzer
  27. Regulus 136deg 13' 01.0" 136° 13.0' 136° 07.9' 136° 07.8'
  28. Pollux 100deg 00' 19.1" 100° 00.3' 099° 56.4' 099° 56.4'
  29. Betelgeuse 74deg 48' 41.0" 074° 48.7' 074° 45.7' 074° 45.6'
  30. Aldebaran 56deg 05' 19.0" 056° 05.3' 056° 02.4' 056° 02.3'
  31. Markab 29deg 49' 53.1" 029° 49.9' 029° 43.9' 029° 43.8'
  32.  
  33. Markab - Regulus 149deg 27' 35.8" 149° 27.6' 149° 10.9' n/a
  34. Markab - Regulus 149deg 27' 35.8" 149° 27.6' 149° 27.6' n/a
  35. (geocentric)
  36. ======================================================================================
  37.  
  38. 2.
  39. Markab - Regulus, geocentric. Agrees with comparisons.
  40. Markab - Regulus, topocentric. Skyfield result same as geocentric! Is refraction the problem?
  41. Chosen Markab low alt & azimuths opposite, so refraction subtractive from arc distance.
  42. Markab (altitude 2° 13') appears 16.1' higher due refraction.
  43. Regulus (altitude 25° 43') appears 2.1' higher.
  44. Combined refraction is 18.2'. This reduces Skyfield's 149° 27.6' to 149° 9.4', much closer to desired 149° 10.9'
  45.  
  46. 3.
  47. Changing the altitude argument from 0m (or 6m) to (say) 1000m has (correctly) no effect with star pair,
  48. but correct small (about 0.5') with Moon - Star pair. Again suggests refraction not working WITH ARC calculation.
  49.  
  50. 4.
  51. Refraction IS WORKING with altaz().
  52. EG: print(f'Altitude : {Apparent1.altaz("standard")[0]}') gives correct refracted values.
  53.  
  54. 5.
  55. "Apparent1.separation_from(Apparent2)" gives arc from observer position without refraction, seemingly working
  56. by vector math of observer and two body positions. Whilst it must be possible to use altaz() to first
  57. create hypothetical body positions that compensate for refraction, I think my traditional code,
  58. starting at line 122, is much easier. Results agree with comparisons.
  59.  
  60. 6.
  61. Skyfield's fantastic accuracy claims are probably correct for the effects considered. However, I
  62. have yet to find out what effects are covered. There is more to accuracy than calculation accuracy!
  63. Does aberration also include the observer's (say 1400km/h) velocity on a rotating Earth? Do the WGS84 methods
  64. compensate for parallax in AZIMUTH? How can the accuracy be specified if the user can change body radii?
  65. Does it use barycentric proper motion for binary stars, particularly Rigil Kentaurus and Sirius? Does it
  66. include gravitational deflections of the vertical which, on Earth, are far greater than the included relativistic effects?
  67. When I find answers to such questions, I will use it to improve Astron's methods.
  68.  
  69. line 69
  70. '''
  71. #### Load essentials ####
  72. import skyfield.api, skyfield.data.hipparcos
  73. import numpy, datetime, math, argparse, sys
  74. SkyfieldLoad = skyfield.api.Loader('~/skyfield-data')
  75. Ephemeris = SkyfieldLoad('de421.bsp') # 16.7 MB download
  76. with SkyfieldLoad.open(skyfield.data.hipparcos.URL) as f0:
  77. hippa = skyfield.data.hipparcos.load_dataframe(f0)
  78. from skyfield.api import wgs84, Angle
  79. SkyfieldTimescale = SkyfieldLoad.timescale() # timescale object with built-in UT1-tables
  80.  
  81. #### Calculation function, called from main(). Was within ParseArguments().
  82. def Calculate(Arguments) :
  83. # Unpack Arguments
  84. EventUTC, GeoPos, Body1Name, Body2Name = Arguments
  85.  
  86. # Assign and show time
  87. t = SkyfieldTimescale.ut1(EventUTC.year, EventUTC.month, EventUTC.day,
  88. EventUTC.hour, EventUTC.minute, EventUTC.second + EventUTC.microsecond / 1e6)
  89. print(); print(); print(f't : {t.ut1_strftime()}')
  90. print('================================')
  91.  
  92. # Observer Position
  93. Observer = NameToBodyData('earth') # Observer at Earth centre
  94. if GeoPos: Observer += GeoPos # Observer at specified 3D position (height relative to earth's WGS84 surface)
  95. Barycentric = Observer.at(t) # Barycentric Observer BCRS position
  96.  
  97. # First body
  98. Body1Data = NameToBodyData(Body1Name) # print(f'# Body1Data : {Body1Data}')
  99. Astrometric1 = Barycentric.observe(Body1Data) # Corrected for light time
  100. Apparent1 = Astrometric1.apparent() # relativistic effects and aberration -> Apparent GCRS position
  101. print(f'Body1Name : {Body1Name}')
  102. print(f'RA : {Apparent1.radec("date")[0]}')
  103. print(f'Dec : {Apparent1.radec("date")[1]}')
  104. print(f'SD : {SemiDiameter(Apparent1).arcminutes():.4f}')
  105. if GeoPos:
  106. print(f'Azimuth : {Apparent1.altaz("standard")[1]}')
  107. print(f'Altitude : {Apparent1.altaz("standard")[0]}')
  108. print('================================')
  109.  
  110. # Second body
  111. Body2Data = NameToBodyData(Body2Name) # print(f'# Body2Data : {Body2Data}')
  112. Astrometric2 = Barycentric.observe(Body2Data) # Astrometric ICRS / ICRF position and velocity
  113. Apparent2 = Astrometric2.apparent() # deflection & aberration : Apparent GCRS position and velocity
  114. print(f'Body2Name : {Body2Name}')
  115. print(f'RA : {Apparent2.radec("date")[0]}')
  116. print(f'Dec : {Apparent2.radec("date")[1]}')
  117. print(f'SD : {SemiDiameter(Apparent2).arcminutes():.4f}')
  118. if GeoPos:
  119. print(f'Azimuth : {Apparent2.altaz("standard")[1]}')
  120. print(f'Altitude : {Apparent2.altaz("standard")[0]}')
  121.  
  122. # ADDED CODE STARTS HERE
  123. # Calculate arc between centres - traditional method
  124. Ha1 = Apparent1.altaz("standard")[0].radians
  125. Az1 = Apparent1.altaz("standard")[1].radians
  126. Ha2 = Apparent2.altaz("standard")[0].radians
  127. Az2 = Apparent2.altaz("standard")[1].radians
  128. ArcBetweenCentres = math.degrees(
  129. (math.acos(
  130. math.sin(Ha1) *
  131. math.sin(Ha2) +
  132. math.cos(Ha1) *
  133. math.cos(Ha2) *
  134. math.cos(Az1 - Az2)
  135. )
  136. )
  137. )
  138. print(f'Skyfield: Arc between centres: {Apparent1.separation_from(Apparent2)}')
  139. print('Trad method: Arc between centres:', skyfield.units.Angle(degrees=ArcBetweenCentres)) ; print()
  140. # Skyfield arc between near limbs
  141. NearArc1 = Apparent1.separation_from(Apparent2).degrees - SemiDiameter(Apparent1).degrees - SemiDiameter(Apparent2).degrees
  142. # Trad arc
  143. NearArc2 = ArcBetweenCentres - SemiDiameter(Apparent1).degrees - SemiDiameter(Apparent2).degrees
  144. print('Skyfield: Arc between near limbs: ', skyfield.units.Angle(degrees=NearArc1))
  145. print('Trad method: Arc between near limbs: ', skyfield.units.Angle(degrees=NearArc2)) ; print()
  146. # ADDED CODE ENDS
  147.  
  148. #### Other Functions ####
  149. def SemiDiameter(BodyData): # Apparent
  150. if BodyData.target == 10: # sun
  151. radius = 696340.0 # km
  152. elif BodyData.target == 301: # moon
  153. # radius = 1737.1 # km
  154. radius = 1737.92
  155. else:
  156. radius = 0.0
  157. # print(f'## BodyData.distance().km : {BodyData.distance().km}')
  158. return skyfield.units.Angle(radians=numpy.arcsin(radius / BodyData.distance().km))
  159.  
  160. ####
  161. def NameToBodyData(Name) :
  162. Name = Name.lower()
  163. if Name in ['sun', 'earth', 'moon']:
  164. BodyData = Ephemeris[Name] # bodycentric
  165. elif Name in ['venus', 'mars', 'jupiter', 'saturn']:
  166. BodyData = Ephemeris[Name + ' barycenter'] # barycentric (why?)
  167. else:
  168. if Name == 'hamal': HipNumber = 9884
  169. elif Name == 'aldebaran': HipNumber = 21421
  170. elif Name == 'betelgeuse': HipNumber = 27989
  171. elif Name == 'sirius': HipNumber = 32349
  172. elif Name == 'pollux': HipNumber = 37826
  173. elif Name == 'regulus': HipNumber = 49669
  174. elif Name == 'spica': HipNumber = 65474
  175. elif Name == 'antares': HipNumber = 80763
  176. elif Name == 'altair': HipNumber = 97649
  177. elif Name == 'fomalhaut': HipNumber = 113368
  178. elif Name == 'markab': HipNumber = 113963
  179. BodyData = skyfield.api.Star.from_dataframe(hippa.loc[HipNumber])
  180. # UnboundLocalError if Name not in above
  181. return BodyData
  182.  
  183. ####
  184. def ParseArguments(Arguments):
  185. Arguments = vars(Arguments) # usings vars() to create dict
  186.  
  187. # --time
  188. if Arguments['time'] is None:
  189. EventUTC = datetime.datetime.utcnow()
  190. else:
  191. EventUTC = datetime.datetime.strptime(Arguments['time'], '%Y-%m-%dT%H:%M:%S')
  192.  
  193. # --geo
  194. if Arguments['geo']:
  195. GeoArgs = Arguments['geo'].split(',')
  196. # use "parse" ? : r0 = '{lat:g},{:s}{lng:g}{}' # ignore Altitude
  197. # ITRS ECEF # XXX height used for "dip" calc (in altaz) ?
  198. GeoPos = skyfield.api.wgs84.latlon(float(GeoArgs[0]), float(GeoArgs[1]), float(GeoArgs[2]))
  199. else:
  200. GeoPos = None
  201.  
  202. # -n1, n2
  203. Body1Name = Arguments['Body1Name']
  204. Body2Name = Arguments['Body2Name']
  205.  
  206. # Do the hard work elsewhere
  207. return EventUTC, GeoPos, Body1Name, Body2Name
  208.  
  209. ####
  210. def main():
  211. parser = argparse.ArgumentParser(description="almanac")
  212. parser.add_argument("-n1", "--Body1Name", default = 'Aldebaran', type = str, help="heavenly body") # was -n
  213. parser.add_argument("-n2", "--Body2Name", default = 'Moon', type = str, help="heavenly body") # was -N
  214. parser.add_argument("-t", "--time", default = '2022-03-05T03:00:00', help="time : %Y-%m-%dT%H:%M:%S")
  215. parser.add_argument("-g", "--geo", default = '38.0,-122.0,0', help="assumed position : lat,lng,meters") # SF area
  216. parser.add_argument("-T", "--temp", default = "standard", help="temperature_C (for refraction)")
  217. Calculate(ParseArguments(parser.parse_args()))
  218.  
  219. '''
  220. # unused code
  221. def PrintBodyInfo(Astrometric, Apparent): # print lots of debug info
  222. #print(f'## Astrometric : {Astrometric}')
  223. #print(f'## Apparent : {Apparent}')
  224. #print(f'## Apparent.center : {Apparent.center}')
  225. #print(f'## Apparent.target : {Apparent.target}')
  226. #print(f'## Ephemeris.names()[Apparent.center] : {Ephemeris.names()[Apparent.center]}') # doesn't work w/ Ephemeris + latlon
  227. #print(f'## Ephemeris.names()[Apparent.target] : {Ephemeris.names()[Apparent.target]}') # doesn't work w/ stars
  228. #print(f'# Astrometric.radec("date") : {Astrometric.radec("date")}')
  229. '''
  230.  
  231. if __name__ == '__main__':
  232. sys.exit(main())
  233.  
  234. '''
  235. Scratch pad for copy/paste command lines
  236. python BR_Mods.py -t 2022-03-05T03:00:00 -n1 Aldebaran -n2 Moon -g 38.0,-122,0
  237. # python BR_Mods.py
  238. # python BR_Mods.py -t 2022-03-05T03:00:00 -n1 Markab -n2 Regulus -g 38.0,-122,1000
  239. '''
Add Comment
Please, Sign In to add comment