{ "metadata": { "Author": "Tom Spalding", "Category": "code", "Date": "2014-10-31", "Tags": "san francisco, pyskyalmanac, python, night sky, cities, pyephem, astronomy, space", "Title": "A smattering of cities to observe the sky", "name": "", "signature": "sha256:c8772deba67a304e2188ca7d79e3907c53107136c2abf358d832ace8a0e9a9cc", "slug": "cities-for-skyalmanac" }, "nbformat": 3, "nbformat_minor": 0, "worksheets": [ { "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "#A smattering of cities to observe the sky\n", "I really love the night sky, but in San Francisco the night sky is sometimes more observable on the computer if you know what I mean.. you don't? It is REALLY FOGGY ALL THE TIME west of [Sutro Mountain](https://en.wikipedia.org/wiki/Mount_Sutro). Hobby-wise, I've been working on [a PySkyAlmanac fork](https://github.com/digitalvapor/PySkyAlmanac) and have primarily been testing the almanac with my own location. See [the generated San Francisco chart here](https://digitalvapor.github.io/PySkyAlmanac/). I've been making it a wee bit more 'automatic', and now want to test for a smattering of choice cities.\n", "\n", "[Brandon Rhodesmill](http://rhodesmill.org/brandon/) who wrote [PyEphem](https://github.com/brandon-rhodes/pyephem) has a [modest database of cities](https://github.com/brandon-rhodes/pyephem/blob/master/ephem/cities.py) that you can use when setting up an astronomical observer. See his quick reference for [settting up an observer](http://rhodesmill.org/pyephem/quick.html#body-compute-observer).\n", "\n", "Here is an example, using my home town of [Winter Springs, FL](https://en.wikipedia.org/wiki/Winter_Springs,_Florida). Using the coordinates from [geohack](https://tools.wmflabs.org/geohack/geohack.php?pagename=Winter_Springs%2C_Florida¶ms=28_41_36_N_81_16_44_W_region:US_type:city) and elevation (m) from Wikipedia is a breeze, but it is ... more breezy? to just use the database as you can see for San Francisco.\n", "\n", "```\n", "import ephem\n", "\n", "# Winter Springs, FL\n", "ws = ephem.Observer()\n", "ws.lon = '28.693333'\n", "ws.lat = '-81.278889'\n", "ws.elevation = 16\n", "ws.date = '2014/10/30 13:20:56'\n", "\n", "# San Francisco, CA\n", "obs = ephem.city('San Francisco')\n", "obs.date = '2014/10/30 13:20:56'\n", "```\n", "\n", "These cities are based on some world city criterion. The input is [cities.in](https://github.com/brandon-rhodes/pyephem/blob/master/data/cities.in), to [cities.py](https://github.com/brandon-rhodes/pyephem/blob/master/generate/cities.py) which looks up each city on [fallingrain.com](http://www.fallingrain.com/), and [rebuild-city-data](https://github.com/brandon-rhodes/pyephem/blob/master/bin/rebuild-city-data) with google maps.\n", "\n", "I'm not sure yet where the initial city data came from, but if you search for `global city`, you'll get similar lists.\n", "\n", "I have some criterion for testing the sky almanac. I want cities near the 40\u00b0N, 50\u00b0N, and 30\u00b0S latitudes to compare to the [Skygazers Almanac](https://www.shopatsky.com/product/skygazers-almanac-2014-40-deg-n/calendars-and-almanacs) calculated by [Roger W. Sinnott](http://www.skyandtelescope.com/about-us/roger-w-sinnott/). I also wanted some locations near the equator and arctic / antarctic circles." ] }, { "cell_type": "code", "collapsed": false, "input": [ "from ephem import cities\n", "all_cities = cities._city_data\n", "num_cities = len(all_cities)\n", "print('{} cities in PyEphem'.format(num_cities))\n", "\n", "all_lat = []\n", "all_lon = []\n", "all_elev = []\n", "\n", "for name in all_cities.keys():\n", " all_lat.append(float(all_cities[name][0]))\n", " all_lon.append(float(all_cities[name][1]))\n", " all_elev.append(float(all_cities[name][2]))\n", "\n", "city_list = zip(all_cities,all_lat,all_lon,all_elev)\n", "city_list = sorted(city_list,key=lambda x:x[1])\n", "northernmost = city_list.pop()\n", "southernmost = city_list[0]\n", "city_list.remove(southernmost)\n", "print('northernmost: {} ({}\u00b0N)'.format(northernmost[0],northernmost[1]))\n", "print('southernmost: {} ({}\u00b0S)'.format(southernmost[0],southernmost[1]))\n", "\n", "n = [] # northern hemisphere\n", "s = [] # southern hemisphere\n", "\n", "for city in city_list:\n", " if(city[1]>=0.0):\n", " n.append(city)\n", " else:\n", " s.append(city)\n", "\n", "nearest_equator_pos = n[0]\n", "n.remove(nearest_equator_pos)\n", "nearest_equator_neg = s.pop()\n", "print('nearest equator in northern hemisphere: {} ({}\u00b0N)'.format(nearest_equator_pos[0],nearest_equator_pos[1]))\n", "print('nearest equator in southern hemisphere: {} ({}\u00b0S)'.format(nearest_equator_neg[0],nearest_equator_neg[1]))\n", "\n", "def city_nearest_lat(list_of_cities,latitude):\n", " sorted_by_closest = sorted(list_of_cities,key=lambda x:(abs(x[1]-latitude)))\n", " return sorted_by_closest[0]\n", "\n", "neg_30S = city_nearest_lat(s,-30.0)\n", "print('nearest to 30\u00b0S: {} ({}\u00b0S)'.format(neg_30S[0],neg_30S[1]))\n", "neg_40N = city_nearest_lat(n,40.0)\n", "print('nearest to 40\u00b0N: {} ({}\u00b0S)'.format(neg_40N[0],neg_40N[1]))\n", "neg_50N = city_nearest_lat(n,50.0)\n", "print('nearest to 50\u00b0N: {} ({}\u00b0S)'.format(neg_50N[0],neg_50N[1]))\n", "\n", "cities_to_test = [northernmost[0],neg_50N[0],neg_40N[0],nearest_equator_pos[0],nearest_equator_neg[0],neg_30S[0],southernmost[0]]\n", "print('cities to test, from North to South {}'.format(cities_to_test))" ], "language": "python", "metadata": {}, "outputs": [ { "output_type": "stream", "stream": "stdout", "text": [ "122 cities in PyEphem\n", "northernmost: Helsinki (60.1698125\u00b0N)\n", "southernmost: Wellington (-41.2924945\u00b0S)\n", "nearest equator in northern hemisphere: Singapore (1.352083\u00b0N)\n", "nearest equator in southern hemisphere: Jakarta (-6.211544\u00b0S)\n", "nearest to 30\u00b0S: Brisbane (-27.4709331\u00b0S)\n", "nearest to 40\u00b0N: Columbus (39.9611755\u00b0S)\n", "nearest to 50\u00b0N: Prague (50.0878114\u00b0S)\n", "cities to test, from North to South ['Helsinki', 'Prague', 'Columbus', 'Singapore', 'Jakarta', 'Brisbane', 'Wellington']\n" ] } ], "prompt_number": 1 }, { "cell_type": "markdown", "metadata": {}, "source": [ "[key](https://docs.python.org/3/howto/sorting.html?highlight=key#key-functions) is what to sort by after a function is called on each element. [lambda](https://docs.python.org/3/reference/expressions.html#lambda) is an anonymous function, so i dont have to define a new function for just returning the second value `x[1]`. same goes for the other use of lambda above in the `city_nearest_lat()` method. \n", "\n", "Now, I can set up a different observer at each of my test cities :)\n", "\n", "Download the San Francisco Sky Gazing Almanac as a [png](https://github.com/digitalvapor/PySkyAlmanac/raw/gh-pages/2014_San_Francisco.png) or [pdf](https://github.com/digitalvapor/PySkyAlmanac/raw/master/almanac_2014_San_Francisco.pdf). I encourage you to fork the project and [host your city's own](https://github.com/digitalvapor/PySkyAlmanac#fork) almanac.\n", "\n", "![SF](https://raw.githubusercontent.com/digitalvapor/PySkyAlmanac/gh-pages/2014_San_Francisco_small.png \"San Francisco Star Gazer's Almanac\")" ] }, { "cell_type": "code", "collapsed": false, "input": [], "language": "python", "metadata": {}, "outputs": [] } ], "metadata": {} } ] }