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 <[email protected]> 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') [email protected](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='[email protected]', - 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 _______________________________________________ Pkg-grass-devel mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-grass-devel

