{"action":"closed","number":135,"pull_request":{"url":"https://api.github.com/repos/OpenGeoscience/geonotebook/pulls/135","id":134669211,"node_id":"MDExOlB1bGxSZXF1ZXN0MTM0NjY5MjEx","html_url":"https://github.com/OpenGeoscience/geonotebook/pull/135","diff_url":"https://github.com/OpenGeoscience/geonotebook/pull/135.diff","patch_url":"https://github.com/OpenGeoscience/geonotebook/pull/135.patch","issue_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/issues/135","number":135,"state":"closed","locked":false,"title":"Allow TMS-served tiles to be displayed on the map","user":{"login":"jpolchlo","id":18410961,"node_id":"MDQ6VXNlcjE4NDEwOTYx","avatar_url":"https://avatars1.githubusercontent.com/u/18410961?v=4","gravatar_id":"","url":"https://api.github.com/users/jpolchlo","html_url":"https://github.com/jpolchlo","followers_url":"https://api.github.com/users/jpolchlo/followers","following_url":"https://api.github.com/users/jpolchlo/following{/other_user}","gists_url":"https://api.github.com/users/jpolchlo/gists{/gist_id}","starred_url":"https://api.github.com/users/jpolchlo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jpolchlo/subscriptions","organizations_url":"https://api.github.com/users/jpolchlo/orgs","repos_url":"https://api.github.com/users/jpolchlo/repos","events_url":"https://api.github.com/users/jpolchlo/events{/privacy}","received_events_url":"https://api.github.com/users/jpolchlo/received_events","type":"User","site_admin":false},"body":"This PR makes it possible to display map layers that are furnished by a remote service with a TMS-like web interface.  With this change, any data-handling back end that implements a simple protocol may display map data in the GeoNotebook web interface.\r\n\r\n_[Note: What we are calling \"TMS\" may not adhere strictly to the definition of a TMS server.  We'd like to name this interface in a way that is consistent with the community's conventions, such that we don't create confusion further down the line.  We'll take recommendations regarding the proper nomenclature to use.]_\r\n\r\nThe interface for the TMS server assumes a standard power-of-two pyramid established over the global extent using a WebMercator projection.  At zoom level n, there are 2^n partitions of the extent along each axis, indexed from 0 to 2^n-1, with the cartesian product of the two axes' partitions giving the space of (x, y) keys for which a tile may exist.  _[Note: At the moment, we index using the Google/Bing/OSM convention where (0, 0) corresponds to the extreme northwest tile.  If necessary, one could accommodate a flag to indicate that the tiles are being served in accordance with the TMS standard of an origin in the extreme southwest.]_\r\n\r\nTo add a TMS-provided layer, one needs to provide an object that adheres to the following simple interface:\r\n```python\r\nclass TMS:\r\n    def bind(self, host, port=None):\r\n        # binds a service to a host at a specified port (random port if port=None)\r\n        # subsequent calls to bind should fail until unbind is called\r\n    def unbind(self):\r\n        # stops the tile server from listening for further requests\r\n        # subsequent calls to bind to a new host/port may restart the service\r\n    @property\r\n    def host(self):\r\n        # the name of the host listening for tile requests\r\n    @property\r\n    def port(self):\r\n        # returns the port number the service is listening to requests on\r\n    @property\r\n    def url_pattern(self):\r\n        # returns a string template of the URL tile requests can be made on\r\n        # the special tokens {z}, {x}, and {y} should be used as placeholders \r\n        # for the zoom level and x and y coordinates, respectively\r\n```\r\nObjects that are duck-typed with this interface (provide these methods/properties) may be wrapped in a `TMSRasterData` (from `geonotebook.wrappers`) and passed to `M.add_layer` as per usual. The TMS server will be bound to a port at the time of creation; removing a TMS-backed layer will unbind the service.  _[Note: I have not implemented special handling of the standard styling options (e.g., opacity) and have no expectation that they will have any effect.  A subsequent PR could address this.]_","created_at":"2017-08-08T14:06:10Z","updated_at":"2018-07-16T13:09:40Z","closed_at":"2018-07-16T13:09:40Z","merged_at":null,"merge_commit_sha":"a6dd64a1b8d2fa64a239b6944d5ec0d3b18caa1e","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/pulls/135/commits","review_comments_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/pulls/135/comments","review_comment_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/pulls/comments{/number}","comments_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/issues/135/comments","statuses_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/statuses/542d6c677c794b68f7ba0762d30650e995d82b2b","head":{"label":"jpolchlo:feature/ktile-tms-extension","ref":"feature/ktile-tms-extension","sha":"542d6c677c794b68f7ba0762d30650e995d82b2b","user":{"login":"jpolchlo","id":18410961,"node_id":"MDQ6VXNlcjE4NDEwOTYx","avatar_url":"https://avatars1.githubusercontent.com/u/18410961?v=4","gravatar_id":"","url":"https://api.github.com/users/jpolchlo","html_url":"https://github.com/jpolchlo","followers_url":"https://api.github.com/users/jpolchlo/followers","following_url":"https://api.github.com/users/jpolchlo/following{/other_user}","gists_url":"https://api.github.com/users/jpolchlo/gists{/gist_id}","starred_url":"https://api.github.com/users/jpolchlo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jpolchlo/subscriptions","organizations_url":"https://api.github.com/users/jpolchlo/orgs","repos_url":"https://api.github.com/users/jpolchlo/repos","events_url":"https://api.github.com/users/jpolchlo/events{/privacy}","received_events_url":"https://api.github.com/users/jpolchlo/received_events","type":"User","site_admin":false},"repo":{"id":90065363,"node_id":"MDEwOlJlcG9zaXRvcnk5MDA2NTM2Mw==","name":"geonotebook","full_name":"jpolchlo/geonotebook","owner":{"login":"jpolchlo","id":18410961,"node_id":"MDQ6VXNlcjE4NDEwOTYx","avatar_url":"https://avatars1.githubusercontent.com/u/18410961?v=4","gravatar_id":"","url":"https://api.github.com/users/jpolchlo","html_url":"https://github.com/jpolchlo","followers_url":"https://api.github.com/users/jpolchlo/followers","following_url":"https://api.github.com/users/jpolchlo/following{/other_user}","gists_url":"https://api.github.com/users/jpolchlo/gists{/gist_id}","starred_url":"https://api.github.com/users/jpolchlo/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jpolchlo/subscriptions","organizations_url":"https://api.github.com/users/jpolchlo/orgs","repos_url":"https://api.github.com/users/jpolchlo/repos","events_url":"https://api.github.com/users/jpolchlo/events{/privacy}","received_events_url":"https://api.github.com/users/jpolchlo/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/jpolchlo/geonotebook","description":"A Jupyter notebook extension for geospatial visualization and analysis","fork":true,"url":"https://api.github.com/repos/jpolchlo/geonotebook","forks_url":"https://api.github.com/repos/jpolchlo/geonotebook/forks","keys_url":"https://api.github.com/repos/jpolchlo/geonotebook/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jpolchlo/geonotebook/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jpolchlo/geonotebook/teams","hooks_url":"https://api.github.com/repos/jpolchlo/geonotebook/hooks","issue_events_url":"https://api.github.com/repos/jpolchlo/geonotebook/issues/events{/number}","events_url":"https://api.github.com/repos/jpolchlo/geonotebook/events","assignees_url":"https://api.github.com/repos/jpolchlo/geonotebook/assignees{/user}","branches_url":"https://api.github.com/repos/jpolchlo/geonotebook/branches{/branch}","tags_url":"https://api.github.com/repos/jpolchlo/geonotebook/tags","blobs_url":"https://api.github.com/repos/jpolchlo/geonotebook/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jpolchlo/geonotebook/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jpolchlo/geonotebook/git/refs{/sha}","trees_url":"https://api.github.com/repos/jpolchlo/geonotebook/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jpolchlo/geonotebook/statuses/{sha}","languages_url":"https://api.github.com/repos/jpolchlo/geonotebook/languages","stargazers_url":"https://api.github.com/repos/jpolchlo/geonotebook/stargazers","contributors_url":"https://api.github.com/repos/jpolchlo/geonotebook/contributors","subscribers_url":"https://api.github.com/repos/jpolchlo/geonotebook/subscribers","subscription_url":"https://api.github.com/repos/jpolchlo/geonotebook/subscription","commits_url":"https://api.github.com/repos/jpolchlo/geonotebook/commits{/sha}","git_commits_url":"https://api.github.com/repos/jpolchlo/geonotebook/git/commits{/sha}","comments_url":"https://api.github.com/repos/jpolchlo/geonotebook/comments{/number}","issue_comment_url":"https://api.github.com/repos/jpolchlo/geonotebook/issues/comments{/number}","contents_url":"https://api.github.com/repos/jpolchlo/geonotebook/contents/{+path}","compare_url":"https://api.github.com/repos/jpolchlo/geonotebook/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jpolchlo/geonotebook/merges","archive_url":"https://api.github.com/repos/jpolchlo/geonotebook/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jpolchlo/geonotebook/downloads","issues_url":"https://api.github.com/repos/jpolchlo/geonotebook/issues{/number}","pulls_url":"https://api.github.com/repos/jpolchlo/geonotebook/pulls{/number}","milestones_url":"https://api.github.com/repos/jpolchlo/geonotebook/milestones{/number}","notifications_url":"https://api.github.com/repos/jpolchlo/geonotebook/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jpolchlo/geonotebook/labels{/name}","releases_url":"https://api.github.com/repos/jpolchlo/geonotebook/releases{/id}","deployments_url":"https://api.github.com/repos/jpolchlo/geonotebook/deployments","created_at":"2017-05-02T18:30:10Z","updated_at":"2017-12-10T02:36:16Z","pushed_at":"2017-09-27T16:39:54Z","git_url":"git://github.com/jpolchlo/geonotebook.git","ssh_url":"git@github.com:jpolchlo/geonotebook.git","clone_url":"https://github.com/jpolchlo/geonotebook.git","svn_url":"https://github.com/jpolchlo/geonotebook","homepage":"","size":15199,"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":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"OpenGeoscience:master","ref":"master","sha":"c5c39b0f434c596e07e2751a5f4cdb16f2f82a48","user":{"login":"OpenGeoscience","id":3434706,"node_id":"MDEyOk9yZ2FuaXphdGlvbjM0MzQ3MDY=","avatar_url":"https://avatars1.githubusercontent.com/u/3434706?v=4","gravatar_id":"","url":"https://api.github.com/users/OpenGeoscience","html_url":"https://github.com/OpenGeoscience","followers_url":"https://api.github.com/users/OpenGeoscience/followers","following_url":"https://api.github.com/users/OpenGeoscience/following{/other_user}","gists_url":"https://api.github.com/users/OpenGeoscience/gists{/gist_id}","starred_url":"https://api.github.com/users/OpenGeoscience/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/OpenGeoscience/subscriptions","organizations_url":"https://api.github.com/users/OpenGeoscience/orgs","repos_url":"https://api.github.com/users/OpenGeoscience/repos","events_url":"https://api.github.com/users/OpenGeoscience/events{/privacy}","received_events_url":"https://api.github.com/users/OpenGeoscience/received_events","type":"Organization","site_admin":false},"repo":{"id":64249762,"node_id":"MDEwOlJlcG9zaXRvcnk2NDI0OTc2Mg==","name":"geonotebook","full_name":"OpenGeoscience/geonotebook","owner":{"login":"OpenGeoscience","id":3434706,"node_id":"MDEyOk9yZ2FuaXphdGlvbjM0MzQ3MDY=","avatar_url":"https://avatars1.githubusercontent.com/u/3434706?v=4","gravatar_id":"","url":"https://api.github.com/users/OpenGeoscience","html_url":"https://github.com/OpenGeoscience","followers_url":"https://api.github.com/users/OpenGeoscience/followers","following_url":"https://api.github.com/users/OpenGeoscience/following{/other_user}","gists_url":"https://api.github.com/users/OpenGeoscience/gists{/gist_id}","starred_url":"https://api.github.com/users/OpenGeoscience/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/OpenGeoscience/subscriptions","organizations_url":"https://api.github.com/users/OpenGeoscience/orgs","repos_url":"https://api.github.com/users/OpenGeoscience/repos","events_url":"https://api.github.com/users/OpenGeoscience/events{/privacy}","received_events_url":"https://api.github.com/users/OpenGeoscience/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/OpenGeoscience/geonotebook","description":"A Jupyter notebook extension for geospatial visualization and analysis","fork":false,"url":"https://api.github.com/repos/OpenGeoscience/geonotebook","forks_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/forks","keys_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/keys{/key_id}","collaborators_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/teams","hooks_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/hooks","issue_events_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/issues/events{/number}","events_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/events","assignees_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/assignees{/user}","branches_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/branches{/branch}","tags_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/tags","blobs_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/git/refs{/sha}","trees_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/git/trees{/sha}","statuses_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/statuses/{sha}","languages_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/languages","stargazers_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/stargazers","contributors_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/contributors","subscribers_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/subscribers","subscription_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/subscription","commits_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/commits{/sha}","git_commits_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/git/commits{/sha}","comments_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/comments{/number}","issue_comment_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/issues/comments{/number}","contents_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/contents/{+path}","compare_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/compare/{base}...{head}","merges_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/merges","archive_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/downloads","issues_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/issues{/number}","pulls_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/pulls{/number}","milestones_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/milestones{/number}","notifications_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/labels{/name}","releases_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/releases{/id}","deployments_url":"https://api.github.com/repos/OpenGeoscience/geonotebook/deployments","created_at":"2016-07-26T19:48:45Z","updated_at":"2018-07-16T08:12:12Z","pushed_at":"2018-07-14T20:30:41Z","git_url":"git://github.com/OpenGeoscience/geonotebook.git","ssh_url":"git@github.com:OpenGeoscience/geonotebook.git","clone_url":"https://github.com/OpenGeoscience/geonotebook.git","svn_url":"https://github.com/OpenGeoscience/geonotebook","homepage":"","size":14869,"stargazers_count":774,"watchers_count":774,"language":"Python","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":88,"mirror_url":null,"archived":false,"open_issues_count":35,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":88,"open_issues":35,"watchers":774,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/OpenGeoscience/geonotebook/pulls/135"},"html":{"href":"https://github.com/OpenGeoscience/geonotebook/pull/135"},"issue":{"href":"https://api.github.com/repos/OpenGeoscience/geonotebook/issues/135"},"comments":{"href":"https://api.github.com/repos/OpenGeoscience/geonotebook/issues/135/comments"},"review_comments":{"href":"https://api.github.com/repos/OpenGeoscience/geonotebook/pulls/135/comments"},"review_comment":{"href":"https://api.github.com/repos/OpenGeoscience/geonotebook/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/OpenGeoscience/geonotebook/pulls/135/commits"},"statuses":{"href":"https://api.github.com/repos/OpenGeoscience/geonotebook/statuses/542d6c677c794b68f7ba0762d30650e995d82b2b"}},"author_association":"NONE","merged":false,"mergeable":false,"rebaseable":false,"mergeable_state":"dirty","merged_by":null,"comments":6,"review_comments":9,"maintainer_can_modify":false,"commits":76,"additions":496,"deletions":103,"changed_files":11}}
{"actor":{"display_login":"jpolchlo"}}