[pycoast] 01/07: New upstream version 0.6.1+dfsg
Antonio Valentino
a_valentino-guest at moszumanska.debian.org
Sun Jun 4 15:52:14 UTC 2017
This is an automated email from the git hooks/post-receive script.
a_valentino-guest pushed a commit to branch master
in repository pycoast.
commit b2dbc911384b688126be6aa4ecda33eaed226447
Author: Antonio Valentino <antonio.valentino at tiscali.it>
Date: Sun Jun 4 17:26:09 2017 +0200
New upstream version 0.6.1+dfsg
---
.bumpversion.cfg | 7 +
.gitchangelog.rc | 192 ++++++++++++++++++++
.travis.yml | 1 -
changelog.rst | 120 ++++--------
pycoast/cw_agg.py | 149 ++-------------
pycoast/cw_base.py | 85 ++++++---
pycoast/tests/dateline_boundary_cross.png | Bin 28162 -> 24826 bytes
pycoast/tests/dateline_cross.png | Bin 28876 -> 25280 bytes
pycoast/tests/grid_europe.png | Bin 32916 -> 28007 bytes
pycoast/tests/grid_nh.png | Bin 36520 -> 33310 bytes
pycoast/tests/test_pycoast.py | 293 ++++++++++++++++++++----------
pycoast/version.py | 24 +--
setup.cfg | 7 +-
setup.py | 39 ++--
14 files changed, 535 insertions(+), 382 deletions(-)
diff --git a/.bumpversion.cfg b/.bumpversion.cfg
new file mode 100644
index 0000000..2a43fee
--- /dev/null
+++ b/.bumpversion.cfg
@@ -0,0 +1,7 @@
+[bumpversion]
+current_version = 0.6.1
+commit = True
+tag = True
+
+[bumpversion:file:pycoast/version.py]
+
diff --git a/.gitchangelog.rc b/.gitchangelog.rc
new file mode 100644
index 0000000..80c1ea7
--- /dev/null
+++ b/.gitchangelog.rc
@@ -0,0 +1,192 @@
+##
+## Format
+##
+## ACTION: [AUDIENCE:] COMMIT_MSG [!TAG ...]
+##
+## Description
+##
+## ACTION is one of 'chg', 'fix', 'new'
+##
+## Is WHAT the change is about.
+##
+## 'chg' is for refactor, small improvement, cosmetic changes...
+## 'fix' is for bug fixes
+## 'new' is for new features, big improvement
+##
+## AUDIENCE is optional and one of 'dev', 'usr', 'pkg', 'test', 'doc'
+##
+## Is WHO is concerned by the change.
+##
+## 'dev' is for developpers (API changes, refactors...)
+## 'usr' is for final users (UI changes)
+## 'pkg' is for packagers (packaging changes)
+## 'test' is for testers (test only related changes)
+## 'doc' is for doc guys (doc only changes)
+##
+## COMMIT_MSG is ... well ... the commit message itself.
+##
+## TAGs are additionnal adjective as 'refactor' 'minor' 'cosmetic'
+##
+## They are preceded with a '!' or a '@' (prefer the former, as the
+## latter is wrongly interpreted in github.) Commonly used tags are:
+##
+## 'refactor' is obviously for refactoring code only
+## 'minor' is for a very meaningless change (a typo, adding a comment)
+## 'cosmetic' is for cosmetic driven change (re-indentation, 80-col...)
+## 'wip' is for partial functionality but complete subfunctionality.
+##
+## Example:
+##
+## new: usr: support of bazaar implemented
+## chg: re-indentend some lines !cosmetic
+## new: dev: updated code to be compatible with last version of killer lib.
+## fix: pkg: updated year of licence coverage.
+## new: test: added a bunch of test around user usability of feature X.
+## fix: typo in spelling my name in comment. !minor
+##
+## Please note that multi-line commit message are supported, and only the
+## first line will be considered as the "summary" of the commit message. So
+## tags, and other rules only applies to the summary. The body of the commit
+## message will be displayed in the changelog without reformatting.
+
+
+##
+## ``ignore_regexps`` is a line of regexps
+##
+## Any commit having its full commit message matching any regexp listed here
+## will be ignored and won't be reported in the changelog.
+##
+ignore_regexps = [
+ r'@minor', r'!minor',
+ r'@cosmetic', r'!cosmetic',
+ r'@refactor', r'!refactor',
+ r'@wip', r'!wip',
+ r'^Merge commit .* into HEAD',
+ r'^([cC]hg|[fF]ix|[nN]ew)\s*:\s*[p|P]kg:',
+ r'^([cC]hg|[fF]ix|[nN]ew)\s*:\s*[d|D]ev:',
+ r'^(.{3,3}\s*:)?\s*[fF]irst commit.?\s*$',
+ ]
+
+
+## ``section_regexps`` is a list of 2-tuples associating a string label and a
+## list of regexp
+##
+## Commit messages will be classified in sections thanks to this. Section
+## titles are the label, and a commit is classified under this section if any
+## of the regexps associated is matching.
+##
+section_regexps = [
+ ('New', [
+ r'^[nN]ew\s*:\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$',
+ ]),
+ ('Changes', [
+ r'^[cC]hg\s*:\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$',
+ ]),
+ ('Fix', [
+ r'^([Bb]ug)?[fF]ix\s*:\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$',
+ ]),
+
+ ('Other', None ## Match all lines
+ ),
+
+]
+
+
+## ``body_process`` is a callable
+##
+## This callable will be given the original body and result will
+## be used in the changelog.
+##
+## Available constructs are:
+##
+## - any python callable that take one txt argument and return txt argument.
+##
+## - ReSub(pattern, replacement): will apply regexp substitution.
+##
+## - Indent(chars=" "): will indent the text with the prefix
+## Please remember that template engines gets also to modify the text and
+## will usually indent themselves the text if needed.
+##git log --pretty=format:"- %s%n%b" --since="$(git show -s --format=%ad `git rev-list --tags --max-count=1`)"
+## - Wrap(regexp=r"\n\n"): re-wrap text in separate paragraph to fill 80-Columns
+##
+## - noop: do nothing
+##
+## - ucfirst: ensure the first letter is uppercase.
+## (usually used in the ``subject_process`` pipeline)
+##
+## - final_dot: ensure text finishes with a dot
+## (usually used in the ``subject_process`` pipeline)
+##
+## - strip: remove any spaces before or after the content of the string
+##
+## Additionally, you can `pipe` the provided filters, for instance:
+#body_process = Wrap(regexp=r'\n(?=\w+\s*:)') | Indent(chars=" ")
+#body_process = Wrap(regexp=r'\n(?=\w+\s*:)')
+#body_process = noop
+body_process = ReSub(r'(?m)\s*^Signed-off-by: .*$\s*', '')
+
+
+## ``subject_process`` is a callable
+##
+## This callable will be given the original subject and result will
+## be used in the changelog.
+##
+## Available constructs are those listed in ``body_process`` doc.
+subject_process = (strip |
+ ReSub(r'^([cC]hg|[fF]ix|[nN]ew)\s*:\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n@]*)(@[a-z]+\s+)*$', r'\4') |
+ ucfirst | final_dot)
+
+
+## ``tag_filter_regexp`` is a regexp
+##
+## Tags that will be used for the changelog must match this regexp.
+##
+tag_filter_regexp = r'^v[0-9]+\.[0-9]+(\.[0-9]+)?$'
+
+
+## ``unreleased_version_label`` is a string
+##
+## This label will be used as the changelog Title of the last set of changes
+## between last valid tag and HEAD if any.
+unreleased_version_label = "%%version%% (unreleased)"
+
+
+## ``output_engine`` is a callable
+##
+## This will change the output format of the generated changelog file
+##
+## Available choices are:
+##
+## - rest_py
+##
+## Legacy pure python engine, outputs ReSTructured text.
+## This is the default.
+##
+## - mustache(<template_name>)
+##
+## Template name could be any of the available templates in
+## ``templates/mustache/*.tpl``.
+## Requires python package ``pystache``.
+## Examples:
+## - mustache("markdown")
+## - mustache("restructuredtext")
+##
+## - makotemplate(<template_name>)
+##
+## Template name could be any of the available templates in
+## ``templates/mako/*.tpl``.
+## Requires python package ``mako``.
+## Examples:
+## - makotemplate("restructuredtext")
+##
+output_engine = rest_py
+#output_engine = mustache("restructuredtext")
+#output_engine = mustache("markdown")
+#output_engine = makotemplate("restructuredtext")
+
+
+## ``include_merges`` is a boolean
+##
+## This option tells git-log whether to include merge commits in the log.
+## The default is to include them.
+include_merges = False
diff --git a/.travis.yml b/.travis.yml
index 7aab1eb..3d458ce 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,6 +1,5 @@
language: python
python:
-- '2.6'
- '2.7'
sudo: false
install:
diff --git a/changelog.rst b/changelog.rst
index 584d68e..1324b5d 100644
--- a/changelog.rst
+++ b/changelog.rst
@@ -1,43 +1,70 @@
Changelog
=========
-v0.5.4 (2016-02-21)
+
+v0.6.1 (2017-05-18)
-------------------
+- Update changelog. [Panu Lahtinen]
+- Bump version: 0.6.0 → 0.6.1. [Panu Lahtinen]
+- Add missing module name from Proj() call. [Panu Lahtinen]
+- Create projection before using it. [Panu Lahtinen]
+- Update changelog. [Panu Lahtinen]
+- Bump version: 0.5.5 → 0.6.0. [Panu Lahtinen]
+- Merge branch 'master' into pre-master. [Panu Lahtinen]
+- Add bumpversion. [Panu Lahtinen]
+- Add bumpversion, gitchangelog and bring versio up-to-date. [Panu
+ Lahtinen]
+- Update changelog. [Panu Lahtinen]
+- Merge branch 'master' into pre-master. [Panu Lahtinen]
+- Merge pull request #5 from avalentino/noagg. [Martin Raspaud]
+
+ Skip test on ContourWriterAGG if drawadd is not available
+- Skip test on ContourWriterAGG if drawadd is not available. [Antonio
+ Valentino]
+- Merge pull request #8 from pytroll/feature_extent_degrees. [Panu
+ Lahtinen]
+
+ Feature extent degrees
+- Drop Python 2.6 support. [Panu Lahtinen]
+- Remove texts from the images. [Panu Lahtinen]
+- Do more PEP8. [Panu Lahtinen]
+- Make geocentric extents the default. [Panu Lahtinen]
+- Fix line lengths (PEP8) [Panu Lahtinen]
+- Use functions from cw_base instead local copies. [Panu Lahtinen]
+- Make it possible to add coastlines to area defs with extents in
+ degrees. [Panu Lahtinen]
+- Minor PEP8. [Panu Lahtinen]
+- Pep8 pretify. [Adam.Dybbroe]
+- Pep8. [Adam.Dybbroe]
+- Update fonts in two test images. [Martin Raspaud]
-- Update changelog. [Martin Raspaud]
+v0.5.4 (2016-02-21)
+-------------------
+- Update changelog. [Martin Raspaud]
- Bump version: 0.5.3 → 0.5.4. [Martin Raspaud]
-
- Merge branch 'pre-master' [Martin Raspaud]
-
- Merge branch 'pre-master' of github.com:pytroll/pycoast into pre-
master. [Martin Raspaud]
-
- Add missing import of ConfigParser. [Panu Lahtinen]
-
- Remove skipping shapefiles crossing dateline, fixes global overlays.
[Panu Lahtinen]
-
- Update test reference images with ones made in Ubuntu so automatic
testing might work in Travis. [Panu Lahtinen]
+
v0.5.3 (2016-02-21)
-------------------
Fix
~~~
-
- Bugfix: The section is called "coasts", plural... [Martin Raspaud]
-
- Bugfix: the refactoring used only coastal style. [Martin Raspaud]
Other
~~~~~
-
- Update changelog. [Martin Raspaud]
-
- Bump version: 0.5.2 → 0.5.3. [Martin Raspaud]
-
- Merge branch 'master' into pre-master. [Martin Raspaud]
Conflicts:
@@ -45,103 +72,73 @@ Other
setup.py
- Add a gitignore file. [Martin Raspaud]
-
- Merge pull request #2 from mitkin/master. [Martin Raspaud]
Update setup.py
-
- Update setup.py. [Mikhail Itkin]
-
- Fix pyproj missing dependency. [Martin Raspaud]
-
- Move the test directory to pycoast.tests (for consistency) [Martin
Raspaud]
-
- Fix .travis.yml to install aggdraw first. [Martin Raspaud]
-
- Merge branch 'restructure' into pre-master. [Martin Raspaud]
-
- Split different readers out of __init__.py, adjust __init__.py so that
everything still works in the same way as previously. [Panu Lahtinen]
-
- More generic ignores. [Panu Lahtinen]
-
- Add a test suite and .travis file for ci. [Martin Raspaud]
-
- Update the reference images to make the test pass with pillow/aggdraw.
[Martin Raspaud]
-
- Add numpy to the list of dependencies. [Martin Raspaud]
-
- Added documentation about configuration files for pycoast. [Martin
Raspaud]
-
- Add setup.cfg for easy rpm generation. [Martin Raspaud]
-
- Some refactoring and pep8. [Martin Raspaud]
-
- _add_shapefile_shape bug fixed. [s.cerino]
-
- Merge branch 'master' into pre-master. [Martin Raspaud]
-
- Add configuration file reading feature. [Martin Raspaud]
-
- Merge branch 'master' of https://code.google.com/p/pycoast. [Martin
Raspaud]
-
- Fixed (sometimes fatal) ImageDraw import. [Hrobjartur Thorsteinsson]
ImageDraw and other PIL modules should be imported
directly from prevailing PIL package.
-
- Merge branch 'master' of https://code.google.com/p/pycoast. [Martin
Raspaud]
-
- Merge branch 'master' of https://code.google.com/p/pycoast. [Martin
Raspaud]
-
- Merge branch 'master' of https://code.google.com/p/pycoast. [Martin
Raspaud]
Conflicts:
pycoast/__init__.py
-
- Removing the rounding of the pixel indices. (Works with AGG and
without). [Martin Raspaud]
-
- Docbuilds. [Hrobjartur Thorsteinsson]
docbuilds
-
- Added documentation for polygons and shapefile methods. [Hrobjartur
Thorsteinsson]
Added documentation for polygons and shapefile methods.
-
- Add_polygon and add_shapefile_shape(s) integration testing.
[Hrobjartur Thorsteinsson]
add_polygon and add_shapefile_shape(s) integration testing.
Also included preliminary test data.
-
- Work in progress setting up shape and cities support. [Hrobjartur
Thorsteinsson]
Work in progress setting up shape and cities support
-
- Removed print line from add_shape routine. [Hrobjartur Thorsteinsson]
removed print line from add_shape routine
-
- Make pillow a dependency if PIL is not already there. [Martin Raspaud]
-
- Fixed fata ImageDraw import. [Hrobjartur Thorsteinsson]
Fixed importing conflict, affecting some users
@@ -150,16 +147,12 @@ Other
all PIL imports should be from same package.
made "from PIL import ImageDraw"
-
- Adding appertizer image at the front. [Adam Dybbroe]
-
- Rearranging documentation, and minor editorial stuff. [Adam Dybbroe]
-
- Bug fix: add_line / add_polygon. [Hrobjartur Thorsteinsson]
Minor bug fix: add_line / add_polygon exception.
-
- Added custom shapefile and shape draw routines. [Hrobjartur
Thorsteinsson]
@@ -170,78 +163,43 @@ Other
add_line(...)
add_polygon(...)
-
- Built docs. [Esben S. Nielsen]
-
- Hrobs changes and FFT metric for unit test. [Esben S. Nielsen]
-
- Flexible grid labeling and placement implemented. [Esben S. Nielsen]
-
- Lon markings now account for dateline too. [Esben S. Nielsen]
-
- Updated doc image. [Esben S. Nielsen]
-
- Updated docs. [Esben S. Nielsen]
-
- Test updated. [Esben S. Nielsen]
-
- Implemented correct dateline handling and updated tests. [Esben S.
Nielsen]
-
- Added all of docs/build/html. [Esben S. Nielsen]
-
- Modified comment. [Esben S. Nielsen]
-
- Added graticule computation from Hrob. [Esben S. Nielsen]
-
- Corrected bug in add_coastlines_to_file. [Esben S. Nielsen]
-
- Bugfixing to improve accuracy. [Esben S. Nielsen]
-
- Added testing. [Esben S. Nielsen]
-
- Corrected docs. [Esben S. Nielsen]
-
- Corrected git doc mess. [Esben S. Nielsen]
-
- Updated docs. [Esben S. Nielsen]
-
- Added possiblility to use AGG. Changed API slightly. [Esben S.
Nielsen]
-
- Docs messed up by git. Trying to clean. [Esben S. Nielsen]
-
- Added missing build doc files. [Esben S. Nielsen]
-
- Corrected invalid reprojection issue for projections like geos. [Esben
S. Nielsen]
-
- Rebuild docs. [Esben S. Nielsen]
-
- Bumped up version. [Esben S. Nielsen]
-
- Corrected south pole filtering bug. [Esben S. Nielsen]
-
- Changed link to SOEST. [Esben S. Nielsen]
-
- Documented project. [Esben S. Nielsen]
-
- Added license and docs. [Esben S. Nielsen]
-
- Now handles poles. [Esben S. Nielsen]
-
- Added docstrings. [Esben S. Nielsen]
-
- Added test. [Esben S. Nielsen]
-
- Created package. [Esben S. Nielsen]
-
- Restructured pixel index calculation. [Esben S. Nielsen]
-
- Added borders and rivers. [Esben S. Nielsen]
-
- First version. [Esben S. Nielsen]
-
- First version. [Esben S. Nielsen]
diff --git a/pycoast/cw_agg.py b/pycoast/cw_agg.py
index a68834b..6a32c7c 100644
--- a/pycoast/cw_agg.py
+++ b/pycoast/cw_agg.py
@@ -12,7 +12,7 @@
# This program 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.
+# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -29,6 +29,8 @@ import logging
import aggdraw
from cw_base import ContourWriterBase
+from cw_base import _get_lon_lat_bounding_box
+from cw_base import _get_pixel_index
logger = logging.getLogger(__name__)
@@ -86,7 +88,8 @@ class ContourWriterAGG(ContourWriterBase):
brush = aggdraw.Brush(kwargs['fill'], fill_opacity)
draw.ellipse(coordinates, brush, pen)
- def _draw_text_box(self, draw, text_position, text, font, outline, box_outline, box_opacity):
+ def _draw_text_box(self, draw, text_position, text, font, outline,
+ box_outline, box_opacity):
"""Add text box in xy
"""
@@ -119,7 +122,8 @@ class ContourWriterAGG(ContourWriterBase):
draw.flush()
- def add_shapefile_shapes(self, image, area_def, filename, feature_type=None,
+ def add_shapefile_shapes(self, image, area_def, filename,
+ feature_type=None,
fill=None, fill_opacity=255, outline='white',
width=1, outline_opacity=255, x_offset=0,
y_offset=0):
@@ -136,7 +140,7 @@ class ContourWriterAGG(ContourWriterBase):
| Area extent as a list (LL_x, LL_y, UR_x, UR_y)
filename : str
Path to ESRI shape file
- feature_type : 'polygon' or 'line',
+ feature_type : 'polygon' or 'line',
only to override the shape type defined in shapefile, optional
fill : str or (R, G, B), optional
Polygon fill color
@@ -154,7 +158,8 @@ class ContourWriterAGG(ContourWriterBase):
Pixel offset in y direction
"""
self._add_shapefile_shapes(image=image, area_def=area_def,
- filename=filename, feature_type=feature_type,
+ filename=filename,
+ feature_type=feature_type,
x_offset=x_offset, y_offset=y_offset,
fill=fill, fill_opacity=fill_opacity,
outline=outline, width=width,
@@ -166,7 +171,7 @@ class ContourWriterAGG(ContourWriterBase):
width=1, outline_opacity=255, x_offset=0,
y_offset=0):
"""Add a single shape file shape from an ESRI shapefile.
- Note: To add all shapes in file use the 'add_shape_file_shapes' routine.
+ Note: To add all shapes in file use the 'add_shape_file_shapes' routine
Note: Currently only supports lon-lat formatted coordinates.
:Parameters:
@@ -181,7 +186,7 @@ class ContourWriterAGG(ContourWriterBase):
Path to ESRI shape file
shape_id : int
integer id of shape in shape file {0; ... }
- feature_type : 'polygon' or 'line',
+ feature_type : 'polygon' or 'line',
only to override the shape type defined in shapefile, optional
fill : str or (R, G, B), optional
Polygon fill color
@@ -318,7 +323,8 @@ class ContourWriterAGG(ContourWriterBase):
minor_outline=minor_outline, minor_width=minor_width,
minor_outline_opacity=minor_outline_opacity,
minor_is_tick=minor_is_tick,
- lon_placement=lon_placement, lat_placement=lat_placement)
+ lon_placement=lon_placement,
+ lat_placement=lat_placement)
def add_grid_to_file(self, filename, area_def, (Dlon, Dlat), (dlon, dlat),
font=None, write_text=True,
@@ -592,130 +598,3 @@ class ContourWriterAGG(ContourWriterBase):
def _get_font(self, outline, font_file, font_size):
"""Return a font."""
return aggdraw.Font(outline, font_file, size=font_size)
-
-
-def _get_lon_lat_bounding_box(area_extent, x_size, y_size, prj):
- """Get extreme lon and lat values
- """
-
- x_ll, y_ll, x_ur, y_ur = area_extent
- x_range = np.linspace(x_ll, x_ur, num=x_size)
- y_range = np.linspace(y_ll, y_ur, num=y_size)
-
- lons_s1, lats_s1 = prj(np.ones(y_range.size) * x_ll, y_range, inverse=True)
- lons_s2, lats_s2 = prj(x_range, np.ones(x_range.size) * y_ur, inverse=True)
- lons_s3, lats_s3 = prj(np.ones(y_range.size) * x_ur, y_range, inverse=True)
- lons_s4, lats_s4 = prj(x_range, np.ones(x_range.size) * y_ll, inverse=True)
-
- angle_sum = 0
- prev = None
- for lon in np.concatenate((lons_s1, lons_s2, lons_s3[::-1], lons_s4[::-1])):
- if prev is not None:
- delta = lon - prev
- if abs(delta) > 180:
- delta = (abs(delta) - 360) * np.sign(delta)
- angle_sum += delta
- prev = lon
-
- if round(angle_sum) == -360:
- # Covers NP
- lat_min = min(lats_s1.min(), lats_s2.min(),
- lats_s3.min(), lats_s4.min())
- lat_max = 90
- lon_min = -180
- lon_max = 180
- elif round(angle_sum) == 360:
- # Covers SP
- lat_min = -90
- lat_max = max(lats_s1.max(), lats_s2.max(),
- lats_s3.max(), lats_s4.max())
- lon_min = -180
- lon_max = 180
- elif round(angle_sum) == 0:
- # Covers no poles
- if np.sign(lons_s1[0]) * np.sign(lons_s1[-1]) == -1:
- # End points of left side on different side of dateline
- lon_min = lons_s1[lons_s1 > 0].min()
- else:
- lon_min = lons_s1.min()
-
- if np.sign(lons_s3[0]) * np.sign(lons_s3[-1]) == -1:
- # End points of right side on different side of dateline
- lon_max = lons_s3[lons_s3 < 0].max()
- else:
- lon_max = lons_s3.max()
-
- lat_min = lats_s4.min()
- lat_max = lats_s2.max()
- else:
- # Pretty strange
- lat_min = -90
- lat_max = 90
- lon_min = -180
- lon_max = 180
-
- if not (-180 <= lon_min <= 180):
- lon_min = -180
- if not (-180 <= lon_max <= 180):
- lon_max = 180
- if not (-90 <= lat_min <= 90):
- lat_min = -90
- if not (-90 <= lat_max <= 90):
- lat_max = 90
-
- return lon_min, lon_max, lat_min, lat_max
-
-
-def _get_pixel_index(shape, area_extent, x_size, y_size, prj,
- x_offset=0, y_offset=0):
- """Map coordinates of shape to image coordinates
- """
-
- # Get shape data as array and reproject
- shape_data = np.array(shape.points)
- lons = shape_data[:, 0]
- lats = shape_data[:, 1]
-
- x_ll, y_ll, x_ur, y_ur = area_extent
-
- x, y = prj(lons, lats)
-
- # Handle out of bounds
- i = 0
- segments = []
- if 1e30 in x or 1e30 in y:
- # Split polygon in line segments within projection
- is_reduced = True
- if x[0] == 1e30 or y[0] == 1e30:
- in_segment = False
- else:
- in_segment = True
-
- for j in range(x.size):
- if (x[j] == 1e30 or y[j] == 1e30):
- if in_segment:
- segments.append((x[i:j], y[i:j]))
- in_segment = False
- elif not in_segment:
- in_segment = True
- i = j
- if in_segment:
- segments.append((x[i:], y[i:]))
-
- else:
- is_reduced = False
- segments = [(x, y)]
-
- # Convert to pixel index coordinates
- l_x = (x_ur - x_ll) / x_size
- l_y = (y_ur - y_ll) / y_size
-
- index_arrays = []
- for x, y in segments:
- n_x = ((-x_ll + x) / l_x) + 0.5 + x_offset
- n_y = ((y_ur - y) / l_y) + 0.5 + y_offset
-
- index_array = np.vstack((n_x, n_y)).T
- index_arrays.append(index_array)
-
- return index_arrays, is_reduced
diff --git a/pycoast/cw_base.py b/pycoast/cw_base.py
index eaa0a0b..0e779e6 100644
--- a/pycoast/cw_base.py
+++ b/pycoast/cw_base.py
@@ -12,7 +12,7 @@
# This program 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.
+# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -33,6 +33,7 @@ from .errors import *
logger = logging.getLogger(__name__)
+
class ContourWriterBase(object):
"""Base class for contourwriters. Do not instantiate.
@@ -173,7 +174,7 @@ class ContourWriterBase(object):
minor_line_kwargs['width'] = kwargs['minor_width']
# set text fonts
- if font == None:
+ if font is None:
font = ImageFont.load_default()
# text margins (at sides of image frame)
y_text_margin = 4
@@ -247,7 +248,7 @@ class ContourWriterBase(object):
# create dummpy shape object
tmpshape = shapefile.Writer("")
- ##### MINOR LINES ######
+ # MINOR LINES ######
if not kwargs['minor_is_tick']:
# minor lat lines
for lat in min_lats:
@@ -287,7 +288,7 @@ class ContourWriterBase(object):
index_array.flatten().tolist(),
**minor_line_kwargs)
- ##### MAJOR LINES AND MINOR TICKS ######
+ # MAJOR LINES AND MINOR TICKS ######
# major lon lines and tick marks:
for lon in maj_lons:
# Draw 'minor' tick lines dlat separation along the lon
@@ -340,7 +341,8 @@ class ContourWriterBase(object):
else:
txt = "%.2dW" % (-lon)
xys = self._find_line_intercepts(index_array, image.size,
- (x_text_margin, y_text_margin))
+ (x_text_margin,
+ y_text_margin))
self._draw_grid_labels(draw, xys, 'lon_placement',
txt, font, **kwargs)
@@ -393,7 +395,8 @@ class ContourWriterBase(object):
else:
txt = "%.2dS" % (-lat)
xys = self._find_line_intercepts(index_array, image.size,
- (x_text_margin, y_text_margin))
+ (x_text_margin,
+ y_text_margin))
self._draw_grid_labels(draw, xys, 'lat_placement',
txt, font, **kwargs)
@@ -470,8 +473,8 @@ class ContourWriterBase(object):
elif shape.shapeType == 5:
feature_type = "polygon"
else:
- raise ShapeFileError("Unsupported shape type: "
- + str(shape.shapeType))
+ raise ShapeFileError("Unsupported shape type: " +
+ str(shape.shapeType))
self._add_shapes(image, area_def, feature_type, [shape], **kwargs)
@@ -526,10 +529,10 @@ class ContourWriterBase(object):
s_lon_ll, s_lat_ll, s_lon_ur, s_lat_ur = shape.bbox
if lon_min > lon_max:
pass
- # # Dateline crossing
+ # Dateline crossing
# if ((s_lon_ur < lon_min and s_lon_ll > lon_max) or
# lat_max < s_lat_ll or lat_min > s_lat_ur):
- # # Polygon is irrelevant
+ # Polygon is irrelevant
# continue
elif (lon_max < s_lon_ll or lon_min > s_lon_ur or
lat_max < s_lat_ll or lat_min > s_lat_ur):
@@ -608,10 +611,10 @@ class ContourWriterBase(object):
s_lon_ll, s_lat_ll, s_lon_ur, s_lat_ur = shape.bbox
if lon_min > lon_max:
pass
- # # Dateline crossing
+ # Dateline crossing
# if ((s_lon_ur < lon_min and s_lon_ll > lon_max) or
# lat_max < s_lat_ll or lat_min > s_lat_ur):
- # # Polygon is irrelevant
+ # Polygon is irrelevant
# continue
elif (lon_max < s_lon_ll or lon_min > s_lon_ur or
lat_max < s_lat_ll or lat_min > s_lat_ur):
@@ -718,8 +721,8 @@ class ContourWriterBase(object):
if config.has_section('cache'):
config_file_name, config_file_extention = \
os.path.splitext(config_file)
- cache_file = (config.get('cache', 'file') + '_'
- + area_def.area_id + '.png')
+ cache_file = (config.get('cache', 'file') + '_' +
+ area_def.area_id + '.png')
try:
configTime = os.path.getmtime(config_file)
@@ -739,13 +742,20 @@ class ContourWriterBase(object):
y_size = area_def.y_size
foreground = Image.new('RGBA', (x_size, y_size), (0, 0, 0, 0))
- # Lines (coasts, rivers, borders) management
- x_resolution = ((area_def.area_extent[2] -
- area_def.area_extent[0]) /
- x_size)
- y_resolution = ((area_def.area_extent[3] -
- area_def.area_extent[1]) /
- y_size)
+ # Lines (coasts, rivers, borders) management
+ prj = pyproj.Proj(area_def.proj4_string)
+ if prj.is_latlong():
+ x_ll, y_ll = prj(area_def.area_extent[0], area_def.area_extent[1])
+ x_ur, y_ur = prj(area_def.area_extent[2], area_def.area_extent[3])
+ x_resolution = (x_ur - x_ll) / x_size
+ y_resolution = (y_ur - y_ll) / y_size
+ else:
+ x_resolution = ((area_def.area_extent[2] -
+ area_def.area_extent[0]) /
+ x_size)
+ y_resolution = ((area_def.area_extent[3] -
+ area_def.area_extent[1]) /
+ y_size)
res = min(x_resolution, y_resolution)
if res > 25000:
@@ -786,7 +796,7 @@ class ContourWriterBase(object):
self.add_rivers,
self.add_borders]):
- if overlays.has_key(section):
+ if section in overlays:
params = DEFAULT.copy()
params.update(overlays[section])
@@ -810,7 +820,7 @@ class ContourWriterBase(object):
logger.info("%s added", section.capitalize())
# Cities management
- if overlays.has_key('cities'):
+ if 'cities' in overlays:
DEFAULT_FONT_SIZE = 12
DEFAULT_OUTLINE = "yellow"
@@ -907,6 +917,7 @@ class ContourWriterBase(object):
self._finalize(draw)
+
def _get_lon_lat_bounding_box(area_extent, x_size, y_size, prj):
"""Get extreme lon and lat values
"""
@@ -915,14 +926,25 @@ def _get_lon_lat_bounding_box(area_extent, x_size, y_size, prj):
x_range = np.linspace(x_ll, x_ur, num=x_size)
y_range = np.linspace(y_ll, y_ur, num=y_size)
- lons_s1, lats_s1 = prj(np.ones(y_range.size) * x_ll, y_range, inverse=True)
- lons_s2, lats_s2 = prj(x_range, np.ones(x_range.size) * y_ur, inverse=True)
- lons_s3, lats_s3 = prj(np.ones(y_range.size) * x_ur, y_range, inverse=True)
- lons_s4, lats_s4 = prj(x_range, np.ones(x_range.size) * y_ll, inverse=True)
+ if prj.is_latlong():
+ lons_s1, lats_s1 = x_ll * np.ones(y_range.size), y_range
+ lons_s2, lats_s2 = x_range, y_ur * np.ones(x_range.size)
+ lons_s3, lats_s3 = x_ur * np.ones(y_range.size), y_range
+ lons_s4, lats_s4 = x_range, y_ll * np.ones(x_range.size)
+ else:
+ lons_s1, lats_s1 = prj(np.ones(y_range.size) * x_ll, y_range,
+ inverse=True)
+ lons_s2, lats_s2 = prj(x_range, np.ones(x_range.size) * y_ur,
+ inverse=True)
+ lons_s3, lats_s3 = prj(np.ones(y_range.size) * x_ur, y_range,
+ inverse=True)
+ lons_s4, lats_s4 = prj(x_range, np.ones(x_range.size) * y_ll,
+ inverse=True)
angle_sum = 0
prev = None
- for lon in np.concatenate((lons_s1, lons_s2, lons_s3[::-1], lons_s4[::-1])):
+ for lon in np.concatenate((lons_s1, lons_s2,
+ lons_s3[::-1], lons_s4[::-1])):
if prev is not None:
delta = lon - prev
if abs(delta) > 180:
@@ -989,7 +1011,11 @@ def _get_pixel_index(shape, area_extent, x_size, y_size, prj,
lons = shape_data[:, 0]
lats = shape_data[:, 1]
- x_ll, y_ll, x_ur, y_ur = area_extent
+ if prj.is_latlong():
+ x_ll, y_ll = prj(area_extent[0], area_extent[1])
+ x_ur, y_ur = prj(area_extent[2], area_extent[3])
+ else:
+ x_ll, y_ll, x_ur, y_ur = area_extent
x, y = prj(lons, lats)
@@ -1032,4 +1058,3 @@ def _get_pixel_index(shape, area_extent, x_size, y_size, prj,
index_arrays.append(index_array)
return index_arrays, is_reduced
-
diff --git a/pycoast/tests/dateline_boundary_cross.png b/pycoast/tests/dateline_boundary_cross.png
index 25ff7e5..712f5c2 100644
Binary files a/pycoast/tests/dateline_boundary_cross.png and b/pycoast/tests/dateline_boundary_cross.png differ
diff --git a/pycoast/tests/dateline_cross.png b/pycoast/tests/dateline_cross.png
index de14b35..bac3993 100644
Binary files a/pycoast/tests/dateline_cross.png and b/pycoast/tests/dateline_cross.png differ
diff --git a/pycoast/tests/grid_europe.png b/pycoast/tests/grid_europe.png
index d5b6e89..45b1ff7 100644
Binary files a/pycoast/tests/grid_europe.png and b/pycoast/tests/grid_europe.png differ
diff --git a/pycoast/tests/grid_nh.png b/pycoast/tests/grid_nh.png
index 14d64e9..6c99b93 100644
Binary files a/pycoast/tests/grid_nh.png and b/pycoast/tests/grid_nh.png differ
diff --git a/pycoast/tests/test_pycoast.py b/pycoast/tests/test_pycoast.py
index 8675a58..8d8fb8b 100644
--- a/pycoast/tests/test_pycoast.py
+++ b/pycoast/tests/test_pycoast.py
@@ -1,6 +1,6 @@
# pycoast, Writing of coastlines, borders and rivers to images in Python
-#
-# Copyright (C) 2011 Esben S. Nielsen
+#
+# Copyright (C) 2011, 2016 Esben S. Nielsen
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -21,7 +21,7 @@ import unittest
import numpy as np
from PIL import Image, ImageFont
-from pycoast import ContourWriter
+from pycoast import ContourWriter, ContourWriterAGG
def tmp(f):
@@ -71,6 +71,7 @@ grid_file = 'test_grid.png'
class TestPycoast(unittest.TestCase):
+
def setUp(self):
img = Image.new('RGB', (640, 480))
img.save(test_file)
@@ -82,13 +83,15 @@ class TestPycoast(unittest.TestCase):
class TestPIL(TestPycoast):
+
def test_europe(self):
euro_img = Image.open(os.path.join(os.path.dirname(__file__),
'contours_europe.png'))
euro_data = np.array(euro_img)
img = Image.new('RGB', (640, 480))
- proj4_string = '+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84'
+ proj4_string = \
+ '+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84'
area_extent = (-3363403.31, -2291879.85, 2630596.69, 2203620.1)
area_def = (proj4_string, area_extent)
cw = ContourWriter(gshhs_root_dir)
@@ -97,14 +100,16 @@ class TestPIL(TestPycoast):
cw.add_borders(img, area_def, outline=(255, 0, 0))
res = np.array(img)
- self.failUnless(fft_metric(euro_data, res), 'Writing of contours failed')
+ self.failUnless(fft_metric(euro_data, res),
+ 'Writing of contours failed')
def test_europe_file(self):
euro_img = Image.open(os.path.join(os.path.dirname(__file__),
'contours_europe.png'))
euro_data = np.array(euro_img)
- proj4_string = '+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84'
+ proj4_string = \
+ '+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84'
area_extent = (-3363403.31, -2291879.85, 2630596.69, 2203620.1)
area_def = (proj4_string, area_extent)
cw = ContourWriter(gshhs_root_dir)
@@ -114,7 +119,8 @@ class TestPIL(TestPycoast):
img = Image.open(test_file)
res = np.array(img)
- self.failUnless(fft_metric(euro_data, res), 'Writing of contours failed')
+ self.failUnless(
+ fft_metric(euro_data, res), 'Writing of contours failed')
def test_geos(self):
geos_img = Image.open(os.path.join(os.path.dirname(__file__),
@@ -122,62 +128,78 @@ class TestPIL(TestPycoast):
geos_data = np.array(geos_img)
img = Image.new('RGB', (425, 425))
- proj4_string = '+proj=geos +lon_0=0.0 +a=6378169.00 +b=6356583.80 +h=35785831.0'
- area_extent = (-5570248.4773392612, -5567248.074173444, 5567248.074173444, 5570248.4773392612)
+ proj4_string = \
+ '+proj=geos +lon_0=0.0 +a=6378169.00 +b=6356583.80 +h=35785831.0'
+ area_extent = (-5570248.4773392612, -5567248.074173444,
+ 5567248.074173444, 5570248.4773392612)
area_def = (proj4_string, area_extent)
cw = ContourWriter(gshhs_root_dir)
cw.add_coastlines(img, area_def, resolution='l')
res = np.array(img)
- self.failUnless(fft_metric(geos_data, res), 'Writing of geos contours failed')
+ self.failUnless(
+ fft_metric(geos_data, res), 'Writing of geos contours failed')
def test_grid(self):
grid_img = Image.open(os.path.join(os.path.dirname(__file__),
'grid_europe.png'))
grid_data = np.array(grid_img)
img = Image.new('RGB', (640, 480))
- proj4_string = '+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84'
+ proj4_string = \
+ '+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84'
area_extent = (-3363403.31, -2291879.85, 2630596.69, 2203620.1)
area_def = (proj4_string, area_extent)
cw = ContourWriter(gshhs_root_dir)
cw.add_coastlines(img, area_def, resolution='l', level=4)
- font = ImageFont.truetype(os.path.join(os.path.dirname(__file__), 'test_data', 'DejaVuSerif.ttf'), 16)
- cw.add_grid(img, area_def, (10.0, 10.0), (2.0, 2.0), font=font, fill='blue',
+ font = ImageFont.truetype(os.path.join(os.path.dirname(__file__),
+ 'test_data', 'DejaVuSerif.ttf'),
+ 16)
+ cw.add_grid(img, area_def, (10.0, 10.0), (2.0, 2.0),
+ font=font, fill='blue', write_text=False,
outline='blue', minor_outline='blue')
res = np.array(img)
self.failUnless(fft_metric(grid_data, res), 'Writing of grid failed')
def test_grid_geos(self):
- geos_img = Image.open(os.path.join(os.path.dirname(__file__), 'grid_geos.png'))
+ geos_img = Image.open(
+ os.path.join(os.path.dirname(__file__), 'grid_geos.png'))
geos_data = np.array(geos_img)
img = Image.new('RGB', (425, 425))
- proj4_string = '+proj=geos +lon_0=0.0 +a=6378169.00 +b=6356583.80 +h=35785831.0'
- area_extent = (-5570248.4773392612, -5567248.074173444, 5567248.074173444, 5570248.4773392612)
+ proj4_string = \
+ '+proj=geos +lon_0=0.0 +a=6378169.00 +b=6356583.80 +h=35785831.0'
+ area_extent = (-5570248.4773392612, -5567248.074173444,
+ 5567248.074173444, 5570248.4773392612)
area_def = (proj4_string, area_extent)
cw = ContourWriter(gshhs_root_dir)
cw.add_coastlines(img, area_def, resolution='l')
- cw.add_grid(img, area_def, (10.0, 10.0), (2.0, 2.0), fill='blue', outline='blue', minor_outline='blue',
+ cw.add_grid(img, area_def, (10.0, 10.0), (2.0, 2.0), fill='blue',
+ outline='blue', minor_outline='blue',
write_text=False)
res = np.array(img)
- self.failUnless(fft_metric(geos_data, res), 'Writing of geos contours failed')
+ self.failUnless(
+ fft_metric(geos_data, res), 'Writing of geos contours failed')
def test_grid_file(self):
grid_img = Image.open(os.path.join(os.path.dirname(__file__),
'grid_europe.png'))
grid_data = np.array(grid_img)
- proj4_string = '+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84'
+ proj4_string = \
+ '+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84'
area_extent = (-3363403.31, -2291879.85, 2630596.69, 2203620.1)
area_def = (proj4_string, area_extent)
cw = ContourWriter(gshhs_root_dir)
cw.add_coastlines_to_file(grid_file, area_def, resolution='l', level=4)
- font = ImageFont.truetype(os.path.join(os.path.dirname(__file__), 'test_data', 'DejaVuSerif.ttf'), 16)
- cw.add_grid_to_file(grid_file, area_def, (10.0, 10.0), (2.0, 2.0), font=font, fill='blue',
+ font = ImageFont.truetype(os.path.join(os.path.dirname(__file__),
+ 'test_data', 'DejaVuSerif.ttf'),
+ 16)
+ cw.add_grid_to_file(grid_file, area_def, (10.0, 10.0), (2.0, 2.0),
+ font=font, fill='blue', write_text=False,
outline='blue', minor_outline='blue')
img = Image.open(grid_file)
@@ -197,13 +219,17 @@ class TestPIL(TestPycoast):
cw = ContourWriter(gshhs_root_dir)
cw.add_coastlines(img, area_def, resolution='l', level=4)
- font = ImageFont.truetype(os.path.join(os.path.dirname(__file__), 'test_data', 'DejaVuSerif.ttf'), 16)
- cw.add_grid(img, area_def, (10.0, 10.0), (2.0, 2.0), font=font, fill='blue',
+ font = ImageFont.truetype(os.path.join(os.path.dirname(__file__),
+ 'test_data',
+ 'DejaVuSerif.ttf'), 16)
+ cw.add_grid(img, area_def, (10.0, 10.0), (2.0, 2.0),
+ font=font, fill='blue', write_text=False,
outline='blue', minor_outline='blue',
lon_placement='b', lat_placement='lr')
res = np.array(img)
- self.failUnless(fft_metric(dl_data, res), 'Writing of dateline crossing data failed')
+ self.failUnless(fft_metric(dl_data, res),
+ 'Writing of dateline crossing data failed')
def test_dateline_boundary_cross(self):
dl_img = Image.open(os.path.join(os.path.dirname(__file__),
@@ -211,20 +237,25 @@ class TestPIL(TestPycoast):
dl_data = np.array(dl_img)
img = Image.new('RGB', (640, 480))
- proj4_string = '+proj=stere +lon_0=140.00 +lat_0=60.00 +lat_ts=50.00 +ellps=WGS84'
+ proj4_string = \
+ '+proj=stere +lon_0=140.00 +lat_0=60.00 +lat_ts=50.00 +ellps=WGS84'
area_extent = (-3363403.31, -2291879.85, 2630596.69, 2203620.1)
area_def = (proj4_string, area_extent)
cw = ContourWriter(gshhs_root_dir)
cw.add_coastlines(img, area_def, resolution='l', level=4)
- font = ImageFont.truetype(os.path.join(os.path.dirname(__file__), 'test_data', 'DejaVuSerif.ttf'), 16)
- cw.add_grid(img, area_def, (10.0, 10.0), (2.0, 2.0), font=font, fill='blue',
- outline='blue', minor_outline='blue',
+ font = ImageFont.truetype(os.path.join(os.path.dirname(__file__),
+ 'test_data',
+ 'DejaVuSerif.ttf'), 16)
+ cw.add_grid(img, area_def, (10.0, 10.0), (2.0, 2.0),
+ font=font, fill='blue',
+ outline='blue', minor_outline='blue', write_text=False,
lon_placement='b', lat_placement='lr')
res = np.array(img)
- self.failUnless(fft_metric(dl_data, res), 'Writing of dateline boundary crossing data failed')
+ self.failUnless(fft_metric(dl_data, res),
+ 'Writing of dateline boundary crossing data failed')
def test_grid_nh(self):
grid_img = Image.open(os.path.join(os.path.dirname(__file__),
@@ -232,19 +263,24 @@ class TestPIL(TestPycoast):
grid_data = np.array(grid_img)
img = Image.new('RGB', (425, 425))
proj4_string = '+proj=laea +lat_0=90 +lon_0=0 +a=6371228.0 +units=m'
- area_extent = (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)
+ area_extent = (-5326849.0625, -5326849.0625,
+ 5326849.0625, 5326849.0625)
area_def = (proj4_string, area_extent)
cw = ContourWriter(gshhs_root_dir)
cw.add_coastlines(img, area_def, resolution='l', level=4)
- font = ImageFont.truetype(os.path.join(os.path.dirname(__file__), 'test_data', 'DejaVuSerif.ttf'), 10)
- cw.add_grid(img, area_def, (10.0, 10.0), (2.0, 2.0), font=font, fill='blue',
- outline='blue', minor_outline='blue',
+ font = ImageFont.truetype(os.path.join(os.path.dirname(__file__),
+ 'test_data', 'DejaVuSerif.ttf'),
+ 10)
+ cw.add_grid(img, area_def, (10.0, 10.0), (2.0, 2.0),
+ font=font, fill='blue',
+ outline='blue', minor_outline='blue', write_text=False,
lon_placement='tblr', lat_placement='')
res = np.array(img)
- self.failUnless(fft_metric(grid_data, res), 'Writing of nh grid failed')
+ self.failUnless(
+ fft_metric(grid_data, res), 'Writing of nh grid failed')
def test_add_polygon(self):
grid_img = Image.open(os.path.join(os.path.dirname(__file__),
@@ -252,29 +288,34 @@ class TestPIL(TestPycoast):
grid_data = np.array(grid_img)
img = Image.new('RGB', (425, 425))
proj4_string = '+proj=laea +lat_0=90 +lon_0=0 +a=6371228.0 +units=m'
- area_extent = (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)
+ area_extent = (-5326849.0625, -5326849.0625,
+ 5326849.0625, 5326849.0625)
area_def = (proj4_string, area_extent)
cw = ContourWriter(gshhs_root_dir)
polygons = {
- 'REYKJAVIK_ATC_A': ((-20.0, 73.0), (0.0, 73.0), (0.0, 61.0), (-30.0, 61.0), (-39.0, 63.5), (-20, 70)),
+ 'REYKJAVIK_ATC_A': ((-20.0, 73.0), (0.0, 73.0), (0.0, 61.0),
+ (-30.0, 61.0), (-39.0, 63.5), (-20, 70)),
'REYKJAVIK_ATC_B': (
- (-39, 63.5), (-55 + 4 / 6.0, 63.5), (-57 + 45 / 60.0, 65), (-76, 76), (-75, 78), (-60, 82), (0, 90),
- (30, 82), (0, 82), (0, 73), (-20, 73), (-20,
- 70)),
+ (-39, 63.5), (-55 + 4 / 6.0, 63.5), (-57 + 45 / 60.0, 65),
+ (-76, 76), (-75, 78), (-60, 82), (0, 90),
+ (30, 82), (0, 82), (0, 73), (-20, 73), (-20, 70)),
'REYKJAVIK_ATC': (
- (0.0, 73.0), (0.0, 61.0), (-30.0, 61.0), (-39, 63.5), (-55 + 4 / 6.0, 63.5), (-57 + 45 / 60.0, 65),
- (-76, 76), (-75, 78), (-60, 82), (0, 90), (30, 82), (0, 82)),
+ (0.0, 73.0), (0.0, 61.0), (-30.0, 61.0), (-39, 63.5),
+ (-55 + 4 / 6.0, 63.5), (-57 + 45 / 60.0, 65),
+ (-76, 76), (-75, 78), (-60, 82), (0, 90), (30, 82), (0, 82)),
'ICELAND_BOX': ((-25, 62.5), (-25, 67), (-13, 67), (-13, 62.5))
}
cw.add_polygon(img, area_def, polygons['REYKJAVIK_ATC'], outline='red')
- cw.add_polygon(img, area_def, polygons['ICELAND_BOX'], outline='green', fill='gray')
+ cw.add_polygon(img, area_def, polygons['ICELAND_BOX'], outline='green',
+ fill='gray')
cw.add_coastlines(img, area_def, resolution='l', level=4)
res = np.array(img)
- self.failUnless(fft_metric(grid_data, res), 'Writing of nh polygons failed')
+ self.failUnless(fft_metric(grid_data, res),
+ 'Writing of nh polygons failed')
def test_add_shapefile_shapes(self):
grid_img = Image.open(os.path.join(os.path.dirname(__file__),
@@ -290,7 +331,9 @@ class TestPIL(TestPycoast):
cw.add_coastlines(img, area_def, resolution='l', level=4)
cw.add_shapefile_shapes(img, area_def,
- os.path.join(os.path.dirname(__file__), 'test_data/shapes/Metareas.shp'),
+ os.path.join(
+ os.path.dirname(__file__),
+ 'test_data/shapes/Metareas.shp'),
outline='red')
cw.add_shapefile_shape(img, area_def,
os.path.join(os.path.dirname(__file__),
@@ -302,10 +345,13 @@ class TestPIL(TestPycoast):
outline='blue', fill='green')
res = np.array(img)
- self.failUnless(fft_metric(grid_data, res), 'Writing of Brazil shapefiles failed')
+ self.failUnless(
+ fft_metric(grid_data, res), 'Writing of Brazil shapefiles failed')
+ at unittest.skipIf(ContourWriterAGG is ContourWriter, 'aggdraw not available')
class TestPILAGG(TestPycoast):
+
def test_europe_agg(self):
from pycoast import ContourWriterAGG
euro_img = Image.open(os.path.join(os.path.dirname(__file__),
@@ -313,15 +359,19 @@ class TestPILAGG(TestPycoast):
euro_data = np.array(euro_img)
img = Image.new('RGB', (640, 480))
- proj4_string = '+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84'
+ proj4_string = \
+ '+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84'
area_extent = (-3363403.31, -2291879.85, 2630596.69, 2203620.1)
area_def = (proj4_string, area_extent)
cw = ContourWriterAGG(gshhs_root_dir)
cw.add_coastlines(img, area_def, resolution='l', level=4)
- cw.add_rivers(img, area_def, level=5, outline='blue', width=0.5, outline_opacity=127)
- cw.add_borders(img, area_def, outline=(255, 0, 0), width=3, outline_opacity=32)
+ cw.add_rivers(img, area_def, level=5, outline='blue', width=0.5,
+ outline_opacity=127)
+ cw.add_borders(img, area_def, outline=(255, 0, 0),
+ width=3, outline_opacity=32)
res = np.array(img)
- self.failUnless(fft_metric(euro_data, res), 'Writing of contours failed for AGG')
+ self.failUnless(fft_metric(euro_data, res),
+ 'Writing of contours failed for AGG')
def test_europe_agg_file(self):
from pycoast import ContourWriterAGG
@@ -329,19 +379,21 @@ class TestPILAGG(TestPycoast):
'contours_europe_agg.png'))
euro_data = np.array(euro_img)
- proj4_string = '+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84'
+ proj4_string = \
+ '+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84'
area_extent = (-3363403.31, -2291879.85, 2630596.69, 2203620.1)
area_def = (proj4_string, area_extent)
cw = ContourWriterAGG(gshhs_root_dir)
cw.add_coastlines_to_file(test_file, area_def, resolution='l', level=4)
cw.add_rivers_to_file(test_file, area_def, level=5, outline='blue',
width=0.5, outline_opacity=127)
- cw.add_borders_to_file(test_file, area_def, outline=(255, 0, 0), width=3,
- outline_opacity=32)
+ cw.add_borders_to_file(test_file, area_def, outline=(255, 0, 0),
+ width=3, outline_opacity=32)
img = Image.open(test_file)
res = np.array(img)
- self.failUnless(fft_metric(euro_data, res), 'Writing of contours failed for AGG')
+ self.failUnless(fft_metric(euro_data, res),
+ 'Writing of contours failed for AGG')
def test_geos_agg(self):
from pycoast import ContourWriterAGG
@@ -350,13 +402,17 @@ class TestPILAGG(TestPycoast):
geos_data = np.array(geos_img)
img = Image.new('RGB', (425, 425))
- proj4_string = '+proj=geos +lon_0=0.0 +a=6378169.00 +b=6356583.80 +h=35785831.0'
- area_extent = (-5570248.4773392612, -5567248.074173444, 5567248.074173444, 5570248.4773392612)
- area_def = (proj4_string, area_extent)
+ proj4_string = \
+ '+proj=geos +lon_0=0.0 +a=6378169.00 +b=6356583.80 +h=35785831.0'
+ area_extent = (-5570248.4773392612, -5567248.074173444,
+ 5567248.074173444, 5570248.4773392612)
+ # area_def = (proj4_string, area_extent)
cw = ContourWriterAGG(gshhs_root_dir)
- cw.add_coastlines(img, (proj4_string, area_extent), resolution='l', width=0.5)
+ cw.add_coastlines(img, (proj4_string, area_extent),
+ resolution='l', width=0.5)
res = np.array(img)
- self.failUnless(fft_metric(geos_data, res), 'Writing of geos contours failed for AGG')
+ self.failUnless(fft_metric(geos_data, res),
+ 'Writing of geos contours failed for AGG')
def test_grid_agg(self):
from pycoast import ContourWriterAGG
@@ -365,7 +421,8 @@ class TestPILAGG(TestPycoast):
grid_data = np.array(grid_img)
img = Image.new('RGB', (640, 480))
- proj4_string = '+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84'
+ proj4_string = \
+ '+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84'
area_extent = (-3363403.31, -2291879.85, 2630596.69, 2203620.1)
area_def = (proj4_string, area_extent)
@@ -374,10 +431,12 @@ class TestPILAGG(TestPycoast):
cw.add_coastlines(img, area_def, resolution='l', level=4)
cw.add_grid(img, area_def, (10.0, 10.0), (2.0, 2.0), write_text=False,
outline='blue', outline_opacity=255, width=1.0,
- minor_outline='white', minor_outline_opacity=255, minor_width=0.5,
- minor_is_tick=False)
+ minor_outline='white', minor_outline_opacity=255,
+ minor_width=0.5, minor_is_tick=False)
+
res = np.array(img)
- self.failUnless(fft_metric(grid_data, res), 'Writing of grid failed for AGG')
+ self.failUnless(
+ fft_metric(grid_data, res), 'Writing of grid failed for AGG')
def test_grid_agg_txt(self):
from pycoast import ContourWriterAGG
@@ -387,22 +446,26 @@ class TestPILAGG(TestPycoast):
grid_data = np.array(grid_img)
img = Image.new('RGB', (640, 480))
- proj4_string = '+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84'
+ proj4_string = \
+ '+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84'
area_extent = (-3363403.31, -2291879.85, 2630596.69, 2203620.1)
area_def = (proj4_string, area_extent)
cw = ContourWriterAGG(gshhs_root_dir)
cw.add_coastlines(img, area_def, resolution='l', level=4)
- font = aggdraw.Font('blue', os.path.join(os.path.dirname(__file__), 'test_data', 'DejaVuSerif.ttf'), size=16,
+ font = aggdraw.Font('blue', os.path.join(os.path.dirname(__file__),
+ 'test_data',
+ 'DejaVuSerif.ttf'), size=16,
opacity=200)
cw.add_grid(img, area_def, (10.0, 10.0), (2.0, 2.0), font=font,
outline='blue', outline_opacity=255, width=1.0,
- minor_outline='white', minor_outline_opacity=255, minor_width=0.5,
- minor_is_tick=False)
+ minor_outline='white', minor_outline_opacity=255,
+ minor_width=0.5, minor_is_tick=False, write_text=False)
res = np.array(img)
- self.failUnless(fft_metric(grid_data, res), 'Writing of grid failed for AGG')
+ self.failUnless(
+ fft_metric(grid_data, res), 'Writing of grid failed for AGG')
def test_grid_geos_agg(self):
from pycoast import ContourWriterAGG
@@ -410,16 +473,20 @@ class TestPILAGG(TestPycoast):
'grid_geos_agg.png'))
geos_data = np.array(geos_img)
img = Image.new('RGB', (425, 425))
- proj4_string = '+proj=geos +lon_0=0.0 +a=6378169.00 +b=6356583.80 +h=35785831.0'
- area_extent = (-5570248.4773392612, -5567248.074173444, 5567248.074173444, 5570248.4773392612)
+ proj4_string = \
+ '+proj=geos +lon_0=0.0 +a=6378169.00 +b=6356583.80 +h=35785831.0'
+ area_extent = (-5570248.4773392612, -5567248.074173444,
+ 5567248.074173444, 5570248.4773392612)
area_def = (proj4_string, area_extent)
cw = ContourWriterAGG(gshhs_root_dir)
cw.add_coastlines(img, area_def, resolution='l')
- cw.add_grid(img, area_def, (10.0, 10.0), (2.0, 2.0), fill='blue', outline='blue', minor_outline='blue',
+ cw.add_grid(img, area_def, (10.0, 10.0), (2.0, 2.0),
+ fill='blue', outline='blue', minor_outline='blue',
write_text=False)
res = np.array(img)
- self.failUnless(fft_metric(geos_data, res), 'Writing of geos contours failed')
+ self.failUnless(
+ fft_metric(geos_data, res), 'Writing of geos contours failed')
def test_grid_agg_file(self):
from pycoast import ContourWriterAGG
@@ -427,20 +494,23 @@ class TestPILAGG(TestPycoast):
'grid_europe_agg.png'))
grid_data = np.array(grid_img)
- proj4_string = '+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84'
+ proj4_string = \
+ '+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84'
area_extent = (-3363403.31, -2291879.85, 2630596.69, 2203620.1)
area_def = (proj4_string, area_extent)
cw = ContourWriterAGG(gshhs_root_dir)
cw.add_coastlines_to_file(grid_file, area_def, resolution='l', level=4)
- cw.add_grid_to_file(grid_file, area_def, (10.0, 10.0), (2.0, 2.0), write_text=False,
- outline='blue', outline_opacity=255, width=1.0,
- minor_outline='white', minor_outline_opacity=255, minor_width=0.5,
- minor_is_tick=False)
+ cw.add_grid_to_file(grid_file, area_def, (10.0, 10.0), (2.0, 2.0),
+ write_text=False, outline='blue',
+ outline_opacity=255, width=1.0,
+ minor_outline='white', minor_outline_opacity=255,
+ minor_width=0.5, minor_is_tick=False)
img = Image.open(grid_file)
res = np.array(img)
- self.failUnless(fft_metric(grid_data, res), 'Writing of grid failed for AGG')
+ self.failUnless(
+ fft_metric(grid_data, res), 'Writing of grid failed for AGG')
def test_grid_nh_agg(self):
from pycoast import ContourWriterAGG
@@ -450,22 +520,28 @@ class TestPILAGG(TestPycoast):
grid_data = np.array(grid_img)
img = Image.new('RGB', (425, 425))
proj4_string = '+proj=laea +lat_0=90 +lon_0=0 +a=6371228.0 +units=m'
- area_extent = (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)
+ area_extent = (-5326849.0625, -5326849.0625,
+ 5326849.0625, 5326849.0625)
area_def = (proj4_string, area_extent)
cw = ContourWriterAGG(gshhs_root_dir)
cw.add_coastlines(img, area_def, resolution='l', level=4)
- font = aggdraw.Font('blue', os.path.join(os.path.dirname(__file__), 'test_data', 'DejaVuSerif.ttf'), size=10)
- cw.add_grid(img, area_def, (10.0, 10.0), (2.0, 2.0), font=font, fill='blue',
+ font = aggdraw.Font('blue', os.path.join(os.path.dirname(__file__),
+ 'test_data',
+ 'DejaVuSerif.ttf'), size=10)
+ cw.add_grid(img, area_def, (10.0, 10.0), (2.0, 2.0),
+ font=font, fill='blue', write_text=False,
outline='blue', minor_outline='blue',
lon_placement='tblr', lat_placement='')
res = np.array(img)
- ## NOTE: Experience inconsistency in ttf font writing between systems.
- ## Still trying to figure out why this test sometimes fails to write correct font markings.
- self.failUnless(fft_metric(grid_data, res), 'Writing of nh grid failed for AGG')
+ # NOTE: Experience inconsistency in ttf font writing between systems.
+ # Still trying to figure out why this test sometimes fails to write
+ # correct font markings.
+ self.failUnless(fft_metric(grid_data, res),
+ 'Writing of nh grid failed for AGG')
def test_add_polygon_agg(self):
from pycoast import ContourWriterAGG
@@ -475,29 +551,35 @@ class TestPILAGG(TestPycoast):
img = Image.new('RGB', (425, 425))
proj4_string = '+proj=laea +lat_0=90 +lon_0=0 +a=6371228.0 +units=m'
- area_extent = (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)
+ area_extent = (-5326849.0625, -5326849.0625,
+ 5326849.0625, 5326849.0625)
area_def = (proj4_string, area_extent)
cw = ContourWriterAGG(gshhs_root_dir)
polygons = {
- 'REYKJAVIK_ATC_A': ((-20.0, 73.0), (0.0, 73.0), (0.0, 61.0), (-30.0, 61.0), (-39.0, 63.5), (-20, 70)),
- 'REYKJAVIK_ATC_B': (
- (-39, 63.5), (-55 + 4 / 6.0, 63.5), (-57 + 45 / 60.0, 65), (-76, 76), (-75, 78), (-60, 82), (0, 90),
- (30, 82), (0, 82), (0, 73), (-20, 73), (-20,
- 70)),
- 'REYKJAVIK_ATC': (
- (0.0, 73.0), (0.0, 61.0), (-30.0, 61.0), (-39, 63.5), (-55 + 4 / 6.0, 63.5), (-57 + 45 / 60.0, 65),
- (-76, 76), (-75, 78), (-60, 82), (0, 90), (30, 82), (0, 82)),
- 'ICELAND_BOX': ((-25, 62.5), (-25, 67), (-13, 67), (-13, 62.5))
+ 'REYKJAVIK_ATC_A': ((-20.0, 73.0), (0.0, 73.0), (0.0, 61.0),
+ (-30.0, 61.0), (-39.0, 63.5), (-20, 70)),
+ 'REYKJAVIK_ATC_B': ((-39, 63.5), (-55 + 4 / 6.0, 63.5),
+ (-57 + 45 / 60.0, 65), (-76, 76),
+ (-75, 78), (-60, 82), (0, 90), (30, 82),
+ (0, 82), (0, 73), (-20, 73), (-20, 70)),
+ 'REYKJAVIK_ATC': ((0.0, 73.0), (0.0, 61.0), (-30.0, 61.0),
+ (-39, 63.5), (-55 + 4 / 6.0, 63.5),
+ (-57 + 45 / 60.0, 65), (-76, 76), (-75, 78),
+ (-60, 82), (0, 90), (30, 82), (0, 82)),
+ 'ICELAND_BOX': ((-25, 62.5), (-25, 67), (-13, 67), (-13, 62.5))
}
- cw.add_polygon(img, area_def, polygons['REYKJAVIK_ATC'], outline='red', width=2)
- cw.add_polygon(img, area_def, polygons['ICELAND_BOX'], outline='green', fill='gray', width=2)
+ cw.add_polygon(img, area_def, polygons['REYKJAVIK_ATC'],
+ outline='red', width=2)
+ cw.add_polygon(img, area_def, polygons['ICELAND_BOX'],
+ outline='green', fill='gray', width=2)
cw.add_coastlines(img, area_def, resolution='l', level=4)
res = np.array(img)
- self.failUnless(fft_metric(grid_data, res), 'Writing of nh polygons failed')
+ self.failUnless(fft_metric(grid_data, res),
+ 'Writing of nh polygons failed')
def test_add_shapefile_shapes_agg(self):
from pycoast import ContourWriterAGG
@@ -506,7 +588,8 @@ class TestPILAGG(TestPycoast):
grid_data = np.array(grid_img)
img = Image.new('RGB', (425, 425))
- proj4_string = '+proj=merc +lon_0=-60 +lat_ts=-30.0 +a=6371228.0 +units=m'
+ proj4_string = \
+ '+proj=merc +lon_0=-60 +lat_ts=-30.0 +a=6371228.0 +units=m'
area_extent = (-2000000.0, -5000000.0, 5000000.0, 2000000.0)
area_def = (proj4_string, area_extent)
@@ -514,7 +597,9 @@ class TestPILAGG(TestPycoast):
cw.add_coastlines(img, area_def, resolution='l', level=4)
cw.add_shapefile_shapes(img, area_def,
- os.path.join(os.path.dirname(__file__), 'test_data/shapes/Metareas.shp'),
+ os.path.join(
+ os.path.dirname(__file__),
+ 'test_data/shapes/Metareas.shp'),
outline='red', width=2)
cw.add_shapefile_shape(img, area_def,
os.path.join(os.path.dirname(__file__),
@@ -524,13 +609,19 @@ class TestPILAGG(TestPycoast):
os.path.join(os.path.dirname(__file__),
'test_data/shapes/divisao_politica/BR_Regioes.shp'), 4,
outline='blue', fill='green')
+
res = np.array(img)
- self.failUnless(fft_metric(grid_data, res), 'Writing of Brazil shapefiles failed')
+ self.failUnless(
+ fft_metric(grid_data, res), 'Writing of Brazil shapefiles failed')
+
def suite():
loader = unittest.TestLoader()
mysuite = unittest.TestSuite()
mysuite.addTest(loader.loadTestsFromTestCase(TestPIL))
- mysuite.addTest(loader.loadTestsFromTestCase(TestPILAGG))
+ # mysuite.addTest(loader.loadTestsFromTestCase(TestPILAGG))
+
+ return mysuite
- return mysuite
\ No newline at end of file
+if __name__ == "__main__":
+ suite()
diff --git a/pycoast/version.py b/pycoast/version.py
index 88dcbf0..e400e26 100644
--- a/pycoast/version.py
+++ b/pycoast/version.py
@@ -1,19 +1,19 @@
-#pycoast, Writing of coastlines, borders and rivers to images in Python
-#
-#Copyright (C) 2011 Esben S. Nielsen
+# pycoast, Writing of coastlines, borders and rivers to images in Python
#
-#This program 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
+# Copyright (C) 2011 Esben S. Nielsen
+#
+# This program 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.
#
-#This program 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.
+# This program 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
+# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-__version__ = '0.5.4'
+__version__ = '0.6.1'
diff --git a/setup.cfg b/setup.cfg
index 530f8a4..cec5037 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,5 +1,8 @@
+[bumpversion]
+current_version = 0.6.0
+
[bdist_rpm]
-requires=pyshp python-pillow aggdraw
-release=1
+requires = pyshp python-pillow aggdraw
+release = 1
doc_files = docs/Makefile docs/source/*.rst
diff --git a/setup.py b/setup.py
index 75f8666..f9a2d1d 100644
--- a/setup.py
+++ b/setup.py
@@ -1,18 +1,18 @@
-#pycoast, Writing of coastlines, borders and rivers to images in Python
-#
-#Copyright (C) 2011, 2014 Esben S. Nielsen
+# pycoast, Writing of coastlines, borders and rivers to images in Python
#
-#This program 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
+# Copyright (C) 2011, 2014, 2016 Esben S. Nielsen
+#
+# This program 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.
#
-#This program 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.
+# This program 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
+# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from setuptools import setup
@@ -33,17 +33,16 @@ setup(name='pycoast',
description='Writing of coastlines, borders and rivers to images in Python',
author='Esben S. Nielsen',
author_email='esn at dmi.dk',
- packages = ['pycoast', 'pycoast.tests'],
+ packages=['pycoast', 'pycoast.tests'],
install_requires=requires,
test_suite='pycoast.tests.test_pycoast.suite',
- zip_safe = False,
+ zip_safe=False,
classifiers=[
- 'Development Status :: 5 - Production/Stable',
- 'License :: OSI Approved :: GNU General Public License v3 (GPLv3)',
- 'Programming Language :: Python',
- 'Operating System :: OS Independent',
- 'Intended Audience :: Science/Research',
- 'Topic :: Scientific/Engineering'
+ 'Development Status :: 5 - Production/Stable',
+ 'License :: OSI Approved :: GNU General Public License v3 (GPLv3)',
+ 'Programming Language :: Python',
+ 'Operating System :: OS Independent',
+ 'Intended Audience :: Science/Research',
+ 'Topic :: Scientific/Engineering'
]
)
-
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/pycoast.git
More information about the Pkg-grass-devel
mailing list