Migrate to a world map / grey line that uses Cartopy (#64)

Migrating grey line functionality over to a Cartopy-based implementation to address issue #62.

Also renamed GreyLine to WorldMap, and bumped the version to v1.1.0-dev.
pull/65/head
Christian T. Jacobs 2018-02-24 13:24:39 +00:00 zatwierdzone przez GitHub
rodzic f283df065b
commit f222d5cc30
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
14 zmienionych plików z 117 dodań i 71 usunięć

Wyświetl plik

@ -1,6 +1,5 @@
sudo: required sudo: required
dist: trusty dist: trusty
group: deprecated-2017Q2
language: python language: python
@ -12,7 +11,7 @@ virtualenv:
before_install: before_install:
- sudo apt-get update -qq - sudo apt-get update -qq
- sudo apt-get install -yq xvfb gir1.2-gtk-3.0 python3-gi-cairo python-mpltoolkits.basemap python3-numpy python3-matplotlib python3-sphinx python-libhamlib2 python3-flake8 python3-pip - sudo apt-get install -yq xvfb python3 python3-pip gir1.2-gtk-3.0 python3-gi-cairo python3-flake8 python3-numpy python3-matplotlib python3-sphinx python-libhamlib2
- "export DISPLAY=:99.0" - "export DISPLAY=:99.0"
- "sh -e /etc/init.d/xvfb start" - "sh -e /etc/init.d/xvfb start"

Wyświetl plik

@ -1,5 +1,19 @@
# Change Log # Change Log
## [UNRELEASED]
### Added
- Added support for the SAT_NAME, SAT_MODE, PROP_MODE, and GRIDSQUARE ADIF fields for the purposes of satellite QSO logging.
- Pinpointing of callsigns on the world map by looking up the latitude-longitude coordinates based on the value in the COUNTRY field. A new right-click popup menu has been created for this purpose.
- Added basic copy/paste functionality for individual records.
- Added a requirements.txt file for the purpose of installing dependencies.
### Changed
- Renamed the GreyLine class to WorldMap, since it now does more than just grey line plotting.
- Improved the section on dependencies in the README.
### Fixed
- Updated the list of supported ADIF fields.
## [1.0.0] - 2017-08-02 ## [1.0.0] - 2017-08-02
### Added ### Added
- Pin-pointing of QTH on grey line map. - Pin-pointing of QTH on grey line map.
@ -95,6 +109,7 @@
- QSO filtering and sorting. - QSO filtering and sorting.
- Duplicate record removal. - Duplicate record removal.
[UNRELEASED]: https://github.com/ctjacobs/pyqso/compare/v1.0.0...HEAD
[1.0.0]: https://github.com/ctjacobs/pyqso/compare/v0.3...v1.0.0 [1.0.0]: https://github.com/ctjacobs/pyqso/compare/v0.3...v1.0.0
[0.3]: https://github.com/ctjacobs/pyqso/compare/v0.2...v0.3 [0.3]: https://github.com/ctjacobs/pyqso/compare/v0.2...v0.3
[0.2]: https://github.com/ctjacobs/pyqso/compare/v0.1...v0.2 [0.2]: https://github.com/ctjacobs/pyqso/compare/v0.1...v0.2

Wyświetl plik

@ -30,17 +30,19 @@ As the name suggests, PyQSO is written primarily in the [Python](https://www.pyt
* gir1.2-gtk-3.0 * gir1.2-gtk-3.0
* python3-gi-cairo * python3-gi-cairo
Several extra packages are necessary to enable the full functionality of PyQSO, such as the grey line tool. Many of these (specified in the `requirements.txt` file) can be readily installed system-wide using the Python package manager by issuing the following command in the terminal: Several extra packages are necessary to enable the full functionality of PyQSO. Many of these (specified in the `requirements.txt` file) can be readily installed system-wide using the Python package manager by issuing the following command in the terminal:
sudo pip3 install -U -r requirements.txt sudo pip3 install -U -r requirements.txt
but the complete list is given below: but the complete list is given below:
* python3-matplotlib (version 1.3.0 or later) * python3-matplotlib (version 1.3.0 or later)
* python3-mpltoolkits.basemap
* python3-numpy * python3-numpy
* libxcb-render0-dev * libxcb-render0-dev
* python3-cairocffi * python3-cairocffi
* libproj-dev (version 4.9.0 or later)
* libgeos-dev (version 3.3.3 or later)
* [cartopy](http://scitools.org.uk/cartopy/) (for drawing the world map and grey line)
* [geocoder](https://pypi.python.org/pypi/geocoder) (for QTH lookups) * [geocoder](https://pypi.python.org/pypi/geocoder) (for QTH lookups)
* python3-sphinx (for building the documentation) * python3-sphinx (for building the documentation)
* python3-hamlib (for Hamlib support) * python3-hamlib (for Hamlib support)

Wyświetl plik

@ -51,16 +51,16 @@ master_doc = 'index'
# General information about the project. # General information about the project.
project = u'PyQSO' project = u'PyQSO'
copyright = u'2015-2017, Christian Thomas Jacobs' copyright = u'2015-2018, Christian Thomas Jacobs'
# The version info for the project you're documenting, acts as replacement for # The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the # |version| and |release|, also used in various other places throughout the
# built documents. # built documents.
# #
# The short X.Y version. # The short X.Y version.
version = '1.0.0' version = '1.1.0-dev'
# The full version, including alpha/beta/rc tags. # The full version, including alpha/beta/rc tags.
release = '1.0.0' release = '1.1.0-dev'
# The language for content autogenerated by Sphinx. Refer to documentation # The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages. # for a list of supported languages.

Wyświetl plik

@ -24,7 +24,7 @@ include:
- Progress tracker for the `DXCC <http://www.arrl.org/dxcc/>`_ award. - Progress tracker for the `DXCC <http://www.arrl.org/dxcc/>`_ award.
- Grey line plotter. - World map with grey line.
- Filter QSOs based on callsign (e.g. only display contacts with callsigns beginning with "M6"). - Filter QSOs based on callsign (e.g. only display contacts with callsigns beginning with "M6").
@ -65,5 +65,5 @@ If you have any comments or questions about PyQSO, please send them via email to
Structure of this documentation Structure of this documentation
------------------------------- -------------------------------
The structure of this documentation is as follows. The section on `Getting Started <getting_started.html>`_ provides information on the PyQSO installation process through to creating a new logbook (or opening an existing one). The `Log Management <log_management.html>`_ section explains how to create a log in the logbook, as well as the basic operations that users can perform with existing logs, such as printing, importing/exporting logs, and sorting. The `Record Management <record_management.html>`_ section deals with the bottom layer of the three-tier model - the creation, deletion, and modification of QSO records in a log. The `Toolbox <toolbox.html>`_ section introduces the PyQSO toolbox which contains three tools that are useful to amateur radio operators: a DX cluster, a grey line plotter, and an awards progress tracker. Finally, the `Preferences <preferences.html>`_ section explains how users can set up Hamlib support and show/hide various fields in a log, along with several other user preferences that can be set via the Preferences dialog window. A `keyboard shortcuts list <shortcuts.html>`_ is also available for reference. The structure of this documentation is as follows. The section on `Getting Started <getting_started.html>`_ provides information on the PyQSO installation process through to creating a new logbook (or opening an existing one). The `Log Management <log_management.html>`_ section explains how to create a log in the logbook, as well as the basic operations that users can perform with existing logs, such as printing, importing/exporting logs, and sorting. The `Record Management <record_management.html>`_ section deals with the bottom layer of the three-tier model - the creation, deletion, and modification of QSO records in a log. The `Toolbox <toolbox.html>`_ section introduces the PyQSO toolbox which contains three tools that are useful to amateur radio operators: a DX cluster, a world map, and an awards progress tracker. Finally, the `Preferences <preferences.html>`_ section explains how users can set up Hamlib support and show/hide various fields in a log, along with several other user preferences that can be set via the Preferences dialog window. A `keyboard shortcuts list <shortcuts.html>`_ is also available for reference.

Wyświetl plik

@ -17,7 +17,7 @@ Under the ``General`` tab, the user can choose to:
- Keep the ``Add Record`` dialog window open after a new QSO is added, in preparation for the next QSO. - Keep the ``Add Record`` dialog window open after a new QSO is added, in preparation for the next QSO.
- Pin-point the user's QTH on the grey line map by specifying the latitude-longitude coordinates (or looking them up based on the QTH's name, e.g. city name). - Pin-point the user's QTH on the world map by specifying the latitude-longitude coordinates (or looking them up based on the QTH's name, e.g. city name).
.. _figure:summary: .. _figure:summary:
.. figure:: images/summary.png .. figure:: images/summary.png

Wyświetl plik

@ -31,20 +31,18 @@ adjacent ``Send Command`` button (or pressing the Enter key).
The DX cluster frame. The DX cluster frame.
Grey line World map
--------- ---------
The grey line tool (see figure:grey_line_) can be used to The world map tool (see figure:world_map_) can be used to plot the QTH of your station and stations that you have contacted. It also features a grey line to check which parts of the world are in darkness. The position of the grey line is automatically updated every 30 minutes.
check which parts of the world are in darkness. The position of the grey
line is automatically updated every 30 minutes.
The user's QTH can be pin-pointed on the map by specifying the QTH's location (e.g. city name) and latitude-longitude coordinates in the preferences. If the `geocoder <https://pypi.python.org/pypi/geocoder>`_ library is installed then these coordinates can be filled in for you by clicking the lookup button after entering the QTH's name, otherwise the coordinates will have to be entered manually. The user's QTH can be pin-pointed on the map by specifying the QTH's location (e.g. city name) and latitude-longitude coordinates in the preferences. If the `geocoder <https://pypi.python.org/pypi/geocoder>`_ library is installed then these coordinates can be filled in for you by clicking the lookup button after entering the QTH's name, otherwise the coordinates will have to be entered manually.
.. _figure:grey_line: .. _figure:world_map:
.. figure:: images/grey_line.png .. figure:: images/world_map.png
:align: center :align: center
The grey line tool with the user's QTH (e.g. Southampton) pin-pointed on the map. The world map tool with the user's QTH (e.g. Southampton) pin-pointed.
Awards Awards
------ ------

Wyświetl plik

@ -1,6 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# Copyright (C) 2012-2017 Christian Thomas Jacobs. # Copyright (C) 2012-2018 Christian Thomas Jacobs.
# This file is part of PyQSO. # This file is part of PyQSO.
@ -1053,7 +1053,7 @@ class Logbook:
return return
def pinpoint_callback(self, widget=None, path=None): def pinpoint_callback(self, widget=None, path=None):
""" A callback function used to pinpoint the callsign on the grey line map. """ """ A callback function used to pinpoint the callsign on the world map. """
try: try:
log_index = self.get_log_index() log_index = self.get_log_index()
@ -1065,7 +1065,7 @@ class Logbook:
logging.error(e) logging.error(e)
return return
self.application.toolbox.grey_line.pinpoint(r) self.application.toolbox.world_map.pinpoint(r)
return return

Wyświetl plik

@ -33,7 +33,7 @@ class Popup:
# Collect Gtk menu items and connect signals. # Collect Gtk menu items and connect signals.
self.items = {} self.items = {}
# Plot selected QSO on the grey line map. # Plot selected QSO on the world map.
self.items["PINPOINT"] = self.builder.get_object("mitem_pinpoint") self.items["PINPOINT"] = self.builder.get_object("mitem_pinpoint")
self.items["PINPOINT"].connect("activate", self.application.logbook.pinpoint_callback) self.items["PINPOINT"].connect("activate", self.application.logbook.pinpoint_callback)

Wyświetl plik

@ -792,7 +792,7 @@
</packing> </packing>
</child> </child>
<child> <child>
<object class="GtkBox" id="greyline"> <object class="GtkBox" id="worldmap">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="orientation">vertical</property> <property name="orientation">vertical</property>
@ -806,10 +806,10 @@
</packing> </packing>
</child> </child>
<child type="tab"> <child type="tab">
<object class="GtkLabel" id="greyline_label"> <object class="GtkLabel" id="worldmap_label">
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">False</property> <property name="can_focus">False</property>
<property name="label" translatable="yes">Grey Line</property> <property name="label" translatable="yes">World Map</property>
</object> </object>
<packing> <packing>
<property name="position">1</property> <property name="position">1</property>
@ -908,8 +908,8 @@
<property name="type_hint">dialog</property> <property name="type_hint">dialog</property>
<property name="transient_for">pyqso</property> <property name="transient_for">pyqso</property>
<property name="program_name">PyQSO</property> <property name="program_name">PyQSO</property>
<property name="version">1.0.0</property> <property name="version">1.1.0-dev</property>
<property name="copyright" translatable="yes">Copyright (C) 2012-2017 Christian Thomas Jacobs</property> <property name="copyright" translatable="yes">Copyright (C) 2012-2018 Christian Thomas Jacobs</property>
<property name="comments" translatable="yes">A contact logging tool for amateur radio operators.</property> <property name="comments" translatable="yes">A contact logging tool for amateur radio operators.</property>
<property name="website">http://christianjacobs.uk/pyqso</property> <property name="website">http://christianjacobs.uk/pyqso</property>
<property name="license" translatable="yes">This program is free software: you can redistribute it and/or modify <property name="license" translatable="yes">This program is free software: you can redistribute it and/or modify
@ -1460,7 +1460,7 @@ along with this program. If not, see &lt;http://www.gnu.org/licenses/&gt;.</pro
<property name="spacing">2</property> <property name="spacing">2</property>
<child> <child>
<object class="GtkCheckButton" id="general_show_qth_checkbutton"> <object class="GtkCheckButton" id="general_show_qth_checkbutton">
<property name="label" translatable="yes">Pin-point QTH on grey line map</property> <property name="label" translatable="yes">Pin-point QTH on world map</property>
<property name="visible">True</property> <property name="visible">True</property>
<property name="can_focus">True</property> <property name="can_focus">True</property>
<property name="receives_default">False</property> <property name="receives_default">False</property>

Wyświetl plik

@ -1,6 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# Copyright (C) 2013-2017 Christian Thomas Jacobs. # Copyright (C) 2013-2018 Christian Thomas Jacobs.
# This file is part of PyQSO. # This file is part of PyQSO.
@ -18,7 +18,7 @@
# along with PyQSO. If not, see <http://www.gnu.org/licenses/>. # along with PyQSO. If not, see <http://www.gnu.org/licenses/>.
from pyqso.dx_cluster import DXCluster from pyqso.dx_cluster import DXCluster
from pyqso.grey_line import GreyLine from pyqso.world_map import WorldMap
from pyqso.awards import Awards from pyqso.awards import Awards
@ -38,7 +38,7 @@ class Toolbox:
self.tools = self.builder.get_object("tools") self.tools = self.builder.get_object("tools")
self.dx_cluster = DXCluster(self.application) self.dx_cluster = DXCluster(self.application)
self.grey_line = GreyLine(self.application) self.world_map = WorldMap(self.application)
self.awards = Awards(self.application) self.awards = Awards(self.application)
self.tools.connect_after("switch-page", self.on_switch_page) self.tools.connect_after("switch-page", self.on_switch_page)
@ -52,7 +52,7 @@ class Toolbox:
return return
def on_switch_page(self, widget, label, new_page): def on_switch_page(self, widget, label, new_page):
""" Re-draw the Grey Line if the user switches to the grey line tab. """ """ Re-draw the WorldMap if the user switches to the World Map tab. """
if(widget.get_tab_label(label).get_text() == "Grey Line"): if(widget.get_tab_label(label).get_text() == "World Map"):
self.grey_line.draw() self.world_map.draw()
return return

Wyświetl plik

@ -1,6 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# Copyright (C) 2013-2017 Christian Thomas Jacobs. # Copyright (C) 2013-2018 Christian Thomas Jacobs.
# This file is part of PyQSO. # This file is part of PyQSO.
@ -19,8 +19,8 @@
from gi.repository import GObject from gi.repository import GObject
import logging import logging
from datetime import datetime
from os.path import expanduser from os.path import expanduser
from datetime import datetime
try: try:
import configparser import configparser
except ImportError: except ImportError:
@ -30,13 +30,13 @@ try:
logging.info("Using version %s of numpy." % (numpy.__version__)) logging.info("Using version %s of numpy." % (numpy.__version__))
import matplotlib import matplotlib
logging.info("Using version %s of matplotlib." % (matplotlib.__version__)) logging.info("Using version %s of matplotlib." % (matplotlib.__version__))
import mpl_toolkits.basemap import cartopy
logging.info("Using version %s of mpl_toolkits.basemap." % (mpl_toolkits.basemap.__version__)) logging.info("Using version %s of cartopy." % (cartopy.__version__))
from matplotlib.backends.backend_gtk3cairo import FigureCanvasGTK3Cairo as FigureCanvas from matplotlib.backends.backend_gtk3cairo import FigureCanvasGTK3Cairo as FigureCanvas
have_necessary_modules = True have_necessary_modules = True
except ImportError as e: except ImportError as e:
logging.warning(e) logging.warning(e)
logging.warning("Could not import a non-standard Python module needed by the GreyLine class, or the version of the non-standard module is too old. Check that all the PyQSO dependencies are satisfied.") logging.warning("Could not import a non-standard Python module needed by the WorldMap class, or the version of the non-standard module is too old. Check that all the PyQSO dependencies are satisfied.")
have_necessary_modules = False have_necessary_modules = False
try: try:
import geocoder import geocoder
@ -64,16 +64,16 @@ class Point:
return return
class GreyLine: class WorldMap:
""" A tool for visualising the grey line. """ """ A tool for visualising the world map. """
def __init__(self, application): def __init__(self, application):
""" Set up the drawing canvas and the timer which will re-plot the grey line every 30 minutes. """ Set up the drawing canvas and the timer which will re-plot the world map every 30 minutes.
:arg application: The PyQSO application containing the main Gtk window, etc. :arg application: The PyQSO application containing the main Gtk window, etc.
""" """
logging.debug("Setting up the grey line...") logging.debug("Setting up the world map...")
self.application = application self.application = application
self.builder = self.application.builder self.builder = self.application.builder
@ -82,10 +82,10 @@ class GreyLine:
if(have_necessary_modules): if(have_necessary_modules):
self.fig = matplotlib.figure.Figure() self.fig = matplotlib.figure.Figure()
self.canvas = FigureCanvas(self.fig) # For embedding in the Gtk application self.canvas = FigureCanvas(self.fig) # For embedding in the Gtk application
self.builder.get_object("greyline").pack_start(self.canvas, True, True, 0) self.builder.get_object("worldmap").pack_start(self.canvas, True, True, 0)
self.refresh_event = GObject.timeout_add(1800000, self.draw) # Re-draw the grey line automatically after 30 minutes (if the grey line tool is visible). self.refresh_event = GObject.timeout_add(1800000, self.draw) # Re-draw the world map automatically after 30 minutes (if the world map tool is visible).
# Plot the QTH coordinates, if available. # Add the QTH coordinates for plotting, if available.
config = configparser.ConfigParser() config = configparser.ConfigParser()
have_config = (config.read(expanduser('~/.config/pyqso/preferences.ini')) != []) have_config = (config.read(expanduser('~/.config/pyqso/preferences.ini')) != [])
(section, option) = ("general", "show_qth") (section, option) = ("general", "show_qth")
@ -97,11 +97,11 @@ class GreyLine:
qth_longitude = float(config.get("general", "qth_longitude")) qth_longitude = float(config.get("general", "qth_longitude"))
self.add_point(qth_name, qth_latitude, qth_longitude, "ro") self.add_point(qth_name, qth_latitude, qth_longitude, "ro")
except ValueError: except ValueError:
logging.warning("Unable to get the QTH name, latitude and/or longitude. The QTH will not be pinpointed on the grey line map. Check preferences?") logging.warning("Unable to get the QTH name, latitude and/or longitude. The QTH will not be pinpointed on the world map. Check preferences?")
self.builder.get_object("greyline").show_all() self.builder.get_object("worldmap").show_all()
logging.debug("Grey line ready!") logging.debug("World map ready!")
return return
@ -119,7 +119,7 @@ class GreyLine:
return return
def pinpoint(self, r): def pinpoint(self, r):
""" Pinpoint the location of a QSO on the grey line map based on the COUNTRY field. """ Pinpoint the location of a QSO on the world map based on the COUNTRY field.
:arg r: The QSO record containing the location to pinpoint. :arg r: The QSO record containing the location to pinpoint.
""" """
@ -145,7 +145,7 @@ class GreyLine:
def draw(self): def draw(self):
""" Draw the world map and the grey line on top of it. """ Draw the world map and the grey line on top of it.
:returns: Always returns True to satisfy the GObject timer, unless the necessary GreyLine dependencies are not satisfied (in which case, the method returns False so as to not re-draw the canvas). :returns: Always returns True to satisfy the GObject timer, unless the necessary WorldMap dependencies are not satisfied (in which case, the method returns False so as to not re-draw the canvas).
:rtype: bool :rtype: bool
""" """
@ -153,32 +153,64 @@ class GreyLine:
toolbox = self.builder.get_object("toolbox") toolbox = self.builder.get_object("toolbox")
tools = self.builder.get_object("tools") tools = self.builder.get_object("tools")
if(tools.get_current_page() != 1 or not toolbox.get_visible()): if(tools.get_current_page() != 1 or not toolbox.get_visible()):
# Don't re-draw if the grey line is not visible. # Don't re-draw if the world map is not visible.
return True # We need to return True in case this is method was called by a timer event. return True # We need to return True in case this is method was called by a timer event.
else: else:
logging.debug("Drawing the grey line...") # Set up the world map.
# Re-draw the grey line logging.debug("Drawing the world map...")
self.fig.clf() self.fig.clf()
sub = self.fig.add_subplot(111) ax = self.fig.add_subplot(111, projection=cartopy.crs.PlateCarree())
ax.set_extent([-180, 180, -90, 90])
ax.set_aspect("auto")
# Draw the map of the world. This is based on the example from: gl = ax.gridlines(draw_labels=True)
# http://matplotlib.org/basemap/users/examples.html gl.xlabels_top = False
m = mpl_toolkits.basemap.Basemap(projection="mill", lon_0=0, ax=sub, resolution="c", fix_aspect=False) gl.ylabels_right = False
m.drawcountries(linewidth=0.4) gl.xformatter = cartopy.mpl.gridliner.LONGITUDE_FORMATTER
m.drawcoastlines(linewidth=0.4) gl.yformatter = cartopy.mpl.gridliner.LATITUDE_FORMATTER
m.drawparallels(numpy.arange(-90, 90, 30), labels=[1, 0, 0, 0]) ax.add_feature(cartopy.feature.LAND, facecolor="green")
m.drawmeridians(numpy.arange(m.lonmin, m.lonmax+30, 60), labels=[0, 0, 0, 1]) ax.add_feature(cartopy.feature.OCEAN, color="skyblue")
m.drawmapboundary(fill_color="skyblue") ax.add_feature(cartopy.feature.COASTLINE)
m.fillcontinents(color="green", lake_color="skyblue") ax.add_feature(cartopy.feature.BORDERS, alpha=0.4)
m.nightshade(datetime.utcnow()) # Add in the grey line using UTC time. Note that this requires NetCDF.
logging.debug("Grey line drawn.") # Draw the grey line. This is based on the code from the Cartopy Aurora Forecast example (http://scitools.org.uk/cartopy/docs/latest/gallery/aurora_forecast.html) and used under the Open Government Licence (http://scitools.org.uk/cartopy/docs/v0.15/copyright.html).
logging.debug("Drawing the grey line...")
dt = datetime.utcnow()
axial_tilt = 23.5
reference_solstice = datetime(2016, 6, 21, 22, 22)
days_per_year = 365.2425
seconds_per_day = 86400.0
days_since_reference = (dt - reference_solstice).total_seconds()/seconds_per_day
latitude = axial_tilt*numpy.cos(2*numpy.pi*days_since_reference/days_per_year)
seconds_since_midnight = (dt - datetime(dt.year, dt.month, dt.day)).seconds
longitude = -(seconds_since_midnight/seconds_per_day - 0.5)*360
pole_longitude = longitude
if latitude > 0:
pole_latitude = -90 + latitude
central_rotated_longitude = 180
else:
pole_latitude = 90 + latitude
central_rotated_longitude = 0
rotated_pole = cartopy.crs.RotatedPole(pole_latitude=pole_latitude, pole_longitude=pole_longitude, central_rotated_longitude=central_rotated_longitude)
x = numpy.empty(360)
y = numpy.empty(360)
x[:180] = -90
y[:180] = numpy.arange(-90, 90.)
x[180:] = 90
y[180:] = numpy.arange(90, -90., -1)
ax.fill(x, y, transform=rotated_pole, color="black", alpha=0.5)
# Plot points on the map. # Plot points on the map.
if(self.points): if(self.points):
logging.debug("Plotting QTHs on the map...")
for p in self.points: for p in self.points:
x, y = m(p.longitude, p.latitude) ax.plot(p.longitude, p.latitude, p.style, transform=cartopy.crs.PlateCarree())
m.plot(x, y, p.style) ax.text(p.longitude+0.02*p.longitude, p.latitude+0.02*p.latitude, p.name, color="white", size="small", weight="bold")
sub.text(x+0.01*x, y+0.01*y, p.name, color="white", size="small", weight="bold")
return True return True
else: else:

Wyświetl plik

@ -1,6 +1,6 @@
numpy numpy
matplotlib>=1.3.0 matplotlib>=1.3.0
basemap cartopy>=0.16.0
cairocffi cairocffi
sphinx sphinx
geocoder geocoder

Wyświetl plik

@ -1,6 +1,6 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# Copyright (C) 2013-2017 Christian Thomas Jacobs. # Copyright (C) 2013-2018 Christian Thomas Jacobs.
# This file is part of PyQSO. # This file is part of PyQSO.
@ -20,7 +20,7 @@
from setuptools import setup from setuptools import setup
setup(name="PyQSO", setup(name="PyQSO",
version="1.0.0", version="1.1.0-dev",
description="A contact logging tool for amateur radio operators.", description="A contact logging tool for amateur radio operators.",
author="Christian Thomas Jacobs", author="Christian Thomas Jacobs",
author_email="christian@christianjacobs.uk", author_email="christian@christianjacobs.uk",