{"action":"created","comment":{"url":"https://api.github.com/repos/AIFDR/inasafe/pulls/comments/33351491","id":33351491,"diff_hunk":"@@ -676,3 +677,107 @@ def adjust_clip_extent(clip_extent, cell_size, layer_extent):\n         adjusted_xmin, adjusted_ymin, adjusted_xmax, adjusted_ymax]\n \n     return adjusted_extent\n+\n+\n+def qgis_align_rasters_available():\n+    \"\"\"\n+    Determine whether QGIS is running in a version recent enough to contain\n+    raster alignment tool (added in 2.12)\n+\n+    :return: bool\n+    \"\"\"\n+    try:\n+        from qgis.analysis import QgsAlignRaster\n+        return True\n+    except ImportError:\n+        return False\n+\n+\n+def qgis_align_rasters(hazard_layer, exposure_layer, geo_extent):\n+    \"\"\"\n+    Align hazard and exposure raster layers so they fit perfectly and\n+    so they can be used for raster algebra. The method uses QGIS\n+    raster alignment tool to do the work (which in turn uses GDAL).\n+\n+    Alignment of layers means that the layers have the same CRS, cell size,\n+    grid origin and size. That involves clipping and resampling of rasters.\n+\n+    From the two layers, the layer with finer resolution (smaller cell size)\n+    will be used as the reference for the alignment (i.e. parameters will\n+    be set to its CRS, cell size and grid offset).\n+\n+    Before calling this function make sure to first check whether\n+    this functionality is available in QGIS as this requires a recent\n+    QGIS version (2.12).\n+\n+    :param hazard_layer: Hazard layer to be aligned\n+    :type exposure_layer: QgsRasterLayer\n+\n+    :param exposure_layer: Exposure layer to be aligned\n+    :type exposure_layer: QgsRasterLayer\n+\n+    :param geo_extent: Extent in WGS 84 to which raster should be clipped\n+    :type geo_extent: list\n+\n+    :return: clipped hazard and exposure layers\n+    :rtype: QgsRasterLayer, QgsRasterLayer\n+    \"\"\"\n+\n+    hazard_output = unique_filename(suffix='.tif')\n+    exposure_output = unique_filename(suffix='.tif')\n+\n+    exposure_keywords = read_file_keywords(exposure_layer.source())\n+\n+    # Setup the two raster layers for alignment\n+    from qgis.analysis import QgsAlignRaster\n+    align = QgsAlignRaster()\n+    lst = [QgsAlignRaster.Item(hazard_layer.source(), hazard_output),\n+           QgsAlignRaster.Item(exposure_layer.source(), exposure_output)]\n+    # TODO: what keywords to consider for rescaling?\n+    if exposure_keywords.get('exposure_unit') == 'count':\n+        lst[1].rescaleValues = True\n+    align.setRasters(lst)\n+\n+    # Find out which layer has finer grid and use it as the reference.\n+    # This will setup destination CRS, cell size and grid origin\n+    # TODO: need to respect 'allow_resampling' keyword?\n+    if exposure_keywords.get('allow_resampling', 'true').lower() == 'true':","path":"safe/utilities/clipper.py","position":83,"original_position":83,"commit_id":"183b2eacbb1645b23bad5957b8c67e455fccee1f","original_commit_id":"183b2eacbb1645b23bad5957b8c67e455fccee1f","user":{"login":"akbargumbira","id":992519,"avatar_url":"https://avatars.githubusercontent.com/u/992519?v=3","gravatar_id":"","url":"https://api.github.com/users/akbargumbira","html_url":"https://github.com/akbargumbira","followers_url":"https://api.github.com/users/akbargumbira/followers","following_url":"https://api.github.com/users/akbargumbira/following{/other_user}","gists_url":"https://api.github.com/users/akbargumbira/gists{/gist_id}","starred_url":"https://api.github.com/users/akbargumbira/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/akbargumbira/subscriptions","organizations_url":"https://api.github.com/users/akbargumbira/orgs","repos_url":"https://api.github.com/users/akbargumbira/repos","events_url":"https://api.github.com/users/akbargumbira/events{/privacy}","received_events_url":"https://api.github.com/users/akbargumbira/received_events","type":"User","site_admin":false},"body":"probably would be better to have a more generic method of this (i.e having one parameter to which layer it should be resampled regarding the grid size) and passing the preference for that would be the job of analysis class (and moving the keywords 'allow_resampling' to that class). With that, this function would be also useful for testing native IF's as we need to clip the layer first. To do that now, I made a clipping function for testing purpose which a bit dodgy","created_at":"2015-06-26T12:36:15Z","updated_at":"2015-06-26T12:36:15Z","html_url":"https://github.com/AIFDR/inasafe/pull/2070#discussion_r33351491","pull_request_url":"https://api.github.com/repos/AIFDR/inasafe/pulls/2070","_links":{"self":{"href":"https://api.github.com/repos/AIFDR/inasafe/pulls/comments/33351491"},"html":{"href":"https://github.com/AIFDR/inasafe/pull/2070#discussion_r33351491"},"pull_request":{"href":"https://api.github.com/repos/AIFDR/inasafe/pulls/2070"}}},"pull_request":{"url":"https://api.github.com/repos/AIFDR/inasafe/pulls/2070","id":38641109,"html_url":"https://github.com/AIFDR/inasafe/pull/2070","diff_url":"https://github.com/AIFDR/inasafe/pull/2070.diff","patch_url":"https://github.com/AIFDR/inasafe/pull/2070.patch","issue_url":"https://api.github.com/repos/AIFDR/inasafe/issues/2070","number":2070,"state":"open","locked":false,"title":"Align raster layers using QGIS functionality","user":{"login":"wonder-sk","id":193367,"avatar_url":"https://avatars.githubusercontent.com/u/193367?v=3","gravatar_id":"","url":"https://api.github.com/users/wonder-sk","html_url":"https://github.com/wonder-sk","followers_url":"https://api.github.com/users/wonder-sk/followers","following_url":"https://api.github.com/users/wonder-sk/following{/other_user}","gists_url":"https://api.github.com/users/wonder-sk/gists{/gist_id}","starred_url":"https://api.github.com/users/wonder-sk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/wonder-sk/subscriptions","organizations_url":"https://api.github.com/users/wonder-sk/orgs","repos_url":"https://api.github.com/users/wonder-sk/repos","events_url":"https://api.github.com/users/wonder-sk/events{/privacy}","received_events_url":"https://api.github.com/users/wonder-sk/received_events","type":"User","site_admin":false},"body":"The PR implements a new way of clipping and resampling of rasters within InaSAFE - see RFC #1998 for more details.\r\n\r\nIn order to test the new functionality one needs QGIS raster alignment tool - currently only available in my branch:\r\nhttps://github.com/wonder-sk/QGIS/tree/raster-alignment-tool\r\n\r\nIf the QGIS raster alignment tool is not present, InaSAFE will use the original code path.\r\n","created_at":"2015-06-26T11:40:12Z","updated_at":"2015-06-26T12:36:15Z","closed_at":null,"merged_at":null,"merge_commit_sha":"2691d9def47c842a650235190d058df78a4b3417","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/AIFDR/inasafe/pulls/2070/commits","review_comments_url":"https://api.github.com/repos/AIFDR/inasafe/pulls/2070/comments","review_comment_url":"https://api.github.com/repos/AIFDR/inasafe/pulls/comments{/number}","comments_url":"https://api.github.com/repos/AIFDR/inasafe/issues/2070/comments","statuses_url":"https://api.github.com/repos/AIFDR/inasafe/statuses/183b2eacbb1645b23bad5957b8c67e455fccee1f","head":{"label":"wonder-sk:use_qgis_raster_align","ref":"use_qgis_raster_align","sha":"183b2eacbb1645b23bad5957b8c67e455fccee1f","user":{"login":"wonder-sk","id":193367,"avatar_url":"https://avatars.githubusercontent.com/u/193367?v=3","gravatar_id":"","url":"https://api.github.com/users/wonder-sk","html_url":"https://github.com/wonder-sk","followers_url":"https://api.github.com/users/wonder-sk/followers","following_url":"https://api.github.com/users/wonder-sk/following{/other_user}","gists_url":"https://api.github.com/users/wonder-sk/gists{/gist_id}","starred_url":"https://api.github.com/users/wonder-sk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/wonder-sk/subscriptions","organizations_url":"https://api.github.com/users/wonder-sk/orgs","repos_url":"https://api.github.com/users/wonder-sk/repos","events_url":"https://api.github.com/users/wonder-sk/events{/privacy}","received_events_url":"https://api.github.com/users/wonder-sk/received_events","type":"User","site_admin":false},"repo":{"id":36855042,"name":"inasafe","full_name":"wonder-sk/inasafe","owner":{"login":"wonder-sk","id":193367,"avatar_url":"https://avatars.githubusercontent.com/u/193367?v=3","gravatar_id":"","url":"https://api.github.com/users/wonder-sk","html_url":"https://github.com/wonder-sk","followers_url":"https://api.github.com/users/wonder-sk/followers","following_url":"https://api.github.com/users/wonder-sk/following{/other_user}","gists_url":"https://api.github.com/users/wonder-sk/gists{/gist_id}","starred_url":"https://api.github.com/users/wonder-sk/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/wonder-sk/subscriptions","organizations_url":"https://api.github.com/users/wonder-sk/orgs","repos_url":"https://api.github.com/users/wonder-sk/repos","events_url":"https://api.github.com/users/wonder-sk/events{/privacy}","received_events_url":"https://api.github.com/users/wonder-sk/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/wonder-sk/inasafe","description":"InaSAFE - QGIS plugin for estimating impact from natural disasters","fork":true,"url":"https://api.github.com/repos/wonder-sk/inasafe","forks_url":"https://api.github.com/repos/wonder-sk/inasafe/forks","keys_url":"https://api.github.com/repos/wonder-sk/inasafe/keys{/key_id}","collaborators_url":"https://api.github.com/repos/wonder-sk/inasafe/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/wonder-sk/inasafe/teams","hooks_url":"https://api.github.com/repos/wonder-sk/inasafe/hooks","issue_events_url":"https://api.github.com/repos/wonder-sk/inasafe/issues/events{/number}","events_url":"https://api.github.com/repos/wonder-sk/inasafe/events","assignees_url":"https://api.github.com/repos/wonder-sk/inasafe/assignees{/user}","branches_url":"https://api.github.com/repos/wonder-sk/inasafe/branches{/branch}","tags_url":"https://api.github.com/repos/wonder-sk/inasafe/tags","blobs_url":"https://api.github.com/repos/wonder-sk/inasafe/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/wonder-sk/inasafe/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/wonder-sk/inasafe/git/refs{/sha}","trees_url":"https://api.github.com/repos/wonder-sk/inasafe/git/trees{/sha}","statuses_url":"https://api.github.com/repos/wonder-sk/inasafe/statuses/{sha}","languages_url":"https://api.github.com/repos/wonder-sk/inasafe/languages","stargazers_url":"https://api.github.com/repos/wonder-sk/inasafe/stargazers","contributors_url":"https://api.github.com/repos/wonder-sk/inasafe/contributors","subscribers_url":"https://api.github.com/repos/wonder-sk/inasafe/subscribers","subscription_url":"https://api.github.com/repos/wonder-sk/inasafe/subscription","commits_url":"https://api.github.com/repos/wonder-sk/inasafe/commits{/sha}","git_commits_url":"https://api.github.com/repos/wonder-sk/inasafe/git/commits{/sha}","comments_url":"https://api.github.com/repos/wonder-sk/inasafe/comments{/number}","issue_comment_url":"https://api.github.com/repos/wonder-sk/inasafe/issues/comments{/number}","contents_url":"https://api.github.com/repos/wonder-sk/inasafe/contents/{+path}","compare_url":"https://api.github.com/repos/wonder-sk/inasafe/compare/{base}...{head}","merges_url":"https://api.github.com/repos/wonder-sk/inasafe/merges","archive_url":"https://api.github.com/repos/wonder-sk/inasafe/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/wonder-sk/inasafe/downloads","issues_url":"https://api.github.com/repos/wonder-sk/inasafe/issues{/number}","pulls_url":"https://api.github.com/repos/wonder-sk/inasafe/pulls{/number}","milestones_url":"https://api.github.com/repos/wonder-sk/inasafe/milestones{/number}","notifications_url":"https://api.github.com/repos/wonder-sk/inasafe/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/wonder-sk/inasafe/labels{/name}","releases_url":"https://api.github.com/repos/wonder-sk/inasafe/releases{/id}","created_at":"2015-06-04T07:26:55Z","updated_at":"2015-06-04T07:26:58Z","pushed_at":"2015-06-26T11:31:25Z","git_url":"git://github.com/wonder-sk/inasafe.git","ssh_url":"git@github.com:wonder-sk/inasafe.git","clone_url":"https://github.com/wonder-sk/inasafe.git","svn_url":"https://github.com/wonder-sk/inasafe","homepage":"www.inasafe.org","size":134178,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"develop"}},"base":{"label":"AIFDR:develop","ref":"develop","sha":"cee6fa47a6c915e5ec3ba123f27af52b8d9ebf21","user":{"login":"AIFDR","id":582004,"avatar_url":"https://avatars.githubusercontent.com/u/582004?v=3","gravatar_id":"","url":"https://api.github.com/users/AIFDR","html_url":"https://github.com/AIFDR","followers_url":"https://api.github.com/users/AIFDR/followers","following_url":"https://api.github.com/users/AIFDR/following{/other_user}","gists_url":"https://api.github.com/users/AIFDR/gists{/gist_id}","starred_url":"https://api.github.com/users/AIFDR/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AIFDR/subscriptions","organizations_url":"https://api.github.com/users/AIFDR/orgs","repos_url":"https://api.github.com/users/AIFDR/repos","events_url":"https://api.github.com/users/AIFDR/events{/privacy}","received_events_url":"https://api.github.com/users/AIFDR/received_events","type":"Organization","site_admin":false},"repo":{"id":3135721,"name":"inasafe","full_name":"AIFDR/inasafe","owner":{"login":"AIFDR","id":582004,"avatar_url":"https://avatars.githubusercontent.com/u/582004?v=3","gravatar_id":"","url":"https://api.github.com/users/AIFDR","html_url":"https://github.com/AIFDR","followers_url":"https://api.github.com/users/AIFDR/followers","following_url":"https://api.github.com/users/AIFDR/following{/other_user}","gists_url":"https://api.github.com/users/AIFDR/gists{/gist_id}","starred_url":"https://api.github.com/users/AIFDR/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/AIFDR/subscriptions","organizations_url":"https://api.github.com/users/AIFDR/orgs","repos_url":"https://api.github.com/users/AIFDR/repos","events_url":"https://api.github.com/users/AIFDR/events{/privacy}","received_events_url":"https://api.github.com/users/AIFDR/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/AIFDR/inasafe","description":"InaSAFE - QGIS plugin for estimating impact from natural disasters","fork":false,"url":"https://api.github.com/repos/AIFDR/inasafe","forks_url":"https://api.github.com/repos/AIFDR/inasafe/forks","keys_url":"https://api.github.com/repos/AIFDR/inasafe/keys{/key_id}","collaborators_url":"https://api.github.com/repos/AIFDR/inasafe/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/AIFDR/inasafe/teams","hooks_url":"https://api.github.com/repos/AIFDR/inasafe/hooks","issue_events_url":"https://api.github.com/repos/AIFDR/inasafe/issues/events{/number}","events_url":"https://api.github.com/repos/AIFDR/inasafe/events","assignees_url":"https://api.github.com/repos/AIFDR/inasafe/assignees{/user}","branches_url":"https://api.github.com/repos/AIFDR/inasafe/branches{/branch}","tags_url":"https://api.github.com/repos/AIFDR/inasafe/tags","blobs_url":"https://api.github.com/repos/AIFDR/inasafe/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/AIFDR/inasafe/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/AIFDR/inasafe/git/refs{/sha}","trees_url":"https://api.github.com/repos/AIFDR/inasafe/git/trees{/sha}","statuses_url":"https://api.github.com/repos/AIFDR/inasafe/statuses/{sha}","languages_url":"https://api.github.com/repos/AIFDR/inasafe/languages","stargazers_url":"https://api.github.com/repos/AIFDR/inasafe/stargazers","contributors_url":"https://api.github.com/repos/AIFDR/inasafe/contributors","subscribers_url":"https://api.github.com/repos/AIFDR/inasafe/subscribers","subscription_url":"https://api.github.com/repos/AIFDR/inasafe/subscription","commits_url":"https://api.github.com/repos/AIFDR/inasafe/commits{/sha}","git_commits_url":"https://api.github.com/repos/AIFDR/inasafe/git/commits{/sha}","comments_url":"https://api.github.com/repos/AIFDR/inasafe/comments{/number}","issue_comment_url":"https://api.github.com/repos/AIFDR/inasafe/issues/comments{/number}","contents_url":"https://api.github.com/repos/AIFDR/inasafe/contents/{+path}","compare_url":"https://api.github.com/repos/AIFDR/inasafe/compare/{base}...{head}","merges_url":"https://api.github.com/repos/AIFDR/inasafe/merges","archive_url":"https://api.github.com/repos/AIFDR/inasafe/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/AIFDR/inasafe/downloads","issues_url":"https://api.github.com/repos/AIFDR/inasafe/issues{/number}","pulls_url":"https://api.github.com/repos/AIFDR/inasafe/pulls{/number}","milestones_url":"https://api.github.com/repos/AIFDR/inasafe/milestones{/number}","notifications_url":"https://api.github.com/repos/AIFDR/inasafe/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/AIFDR/inasafe/labels{/name}","releases_url":"https://api.github.com/repos/AIFDR/inasafe/releases{/id}","created_at":"2012-01-09T10:34:29Z","updated_at":"2015-06-24T23:09:40Z","pushed_at":"2015-06-26T11:40:12Z","git_url":"git://github.com/AIFDR/inasafe.git","ssh_url":"git@github.com:AIFDR/inasafe.git","clone_url":"https://github.com/AIFDR/inasafe.git","svn_url":"https://github.com/AIFDR/inasafe","homepage":"www.inasafe.org","size":159703,"stargazers_count":71,"watchers_count":71,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":70,"mirror_url":null,"open_issues_count":242,"forks":70,"open_issues":242,"watchers":71,"default_branch":"develop"}},"_links":{"self":{"href":"https://api.github.com/repos/AIFDR/inasafe/pulls/2070"},"html":{"href":"https://github.com/AIFDR/inasafe/pull/2070"},"issue":{"href":"https://api.github.com/repos/AIFDR/inasafe/issues/2070"},"comments":{"href":"https://api.github.com/repos/AIFDR/inasafe/issues/2070/comments"},"review_comments":{"href":"https://api.github.com/repos/AIFDR/inasafe/pulls/2070/comments"},"review_comment":{"href":"https://api.github.com/repos/AIFDR/inasafe/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/AIFDR/inasafe/pulls/2070/commits"},"statuses":{"href":"https://api.github.com/repos/AIFDR/inasafe/statuses/183b2eacbb1645b23bad5957b8c67e455fccee1f"}}}}