{"action":"created","comment":{"url":"https://api.github.com/repos/metoppv/improver/pulls/comments/202633881","pull_request_review_id":137355127,"id":202633881,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIwMjYzMzg4MQ==","diff_hunk":"@@ -0,0 +1,308 @@\n+# -*- coding: utf-8 -*-\n+# -----------------------------------------------------------------------------\n+# (C) British Crown Copyright 2017-2018 Met Office.\n+# All rights reserved.\n+#\n+# Redistribution and use in source and binary forms, with or without\n+# modification, are permitted provided that the following conditions are met:\n+#\n+# * Redistributions of source code must retain the above copyright notice, this\n+#   list of conditions and the following disclaimer.\n+#\n+# * Redistributions in binary form must reproduce the above copyright notice,\n+#   this list of conditions and the following disclaimer in the documentation\n+#   and/or other materials provided with the distribution.\n+#\n+# * Neither the name of the copyright holder nor the names of its\n+#   contributors may be used to endorse or promote products derived from\n+#   this software without specific prior written permission.\n+#\n+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\n+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n+# POSSIBILITY OF SUCH DAMAGE.\n+\"\"\"Module containing lapse rate calculation plugins.\"\"\"\n+\n+import iris\n+import numpy as np\n+from numpy.linalg import lstsq\n+from improver.utilities.cube_manipulation import enforce_float32_precision\n+\n+from improver.constants import (ABSOLUTE_ZERO)\n+\n+from scipy.ndimage import generic_filter\n+\n+\n+class LapseRate(object):\n+    \"\"\"Plugin to calculate the lapse rate from orography and temperature\n+       fields.\n+\n+    Science background:\n+\n+    The method applied here is based on the method used in the 2010 paper:\n+    https://rmets.onlinelibrary.wiley.com/doi/abs/10.1002/met.177\n+\n+    The current lapse rate (LR) FORTRAN code is kept here:\n+    http://fcm9/projects/PostProc/browser/PostProc/trunk/\n+                                         model_processing/Fss_CalcTLev1Grad.f90\n+\n+    However the paper doesn't give critical information on certain aspects and\n+    they will need more investigation - but for now its important to just have\n+    a functional script.\n+\n+    1) The paper imposes an upper limit to the LR of 0.0098K/m-1\n+       (the Dry Air Adibatic Lapse Rate) but not a lower limit.\n+\n+       Wheras the current FORTRAN code places a lower limit on the LR of\n+       -3.0*DALR in addition to the upper limit.\n+\n+    2) The paper and FORTRAN code uses a 8x8 neighbourhood, but this was for\n+       the older 4km model. More research is required to determine what size\n+       neighbourhood is needed for UKV data.\n+       In addition - this code will not work with even-numbered neighbourhood\n+       sizes. This is because the neighbourhooding code requires a\n+       centre point.\n+\n+    3) Where an invalid lapse rate calculation is returned - should the code\n+       return zero or DALR? See \"calc_lapse_rate\" function.\n+\n+    Code methodology:\n+    1) Apply land/sea mask to temperature and orography datasets. Mask sea\n+       points as NaN since image processing module does not recognise Numpy\n+       masks.\n+    2) Extracts neighbourhoods from both datasets:\n+       Apply \"generic_filter\" image processing module to temperature data\n+       to extract a neighbourhood for each single point and save this\n+       neighbourhood into a larger array.\n+       Repeat for orography data.\n+       generic_filter mode=\"constant\" ensures that points beyond edges of\n+       dataset will be filled with \"cval\". (NaN in this case)\n+    3) For all the stored orography neighbourhoods - take the neighbours around\n+       the central point and create a mask where the height difference from\n+       the central point is greater than 35m.\n+    4) Loop through array of neighbourhoods and take the height and temperature\n+       of all grid points and calculate the\n+       temperature/height gradient = lapse rate\n+    5) Constrain the lapse rate as < DALR and > -3.0*DALR\n+\n+    \"\"\"\n+\n+    def __init__(self):\n+        \"\"\"Initialise class.\"\"\"\n+        pass\n+\n+    def __repr__(self):\n+        \"\"\"Represent the configured plugin instance as a string.\"\"\"\n+        desc = ('<LapseRate>')\n+        return desc\n+\n+    def process(self, temperature_cube, orography_cube, land_sea_mask_cube,\n+                max_height_diff=35, footprint_len=3):\n+        \"\"\"Calculates the lapse rate from the temperature and orography cubes.\n+\n+        Args:\n+            temperature_cube (iris.cube.Cube):\n+                Cube of air temperatures (K).\n+\n+            orography_cube (Iris.cube.Cube):\n+                Cube containing orography data (metres)\n+\n+            land_sea_mask_cube (iris.cube.Cube):\n+                Cube containing a binary land-sea mask. True for land-points\n+                and False for Sea.\n+\n+        Keyword Args:\n+            max_height_diff (float):\n+                Maximum allowable height difference between the central point\n+                and its neighboours (metres).\n+\n+            footprint_len (int):\n+                Size of neighbourhood around each point.\n+\n+        Returns:\n+            lapse_rate_cube (iris.cube.Cube):\n+                Cube containing lapse rate (Km-1)\n+\n+        Raises\n+        ------\n+        TypeError: If input cubes are not cubes\n+\n+        \"\"\"\n+\n+        class fnc_class:\n+            def __init__(self, allbuffers):\n+                # Initialises the iterator:\n+                self.i = 0\n+                # Saves all the buffers into this array.\n+                self.allbuffers = allbuffers\n+\n+            def filter(self, buffer):\n+                self.allbuffers[self.i, :] = buffer\n+                self.i += 1\n+                return 0.0  # Need to return a value\n+\n+        def calc_lapse_rate(temperature, orography, ind_central_point):\n+            \"\"\"\n+            Least-squares fit to local temperature and altitude data to\n+            calculate a local lapse rate.\n+\n+            \"\"\"\n+\n+            # If central point NaN then return blank value.\n+            if np.isnan(temperature[ind_central_point]):\n+                return 0.0\n+\n+            # Remove NaN values before calculation.\n+            y_data = temperature[~np.isnan(temperature)]\n+            x_data = orography[~np.isnan(orography)]\n+\n+            # If empty array - return blank value.\n+            if len(y_data) == 0:\n+                return 0.0\n+\n+            matrix = np.stack([x_data, np.ones(len(x_data))], axis=0).T\n+            gradient, intercept = lstsq(matrix, y_data)[0]\n+\n+            return gradient\n+\n+        def create_height_diff_mask(all_orog_subsections, ind_central_point,\n+                                    max_height_diff):\n+            \"\"\"\n+            Create a mask for any neighbouring points where the height\n+            difference from the central point is greater than max_height_diff.\n+\n+            Slice through the orography subsection array to remove central\n+            points. Then subtract central height value from neighbourhoods.\n+            \"\"\"\n+            central_points = all_orog_subsections[:, ind_central_point]\n+            central_points = np.swapaxes([central_points], 0, 1)\n+\n+            height_diff = np.subtract(all_orog_subsections, central_points)\n+            height_diff = np.absolute(height_diff)\n+\n+            height_diff_mask = np.where(height_diff >= max_height_diff, True,\n+                                        False)\n+            return height_diff_mask\n+\n+        DALR = 0.0098  # Dry Adiabatic Lapse Rate in unit of K/m-1\n+\n+        # footprint=3 corresponds to a 3x3 array centred on central point.\n+        # Exclude even numbers since the central point is lower right eg.\n+        # 4x4 array means centre is (2,2).\n+        if footprint_len % 2 == 0:\n+            msg = \"Footprint length is {}, must be odd number!\"\n+            raise ValueError(msg.format(footprint_len))\n+\n+        # generic_filter extracts the neighbourhood and returns a 1D array.\n+        # ind_central_point indicates where the central point is on this array\n+        footprintarray_size = footprint_len**2\n+        ind_central_point = int(footprintarray_size/2)\n+\n+        if not isinstance(temperature_cube, iris.cube.Cube):\n+            msg = \"Temperature input is not a cube, but {}\"\n+            raise TypeError(msg.format(type(temperature_cube)))\n+\n+        if not isinstance(orography_cube, iris.cube.Cube):\n+            msg = \"Orography input is not a cube, but {}\"\n+            raise TypeError(msg.format(type(orography_cube)))\n+\n+        if not isinstance(land_sea_mask_cube, iris.cube.Cube):\n+            msg = \"Land/Sea mask input is not a cube, but {}\"\n+            raise TypeError(msg.format(type(land_sea_mask_cube)))\n+\n+        enforce_float32_precision([temperature_cube])\n+\n+        # Extract x/y co-ordinates.\n+        x_coord = temperature_cube.coord(axis='x').name()\n+        y_coord = temperature_cube.coord(axis='y').name()\n+\n+        # Extract orography and land/sea mask data.\n+        orography_data = next(orography_cube.slices([y_coord,\n+                                                     x_coord])).data\n+        land_sea_mask = next(land_sea_mask_cube.slices([y_coord,\n+                                                        x_coord])).data\n+        # Fill sea points with NaN values.\n+        orography_data = np.where(land_sea_mask, orography_data, np.nan)\n+\n+        # Extract data array dimensions to define output arrays.\n+        dataarray_shape = next(temperature_cube.slices(\n+            [\"realization\", y_coord, x_coord])).data[0].shape\n+        dataarray_size = dataarray_shape[0] * dataarray_shape[1]\n+\n+        # Array containing all of the subsections extracted from data array.\n+        all_temp_subsections = np.zeros((dataarray_size, footprintarray_size))\n+        all_orog_subsections = np.zeros((dataarray_size, footprintarray_size))\n+\n+        # Creates cube list to hold lapse rate data.\n+        lapse_rate_cube_list = iris.cube.CubeList([])\n+\n+        slices_over_realization = temperature_cube.slices_over(\"realization\")","path":"lib/improver/lapse_rate.py","position":246,"original_position":246,"commit_id":"ba98fc17f38fddbbda7eee28b42bd3a2df71d520","original_commit_id":"ba98fc17f38fddbbda7eee28b42bd3a2df71d520","user":{"login":"bayliffe","id":28042362,"node_id":"MDQ6VXNlcjI4MDQyMzYy","avatar_url":"https://avatars3.githubusercontent.com/u/28042362?v=4","gravatar_id":"","url":"https://api.github.com/users/bayliffe","html_url":"https://github.com/bayliffe","followers_url":"https://api.github.com/users/bayliffe/followers","following_url":"https://api.github.com/users/bayliffe/following{/other_user}","gists_url":"https://api.github.com/users/bayliffe/gists{/gist_id}","starred_url":"https://api.github.com/users/bayliffe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/bayliffe/subscriptions","organizations_url":"https://api.github.com/users/bayliffe/orgs","repos_url":"https://api.github.com/users/bayliffe/repos","events_url":"https://api.github.com/users/bayliffe/events{/privacy}","received_events_url":"https://api.github.com/users/bayliffe/received_events","type":"User","site_admin":false},"body":"Again, this assumes there is a realization coordinate.","created_at":"2018-07-16T10:19:01Z","updated_at":"2018-07-16T11:03:44Z","html_url":"https://github.com/metoppv/improver/pull/603#discussion_r202633881","pull_request_url":"https://api.github.com/repos/metoppv/improver/pulls/603","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/metoppv/improver/pulls/comments/202633881"},"html":{"href":"https://github.com/metoppv/improver/pull/603#discussion_r202633881"},"pull_request":{"href":"https://api.github.com/repos/metoppv/improver/pulls/603"}}},"pull_request":{"url":"https://api.github.com/repos/metoppv/improver/pulls/603","id":201243808,"node_id":"MDExOlB1bGxSZXF1ZXN0MjAxMjQzODA4","html_url":"https://github.com/metoppv/improver/pull/603","diff_url":"https://github.com/metoppv/improver/pull/603.diff","patch_url":"https://github.com/metoppv/improver/pull/603.patch","issue_url":"https://api.github.com/repos/metoppv/improver/issues/603","number":603,"state":"open","locked":false,"title":"Added Lapse Rate code and basic test","user":{"login":"MarkWorsfold","id":35810969,"node_id":"MDQ6VXNlcjM1ODEwOTY5","avatar_url":"https://avatars2.githubusercontent.com/u/35810969?v=4","gravatar_id":"","url":"https://api.github.com/users/MarkWorsfold","html_url":"https://github.com/MarkWorsfold","followers_url":"https://api.github.com/users/MarkWorsfold/followers","following_url":"https://api.github.com/users/MarkWorsfold/following{/other_user}","gists_url":"https://api.github.com/users/MarkWorsfold/gists{/gist_id}","starred_url":"https://api.github.com/users/MarkWorsfold/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/MarkWorsfold/subscriptions","organizations_url":"https://api.github.com/users/MarkWorsfold/orgs","repos_url":"https://api.github.com/users/MarkWorsfold/repos","events_url":"https://api.github.com/users/MarkWorsfold/events{/privacy}","received_events_url":"https://api.github.com/users/MarkWorsfold/received_events","type":"User","site_admin":false},"body":"Addresses #GitHubissuenum\r\n\r\nDescription:\r\nCreated basic Lapse Rate code - there are unresolved questions which are highlighted in the doc string for the class.\r\nI have added an extremely basic unit test file, this is not intended to be the finished version. It is simply to allow the user to run the code themselves using a simplistic dataset.\r\n\r\nTesting:\r\n - [ x] Ran tests and they passed OK\r\n - [ x] Added new tests for the new feature(s)\r\n","created_at":"2018-07-13T10:00:32Z","updated_at":"2018-07-16T11:03:44Z","closed_at":null,"merged_at":null,"merge_commit_sha":"3dff5f530f616801853ab0aa4d152cc599d53507","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/metoppv/improver/pulls/603/commits","review_comments_url":"https://api.github.com/repos/metoppv/improver/pulls/603/comments","review_comment_url":"https://api.github.com/repos/metoppv/improver/pulls/comments{/number}","comments_url":"https://api.github.com/repos/metoppv/improver/issues/603/comments","statuses_url":"https://api.github.com/repos/metoppv/improver/statuses/ba98fc17f38fddbbda7eee28b42bd3a2df71d520","head":{"label":"MarkWorsfold:IMPRO_683","ref":"IMPRO_683","sha":"ba98fc17f38fddbbda7eee28b42bd3a2df71d520","user":{"login":"MarkWorsfold","id":35810969,"node_id":"MDQ6VXNlcjM1ODEwOTY5","avatar_url":"https://avatars2.githubusercontent.com/u/35810969?v=4","gravatar_id":"","url":"https://api.github.com/users/MarkWorsfold","html_url":"https://github.com/MarkWorsfold","followers_url":"https://api.github.com/users/MarkWorsfold/followers","following_url":"https://api.github.com/users/MarkWorsfold/following{/other_user}","gists_url":"https://api.github.com/users/MarkWorsfold/gists{/gist_id}","starred_url":"https://api.github.com/users/MarkWorsfold/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/MarkWorsfold/subscriptions","organizations_url":"https://api.github.com/users/MarkWorsfold/orgs","repos_url":"https://api.github.com/users/MarkWorsfold/repos","events_url":"https://api.github.com/users/MarkWorsfold/events{/privacy}","received_events_url":"https://api.github.com/users/MarkWorsfold/received_events","type":"User","site_admin":false},"repo":{"id":120636183,"node_id":"MDEwOlJlcG9zaXRvcnkxMjA2MzYxODM=","name":"improver","full_name":"MarkWorsfold/improver","owner":{"login":"MarkWorsfold","id":35810969,"node_id":"MDQ6VXNlcjM1ODEwOTY5","avatar_url":"https://avatars2.githubusercontent.com/u/35810969?v=4","gravatar_id":"","url":"https://api.github.com/users/MarkWorsfold","html_url":"https://github.com/MarkWorsfold","followers_url":"https://api.github.com/users/MarkWorsfold/followers","following_url":"https://api.github.com/users/MarkWorsfold/following{/other_user}","gists_url":"https://api.github.com/users/MarkWorsfold/gists{/gist_id}","starred_url":"https://api.github.com/users/MarkWorsfold/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/MarkWorsfold/subscriptions","organizations_url":"https://api.github.com/users/MarkWorsfold/orgs","repos_url":"https://api.github.com/users/MarkWorsfold/repos","events_url":"https://api.github.com/users/MarkWorsfold/events{/privacy}","received_events_url":"https://api.github.com/users/MarkWorsfold/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/MarkWorsfold/improver","description":"IMPROVER is a library of algorithms for meteorological post-processing and verification.","fork":true,"url":"https://api.github.com/repos/MarkWorsfold/improver","forks_url":"https://api.github.com/repos/MarkWorsfold/improver/forks","keys_url":"https://api.github.com/repos/MarkWorsfold/improver/keys{/key_id}","collaborators_url":"https://api.github.com/repos/MarkWorsfold/improver/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/MarkWorsfold/improver/teams","hooks_url":"https://api.github.com/repos/MarkWorsfold/improver/hooks","issue_events_url":"https://api.github.com/repos/MarkWorsfold/improver/issues/events{/number}","events_url":"https://api.github.com/repos/MarkWorsfold/improver/events","assignees_url":"https://api.github.com/repos/MarkWorsfold/improver/assignees{/user}","branches_url":"https://api.github.com/repos/MarkWorsfold/improver/branches{/branch}","tags_url":"https://api.github.com/repos/MarkWorsfold/improver/tags","blobs_url":"https://api.github.com/repos/MarkWorsfold/improver/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/MarkWorsfold/improver/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/MarkWorsfold/improver/git/refs{/sha}","trees_url":"https://api.github.com/repos/MarkWorsfold/improver/git/trees{/sha}","statuses_url":"https://api.github.com/repos/MarkWorsfold/improver/statuses/{sha}","languages_url":"https://api.github.com/repos/MarkWorsfold/improver/languages","stargazers_url":"https://api.github.com/repos/MarkWorsfold/improver/stargazers","contributors_url":"https://api.github.com/repos/MarkWorsfold/improver/contributors","subscribers_url":"https://api.github.com/repos/MarkWorsfold/improver/subscribers","subscription_url":"https://api.github.com/repos/MarkWorsfold/improver/subscription","commits_url":"https://api.github.com/repos/MarkWorsfold/improver/commits{/sha}","git_commits_url":"https://api.github.com/repos/MarkWorsfold/improver/git/commits{/sha}","comments_url":"https://api.github.com/repos/MarkWorsfold/improver/comments{/number}","issue_comment_url":"https://api.github.com/repos/MarkWorsfold/improver/issues/comments{/number}","contents_url":"https://api.github.com/repos/MarkWorsfold/improver/contents/{+path}","compare_url":"https://api.github.com/repos/MarkWorsfold/improver/compare/{base}...{head}","merges_url":"https://api.github.com/repos/MarkWorsfold/improver/merges","archive_url":"https://api.github.com/repos/MarkWorsfold/improver/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/MarkWorsfold/improver/downloads","issues_url":"https://api.github.com/repos/MarkWorsfold/improver/issues{/number}","pulls_url":"https://api.github.com/repos/MarkWorsfold/improver/pulls{/number}","milestones_url":"https://api.github.com/repos/MarkWorsfold/improver/milestones{/number}","notifications_url":"https://api.github.com/repos/MarkWorsfold/improver/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/MarkWorsfold/improver/labels{/name}","releases_url":"https://api.github.com/repos/MarkWorsfold/improver/releases{/id}","deployments_url":"https://api.github.com/repos/MarkWorsfold/improver/deployments","created_at":"2018-02-07T15:53:28Z","updated_at":"2018-02-07T15:53:30Z","pushed_at":"2018-07-13T09:54:43Z","git_url":"git://github.com/MarkWorsfold/improver.git","ssh_url":"git@github.com:MarkWorsfold/improver.git","clone_url":"https://github.com/MarkWorsfold/improver.git","svn_url":"https://github.com/MarkWorsfold/improver","homepage":"http://improver.readthedocs.io/en/latest/","size":3573,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"other","name":"Other","spdx_id":null,"url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"metoppv:master","ref":"master","sha":"0bdce4a95be28353302e38218dca4f7036fefaf1","user":{"login":"metoppv","id":26465485,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI2NDY1NDg1","avatar_url":"https://avatars2.githubusercontent.com/u/26465485?v=4","gravatar_id":"","url":"https://api.github.com/users/metoppv","html_url":"https://github.com/metoppv","followers_url":"https://api.github.com/users/metoppv/followers","following_url":"https://api.github.com/users/metoppv/following{/other_user}","gists_url":"https://api.github.com/users/metoppv/gists{/gist_id}","starred_url":"https://api.github.com/users/metoppv/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/metoppv/subscriptions","organizations_url":"https://api.github.com/users/metoppv/orgs","repos_url":"https://api.github.com/users/metoppv/repos","events_url":"https://api.github.com/users/metoppv/events{/privacy}","received_events_url":"https://api.github.com/users/metoppv/received_events","type":"Organization","site_admin":false},"repo":{"id":85334761,"node_id":"MDEwOlJlcG9zaXRvcnk4NTMzNDc2MQ==","name":"improver","full_name":"metoppv/improver","owner":{"login":"metoppv","id":26465485,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI2NDY1NDg1","avatar_url":"https://avatars2.githubusercontent.com/u/26465485?v=4","gravatar_id":"","url":"https://api.github.com/users/metoppv","html_url":"https://github.com/metoppv","followers_url":"https://api.github.com/users/metoppv/followers","following_url":"https://api.github.com/users/metoppv/following{/other_user}","gists_url":"https://api.github.com/users/metoppv/gists{/gist_id}","starred_url":"https://api.github.com/users/metoppv/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/metoppv/subscriptions","organizations_url":"https://api.github.com/users/metoppv/orgs","repos_url":"https://api.github.com/users/metoppv/repos","events_url":"https://api.github.com/users/metoppv/events{/privacy}","received_events_url":"https://api.github.com/users/metoppv/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/metoppv/improver","description":"IMPROVER is a library of algorithms for meteorological post-processing and verification.","fork":false,"url":"https://api.github.com/repos/metoppv/improver","forks_url":"https://api.github.com/repos/metoppv/improver/forks","keys_url":"https://api.github.com/repos/metoppv/improver/keys{/key_id}","collaborators_url":"https://api.github.com/repos/metoppv/improver/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/metoppv/improver/teams","hooks_url":"https://api.github.com/repos/metoppv/improver/hooks","issue_events_url":"https://api.github.com/repos/metoppv/improver/issues/events{/number}","events_url":"https://api.github.com/repos/metoppv/improver/events","assignees_url":"https://api.github.com/repos/metoppv/improver/assignees{/user}","branches_url":"https://api.github.com/repos/metoppv/improver/branches{/branch}","tags_url":"https://api.github.com/repos/metoppv/improver/tags","blobs_url":"https://api.github.com/repos/metoppv/improver/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/metoppv/improver/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/metoppv/improver/git/refs{/sha}","trees_url":"https://api.github.com/repos/metoppv/improver/git/trees{/sha}","statuses_url":"https://api.github.com/repos/metoppv/improver/statuses/{sha}","languages_url":"https://api.github.com/repos/metoppv/improver/languages","stargazers_url":"https://api.github.com/repos/metoppv/improver/stargazers","contributors_url":"https://api.github.com/repos/metoppv/improver/contributors","subscribers_url":"https://api.github.com/repos/metoppv/improver/subscribers","subscription_url":"https://api.github.com/repos/metoppv/improver/subscription","commits_url":"https://api.github.com/repos/metoppv/improver/commits{/sha}","git_commits_url":"https://api.github.com/repos/metoppv/improver/git/commits{/sha}","comments_url":"https://api.github.com/repos/metoppv/improver/comments{/number}","issue_comment_url":"https://api.github.com/repos/metoppv/improver/issues/comments{/number}","contents_url":"https://api.github.com/repos/metoppv/improver/contents/{+path}","compare_url":"https://api.github.com/repos/metoppv/improver/compare/{base}...{head}","merges_url":"https://api.github.com/repos/metoppv/improver/merges","archive_url":"https://api.github.com/repos/metoppv/improver/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/metoppv/improver/downloads","issues_url":"https://api.github.com/repos/metoppv/improver/issues{/number}","pulls_url":"https://api.github.com/repos/metoppv/improver/pulls{/number}","milestones_url":"https://api.github.com/repos/metoppv/improver/milestones{/number}","notifications_url":"https://api.github.com/repos/metoppv/improver/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/metoppv/improver/labels{/name}","releases_url":"https://api.github.com/repos/metoppv/improver/releases{/id}","deployments_url":"https://api.github.com/repos/metoppv/improver/deployments","created_at":"2017-03-17T16:51:29Z","updated_at":"2018-07-13T11:51:47Z","pushed_at":"2018-07-16T11:01:57Z","git_url":"git://github.com/metoppv/improver.git","ssh_url":"git@github.com:metoppv/improver.git","clone_url":"https://github.com/metoppv/improver.git","svn_url":"https://github.com/metoppv/improver","homepage":"http://improver.readthedocs.io/en/latest/","size":3585,"stargazers_count":17,"watchers_count":17,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":28,"mirror_url":null,"archived":false,"open_issues_count":112,"license":{"key":"other","name":"Other","spdx_id":null,"url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":28,"open_issues":112,"watchers":17,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/metoppv/improver/pulls/603"},"html":{"href":"https://github.com/metoppv/improver/pull/603"},"issue":{"href":"https://api.github.com/repos/metoppv/improver/issues/603"},"comments":{"href":"https://api.github.com/repos/metoppv/improver/issues/603/comments"},"review_comments":{"href":"https://api.github.com/repos/metoppv/improver/pulls/603/comments"},"review_comment":{"href":"https://api.github.com/repos/metoppv/improver/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/metoppv/improver/pulls/603/commits"},"statuses":{"href":"https://api.github.com/repos/metoppv/improver/statuses/ba98fc17f38fddbbda7eee28b42bd3a2df71d520"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"bayliffe"}}