GitHub PullRequestReviewCommentEvent at 2014-09-06 20:48:20
Repository: vispy
Actor: rossant
Payload: {"action":"created","comment":{"url":"https://api.github.com/repos/vispy/vispy/pulls/comments/17211241","id":17211241,"diff_hunk":"@@ -0,0 +1,427 @@\n+#!/usr/bin/env python\n+# -*- coding: utf-8 -*-\n+# vispy: gallery 2\n+# Copyright (c) 2014, Vispy Development Team.\n+# Distributed under the (new) BSD License. See LICENSE.txt for more info.\n+\n+\"\"\"\n+Shadertoy demo. You can copy-paste shader code from an example on\n+www.shadertoy.com and get the demo.\n+\n+TODO: support cubes and videos as channel inputs (currently, only images\n+are supported).\n+\n+\"\"\"\n+\n+from vispy import gloo\n+from vispy import app\n+from datetime import datetime, time\n+import numpy as np\n+from scipy.misc import imread\n+\n+\n+vertex = \"\"\"\n+#version 120\n+\n+attribute vec2 position;\n+void main()\n+{\n+    gl_Position = vec4(position, 0.0, 1.0);\n+}\n+\"\"\"\n+\n+fragment = \"\"\"\n+#version 120\n+\n+uniform vec3      iResolution;           // viewport resolution (in pixels)\n+uniform float     iGlobalTime;           // shader playback time (in seconds)\n+uniform vec4      iMouse;                // mouse pixel coords\n+uniform vec4      iDate;                 // (year, month, day, time in seconds)\n+uniform float     iSampleRate;           // sound sample rate (i.e., 44100)\n+uniform sampler2D iChannel0;             // input channel. XX = 2D/Cube\n+uniform sampler2D iChannel1;             // input channel. XX = 2D/Cube\n+uniform sampler2D iChannel2;             // input channel. XX = 2D/Cube\n+uniform sampler2D iChannel3;             // input channel. XX = 2D/Cube\n+uniform vec3      iChannelResolution[4]; // channel resolution (in pixels)\n+uniform float     iChannelTime[4];       // channel playback time (in seconds)\n+\n+%s\n+\"\"\"\n+\n+\n+def get_idate():\n+    now = datetime.now()\n+    utcnow = datetime.utcnow()\n+    midnight_utc = datetime.combine(utcnow.date(), time(0))\n+    delta = utcnow - midnight_utc\n+    return (now.year, now.month, now.day, delta.seconds)\n+\n+\n+def noise(resolution=64, nchannels=1):\n+    # Random texture.\n+    return np.random.randint(low=0, high=256, \n+                             size=(resolution, resolution, nchannels)\n+                             ).astype(np.uint8)\n+\n+\n+def load_image(path):\n+    # Load an image.\n+    im = imread(path)\n+    im = np.atleast_3d(im)\n+    return im\n+\n+\n+class Canvas(app.Canvas):\n+\n+    def __init__(self, shadertoy):\n+        app.Canvas.__init__(self, keys='interactive')\n+        self.program = gloo.Program(vertex, fragment % shadertoy)\n+\n+        self.program[\"position\"] = [(-1, -1), (-1, 1), (1, 1),\n+                                    (-1, -1), (1, 1), (1, -1)]\n+\n+        self.program['iSampleRate'] = 44100.\n+        for i in range(4):\n+            self.program['iChannelTime[%d]' % i] = 0.\n+        self._timer = app.Timer('auto', connect=self.on_timer, start=True)\n+\n+    def set_channel_input(self, img, i=0):\n+        tex = gloo.Texture2D(img)\n+        tex.interpolation = 'linear'\n+        tex.wrapping = 'repeat'\n+        self.program['iChannel%d' % i] = tex\n+        self.program['iChannelResolution[%d]' % i] = img.shape\n+        \n+    def on_draw(self, event):\n+        self.program.draw()\n+\n+    def on_mouse_click(self, event):\n+        # BUG: DOES NOT WORK YET, NO CLICK EVENT IN VISPY FOR NOW...\n+        imouse = event.pos + event.pos\n+        self.program['iMouse'] = imouse\n+\n+    def on_mouse_move(self, event):\n+        if event.is_dragging:\n+            x, y = event.pos\n+            px, py = event.press_event.pos\n+            imouse = (x, self.size[1] - y, px, self.size[1] - py)\n+            self.program['iMouse'] = imouse\n+        \n+    def on_timer(self, event):\n+        self.program['iGlobalTime'] = event.elapsed\n+        self.program['iDate'] = get_idate()\n+        self.update()\n+        \n+    def on_resize(self, event):\n+        width, height = event.size\n+        gloo.set_viewport(0, 0, width, height)\n+        self.program['iResolution'] = (width, height, 0.)\n+        \n+if __name__ == '__main__':\n+    # -------------------------------------------------------------------------\n+    # COPY-PASTE SHADERTOY CODE BELOW\n+    # -------------------------------------------------------------------------\n+    SHADERTOY = \"\"\"\n+    // From: https://www.shadertoy.com/view/MdX3Rr\n+    \n+    // Created by inigo quilez - iq/2013\n+    // License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 \n+    // Unported License.\n+\n+    //stereo thanks to Croqueteer\n+    //#define STEREO\n+\n+    // value noise, and its analytical derivatives\n+    vec3 noised( in vec2 x )\n+    {\n+        vec2 p = floor(x);\n+        vec2 f = fract(x);\n+\n+        vec2 u = f*f*(3.0-2.0*f);\n+\n+        float a = texture2D(iChannel0,(p+vec2(0.5,0.5))/256.0,-100.0).x;\n+        float b = texture2D(iChannel0,(p+vec2(1.5,0.5))/256.0,-100.0).x;\n+        float c = texture2D(iChannel0,(p+vec2(0.5,1.5))/256.0,-100.0).x;\n+        float d = texture2D(iChannel0,(p+vec2(1.5,1.5))/256.0,-100.0).x;\n+        \n+        return vec3(a+(b-a)*u.x+(c-a)*u.y+(a-b-c+d)*u.x*u.y,\n+                    6.0*f*(1.0-f)*(vec2(b-a,c-a)+(a-b-c+d)*u.yx));\n+    }\n+\n+    const mat2 m2 = mat2(0.8,-0.6,0.6,0.8);\n+\n+    float terrain( in vec2 x )\n+    {\n+        vec2  p = x*0.003;\n+        float a = 0.0;\n+        float b = 1.0;\n+        vec2  d = vec2(0.0);\n+        for( int i=0; i<6; i++ )\n+        {\n+            vec3 n = noised(p);\n+            d += n.yz;\n+            a += b*n.x/(1.0+dot(d,d));\n+            b *= 0.5;\n+            p = m2*p*2.0;\n+        }\n+\n+        return 140.0*a;\n+    }\n+\n+    float terrain2( in vec2 x )\n+    {\n+        vec2  p = x*0.003;\n+        float a = 0.0;\n+        float b = 1.0;\n+        vec2  d = vec2(0.0);\n+        for( int i=0; i<14; i++ )\n+        {\n+            vec3 n = noised(p);\n+            d += n.yz;\n+            a += b*n.x/(1.0+dot(d,d));\n+            b *= 0.5;\n+            p=m2*p*2.0;\n+        }\n+\n+        return 140.0*a;\n+    }\n+\n+    float terrain3( in vec2 x )\n+    {\n+        vec2  p = x*0.003;\n+        float a = 0.0;\n+        float b = 1.0;\n+        vec2  d = vec2(0.0);\n+        for( int i=0; i<4; i++ )\n+        {\n+            vec3 n = noised(p);\n+            d += n.yz;\n+            a += b*n.x/(1.0+dot(d,d));\n+            b *= 0.5;\n+            p = m2*p*2.0;\n+        }\n+\n+        return 140.0*a;\n+    }\n+\n+    float map( in vec3 p )\n+    {\n+        float h = terrain(p.xz);\n+        return p.y - h;\n+    }\n+\n+    float map2( in vec3 p )\n+    {\n+        float h = terrain2(p.xz);\n+        return p.y - h;\n+    }\n+\n+    float interesct( in vec3 ro, in vec3 rd )\n+    {\n+        float h = 1.0;\n+        float t = 1.0;\n+        for( int i=0; i<120; i++ )\n+        {\n+            if( h<0.01 || t>2000.0 ) break;\n+            t += 0.5*h;\n+            h = map( ro + t*rd );\n+        }\n+\n+        if( t>2000.0 ) t = -1.0;\n+        return t;\n+    }\n+\n+    float sinteresct(in vec3 ro, in vec3 rd )\n+    {\n+    #if 0\n+        // no shadows\t\n+        return 1.0;\n+    #endif\n+        \n+    #if 0\n+        // fake shadows\n+        vec3 nor;\n+        vec3  eps = vec3(20.0,0.0,0.0);\n+        nor.x = terrain3(ro.xz-eps.xy) - terrain3(ro.xz+eps.xy);\n+        nor.y = 1.0*eps.x;\n+        nor.z = terrain3(ro.xz-eps.yx) - terrain3(ro.xz+eps.yx);\n+        nor = normalize(nor);\n+        return clamp( 4.0*dot(nor,rd), 0.0, 1.0 );\n+    #endif\n+        \n+    #if 1\n+        // real shadows\t\n+        float res = 1.0;\n+        float t = 0.0;\n+        for( int j=0; j<48; j++ )\n+        {\n+            vec3 p = ro + t*rd;\n+            float h = map( p );\n+            res = min( res, 16.0*h/t );\n+            t += h;\n+            if( res<0.001 ||p.y>300.0 ) break;\n+        }\n+\n+        return clamp( res, 0.0, 1.0 );\n+    #endif\n+    }\n+\n+    vec3 calcNormal( in vec3 pos, float t )\n+    {\n+        float e = 0.001;\n+        e = 0.001*t;\n+        vec3  eps = vec3(e,0.0,0.0);\n+        vec3 nor;\n+    #if 0\n+        nor.x = map2(pos+eps.xyy) - map2(pos-eps.xyy);\n+        nor.y = map2(pos+eps.yxy) - map2(pos-eps.yxy);\n+        nor.z = map2(pos+eps.yyx) - map2(pos-eps.yyx);\n+    #else\n+        nor.x = terrain2(pos.xz-eps.xy) - terrain2(pos.xz+eps.xy);\n+        nor.y = 2.0*e;\n+        nor.z = terrain2(pos.xz-eps.yx) - terrain2(pos.xz+eps.yx);\n+    #endif\t\n+        return normalize(nor);\n+    }\n+\n+    vec3 camPath( float time )\n+    {\n+        vec2 p = 1100.0*vec2( cos(0.0+0.23*time), cos(1.5+0.21*time) );\n+\n+        return vec3( p.x, 0.0, p.y );\n+    }\n+\n+        \n+    float fbm( vec2 p )\n+    {\n+        float f = 0.0;\n+\n+        f += 0.5000*texture2D( iChannel0, p/256.0 ).x; p = m2*p*2.02;\n+        f += 0.2500*texture2D( iChannel0, p/256.0 ).x; p = m2*p*2.03;\n+        f += 0.1250*texture2D( iChannel0, p/256.0 ).x; p = m2*p*2.01;\n+        f += 0.0625*texture2D( iChannel0, p/256.0 ).x;\n+\n+        return f/0.9375;\n+    }\n+\n+\n+    void main(void)\n+    {\n+        vec2 xy = -1.0 + 2.0*gl_FragCoord.xy / iResolution.xy;\n+\n+        vec2 s = xy*vec2(iResolution.x/iResolution.y,1.0);\n+\n+        #ifdef STEREO\n+        float isCyan = mod(gl_FragCoord.x + mod(gl_FragCoord.y,2.0),2.0);\n+        #endif\n+        \n+        float time = iGlobalTime*0.15 + 0.3 + 4.0*iMouse.x/iResolution.x;\n+        \n+        vec3 light1 = normalize( vec3(-0.8,0.4,-0.3) );\n+        \n+\n+\n+        vec3 ro = camPath( time );\n+        vec3 ta = camPath( time + 3.0 );\n+        ro.y = terrain3( ro.xz ) + 11.0;\n+        ta.y = ro.y - 20.0;\n+\n+        float cr = 0.2*cos(0.1*time);\n+        vec3  cw = normalize(ta-ro);\n+        vec3  cp = vec3(sin(cr), cos(cr),0.0);\n+        vec3  cu = normalize( cross(cw,cp) );\n+        vec3  cv = normalize( cross(cu,cw) );\n+        vec3  rd = normalize( s.x*cu + s.y*cv + 2.0*cw );\n+\n+        #ifdef STEREO\n+        ro += 2.0*cu*isCyan;\n+        #endif\n+\n+        float sundot = clamp(dot(rd,light1),0.0,1.0);\n+        vec3 col;\n+        float t = interesct( ro, rd );\n+        if( t<0.0 )\n+        {\n+            // sky\t\t\n+            col = vec3(0.3,.55,0.8)*(1.0-0.8*rd.y);\n+            col += 0.25*vec3(1.0,0.7,0.4)*pow( sundot,5.0 );\n+            col += 0.25*vec3(1.0,0.8,0.6)*pow( sundot,64.0 );\n+            col += 0.2*vec3(1.0,0.8,0.6)*pow( sundot,512.0 );\n+            vec2 sc = ro.xz + rd.xz*(1000.0-ro.y)/rd.y;\n+            col = mix( col, vec3(1.0,0.95,1.0), \n+                0.5*smoothstep(0.5,0.8,fbm(0.0005*sc)) );\n+        }\n+        else\n+        {\n+            // mountains\t\t\n+            vec3 pos = ro + t*rd;\n+\n+            vec3 nor = calcNormal( pos, t );\n+\n+            float r = texture2D( iChannel0, 7.0*pos.xz/256.0 ).x;\n+\n+            col = (r*0.25+0.75)*0.9*mix( vec3(0.08,0.05,0.03), \n+                vec3(0.10,0.09,0.08), texture2D(iChannel0,0.00007*vec2(\n+                    pos.x,pos.y*48.0)).x );\n+            col = mix( col, 0.20*vec3(0.45,.30,0.15)*(0.50+0.50*r),\n+                smoothstep(0.70,0.9,nor.y) );\n+            col = mix( col, 0.15*vec3(0.30,.30,0.10)*(0.25+0.75*r),\n+                smoothstep(0.95,1.0,nor.y) );\n+\n+            // snow\n+            float h = smoothstep(55.0,80.0,pos.y + 25.0*fbm(0.01*pos.xz) );\n+            float e = smoothstep(1.0-0.5*h,1.0-0.1*h,nor.y);\n+            float o = 0.3 + 0.7*smoothstep(0.0,0.1,nor.x+h*h);\n+            float s = h*e*o;\n+            col = mix( col, 0.29*vec3(0.62,0.65,0.7), smoothstep( \n+                0.1, 0.9, s ) );\n+            \n+             // lighting\t\t\n+            float amb = clamp(0.5+0.5*nor.y,0.0,1.0);\n+            float dif = clamp( dot( light1, nor ), 0.0, 1.0 );\n+            float bac = clamp( 0.2 + 0.8*dot( normalize( \n+                vec3(-light1.x, 0.0, light1.z ) ), nor ), 0.0, 1.0 );\n+            float sh = 1.0; if( dif>=0.0001 ) sh = sinteresct(\n+                pos+light1*20.0,light1);\n+            \n+            vec3 lin  = vec3(0.0);\n+            lin += dif*vec3(7.00,5.00,3.00)*vec3( sh, sh*sh*0.5+0.5*sh, \n+                sh*sh*0.8+0.2*sh );\n+            lin += amb*vec3(0.40,0.60,0.80)*1.5;\n+            lin += bac*vec3(0.40,0.50,0.60);\n+            col *= lin;\n+\n+            \n+            float fo = 1.0-exp(-0.0005*t);\n+            vec3 fco = 0.55*vec3(0.55,0.65,0.75) + 0.1*vec3(1.0,0.8,0.5)*pow( \n+                sundot, 4.0 );\n+            col = mix( col, fco, fo );\n+\n+            col += 0.3*vec3(1.0,0.8,0.4)*pow( sundot, \n+                        8.0 )*(1.0-exp(-0.002*t));\n+        }\n+\n+        col = pow(col,vec3(0.4545));\n+\n+        // vignetting\t\n+        col *= 0.5 + 0.5*pow( (xy.x+1.0)*(xy.y+1.0)*(xy.x-1.0)*(xy.y-1.0), \n+                             0.1 );\n+        \n+        #ifdef STEREO\t\n+        col *= vec3( isCyan, 1.0-isCyan, 1.0-isCyan );\t\n+        #endif\n+        \n+    //\tcol *= smoothstep( 0.0, 2.0, iGlobalTime );\n+\n+        gl_FragColor=vec4(col,1.0);\n+    }\n+    \"\"\"\n+    # -------------------------------------------------------------------------\n+    \n+    c = Canvas(SHADERTOY)","path":"examples/demo/gloo/shadertoy.py","position":null,"original_position":421,"commit_id":"aa7d82b80d53d650b4593dbef5e0e33fb7075ce6","original_commit_id":"b2ec9a72c4ed24d663c870671cd56fb6ddf4a627","user":{"login":"rossant","id":1942359,"avatar_url":"https://avatars.githubusercontent.com/u/1942359?v=2","gravatar_id":"2ad027f822fc288e132648d76d7e8031","url":"https://api.github.com/users/rossant","html_url":"https://github.com/rossant","followers_url":"https://api.github.com/users/rossant/followers","following_url":"https://api.github.com/users/rossant/following{/other_user}","gists_url":"https://api.github.com/users/rossant/gists{/gist_id}","starred_url":"https://api.github.com/users/rossant/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rossant/subscriptions","organizations_url":"https://api.github.com/users/rossant/orgs","repos_url":"https://api.github.com/users/rossant/repos","events_url":"https://api.github.com/users/rossant/events{/privacy}","received_events_url":"https://api.github.com/users/rossant/received_events","type":"User","site_admin":false},"body":"Ah, right :) done!","created_at":"2014-09-06T20:48:20Z","updated_at":"2014-09-06T20:48:20Z","html_url":"https://github.com/vispy/vispy/pull/540#discussion_r17211241","pull_request_url":"https://api.github.com/repos/vispy/vispy/pulls/540","_links":{"self":{"href":"https://api.github.com/repos/vispy/vispy/pulls/comments/17211241"},"html":{"href":"https://github.com/vispy/vispy/pull/540#discussion_r17211241"},"pull_request":{"href":"https://api.github.com/repos/vispy/vispy/pulls/540"}}},"pull_request":{"url":"https://api.github.com/repos/vispy/vispy/pulls/540","id":20850872,"html_url":"https://github.com/vispy/vispy/pull/540","diff_url":"https://github.com/vispy/vispy/pull/540.diff","patch_url":"https://github.com/vispy/vispy/pull/540.patch","issue_url":"https://api.github.com/repos/vispy/vispy/issues/540","number":540,"state":"open","locked":false,"title":"Add shadertoy example","user":{"login":"rossant","id":1942359,"avatar_url":"https://avatars.githubusercontent.com/u/1942359?v=2","gravatar_id":"2ad027f822fc288e132648d76d7e8031","url":"https://api.github.com/users/rossant","html_url":"https://github.com/rossant","followers_url":"https://api.github.com/users/rossant/followers","following_url":"https://api.github.com/users/rossant/following{/other_user}","gists_url":"https://api.github.com/users/rossant/gists{/gist_id}","starred_url":"https://api.github.com/users/rossant/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rossant/subscriptions","organizations_url":"https://api.github.com/users/rossant/orgs","repos_url":"https://api.github.com/users/rossant/repos","events_url":"https://api.github.com/users/rossant/events{/privacy}","received_events_url":"https://api.github.com/users/rossant/received_events","type":"User","site_admin":false},"body":"Closes #420.","created_at":"2014-09-06T17:07:13Z","updated_at":"2014-09-06T20:48:20Z","closed_at":null,"merged_at":null,"merge_commit_sha":"a7c6c74cc89f098f873a1f110fa2e3494c68a7d9","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/vispy/vispy/pulls/540/commits","review_comments_url":"https://api.github.com/repos/vispy/vispy/pulls/540/comments","review_comment_url":"https://api.github.com/repos/vispy/vispy/pulls/comments/{number}","comments_url":"https://api.github.com/repos/vispy/vispy/issues/540/comments","statuses_url":"https://api.github.com/repos/vispy/vispy/statuses/aa7d82b80d53d650b4593dbef5e0e33fb7075ce6","head":{"label":"rossant:shadertoy-example","ref":"shadertoy-example","sha":"aa7d82b80d53d650b4593dbef5e0e33fb7075ce6","user":{"login":"rossant","id":1942359,"avatar_url":"https://avatars.githubusercontent.com/u/1942359?v=2","gravatar_id":"2ad027f822fc288e132648d76d7e8031","url":"https://api.github.com/users/rossant","html_url":"https://github.com/rossant","followers_url":"https://api.github.com/users/rossant/followers","following_url":"https://api.github.com/users/rossant/following{/other_user}","gists_url":"https://api.github.com/users/rossant/gists{/gist_id}","starred_url":"https://api.github.com/users/rossant/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rossant/subscriptions","organizations_url":"https://api.github.com/users/rossant/orgs","repos_url":"https://api.github.com/users/rossant/repos","events_url":"https://api.github.com/users/rossant/events{/privacy}","received_events_url":"https://api.github.com/users/rossant/received_events","type":"User","site_admin":false},"repo":{"id":20727406,"name":"vispy","full_name":"rossant/vispy","owner":{"login":"rossant","id":1942359,"avatar_url":"https://avatars.githubusercontent.com/u/1942359?v=2","gravatar_id":"2ad027f822fc288e132648d76d7e8031","url":"https://api.github.com/users/rossant","html_url":"https://github.com/rossant","followers_url":"https://api.github.com/users/rossant/followers","following_url":"https://api.github.com/users/rossant/following{/other_user}","gists_url":"https://api.github.com/users/rossant/gists{/gist_id}","starred_url":"https://api.github.com/users/rossant/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rossant/subscriptions","organizations_url":"https://api.github.com/users/rossant/orgs","repos_url":"https://api.github.com/users/rossant/repos","events_url":"https://api.github.com/users/rossant/events{/privacy}","received_events_url":"https://api.github.com/users/rossant/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/rossant/vispy","description":"Main repository for Vispy","fork":true,"url":"https://api.github.com/repos/rossant/vispy","forks_url":"https://api.github.com/repos/rossant/vispy/forks","keys_url":"https://api.github.com/repos/rossant/vispy/keys{/key_id}","collaborators_url":"https://api.github.com/repos/rossant/vispy/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/rossant/vispy/teams","hooks_url":"https://api.github.com/repos/rossant/vispy/hooks","issue_events_url":"https://api.github.com/repos/rossant/vispy/issues/events{/number}","events_url":"https://api.github.com/repos/rossant/vispy/events","assignees_url":"https://api.github.com/repos/rossant/vispy/assignees{/user}","branches_url":"https://api.github.com/repos/rossant/vispy/branches{/branch}","tags_url":"https://api.github.com/repos/rossant/vispy/tags","blobs_url":"https://api.github.com/repos/rossant/vispy/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/rossant/vispy/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/rossant/vispy/git/refs{/sha}","trees_url":"https://api.github.com/repos/rossant/vispy/git/trees{/sha}","statuses_url":"https://api.github.com/repos/rossant/vispy/statuses/{sha}","languages_url":"https://api.github.com/repos/rossant/vispy/languages","stargazers_url":"https://api.github.com/repos/rossant/vispy/stargazers","contributors_url":"https://api.github.com/repos/rossant/vispy/contributors","subscribers_url":"https://api.github.com/repos/rossant/vispy/subscribers","subscription_url":"https://api.github.com/repos/rossant/vispy/subscription","commits_url":"https://api.github.com/repos/rossant/vispy/commits{/sha}","git_commits_url":"https://api.github.com/repos/rossant/vispy/git/commits{/sha}","comments_url":"https://api.github.com/repos/rossant/vispy/comments{/number}","issue_comment_url":"https://api.github.com/repos/rossant/vispy/issues/comments/{number}","contents_url":"https://api.github.com/repos/rossant/vispy/contents/{+path}","compare_url":"https://api.github.com/repos/rossant/vispy/compare/{base}...{head}","merges_url":"https://api.github.com/repos/rossant/vispy/merges","archive_url":"https://api.github.com/repos/rossant/vispy/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/rossant/vispy/downloads","issues_url":"https://api.github.com/repos/rossant/vispy/issues{/number}","pulls_url":"https://api.github.com/repos/rossant/vispy/pulls{/number}","milestones_url":"https://api.github.com/repos/rossant/vispy/milestones{/number}","notifications_url":"https://api.github.com/repos/rossant/vispy/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/rossant/vispy/labels{/name}","releases_url":"https://api.github.com/repos/rossant/vispy/releases{/id}","created_at":"2014-06-11T14:07:00Z","updated_at":"2014-07-24T18:33:34Z","pushed_at":"2014-09-06T20:48:05Z","git_url":"git://github.com/rossant/vispy.git","ssh_url":"git@github.com:rossant/vispy.git","clone_url":"https://github.com/rossant/vispy.git","svn_url":"https://github.com/rossant/vispy","homepage":"","size":6111,"stargazers_count":1,"watchers_count":1,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"forks_count":1,"mirror_url":null,"open_issues_count":0,"forks":1,"open_issues":0,"watchers":1,"default_branch":"master"}},"base":{"label":"vispy:master","ref":"master","sha":"45e4b8f5a154d85390de9b5e6358c672ee9e28a0","user":{"login":"vispy","id":3934254,"avatar_url":"https://avatars.githubusercontent.com/u/3934254?v=2","gravatar_id":"47bf7b9218948408c9b197107b484b1f","url":"https://api.github.com/users/vispy","html_url":"https://github.com/vispy","followers_url":"https://api.github.com/users/vispy/followers","following_url":"https://api.github.com/users/vispy/following{/other_user}","gists_url":"https://api.github.com/users/vispy/gists{/gist_id}","starred_url":"https://api.github.com/users/vispy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vispy/subscriptions","organizations_url":"https://api.github.com/users/vispy/orgs","repos_url":"https://api.github.com/users/vispy/repos","events_url":"https://api.github.com/users/vispy/events{/privacy}","received_events_url":"https://api.github.com/users/vispy/received_events","type":"Organization","site_admin":false},"repo":{"id":8935948,"name":"vispy","full_name":"vispy/vispy","owner":{"login":"vispy","id":3934254,"avatar_url":"https://avatars.githubusercontent.com/u/3934254?v=2","gravatar_id":"47bf7b9218948408c9b197107b484b1f","url":"https://api.github.com/users/vispy","html_url":"https://github.com/vispy","followers_url":"https://api.github.com/users/vispy/followers","following_url":"https://api.github.com/users/vispy/following{/other_user}","gists_url":"https://api.github.com/users/vispy/gists{/gist_id}","starred_url":"https://api.github.com/users/vispy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vispy/subscriptions","organizations_url":"https://api.github.com/users/vispy/orgs","repos_url":"https://api.github.com/users/vispy/repos","events_url":"https://api.github.com/users/vispy/events{/privacy}","received_events_url":"https://api.github.com/users/vispy/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/vispy/vispy","description":"Main repository for Vispy","fork":false,"url":"https://api.github.com/repos/vispy/vispy","forks_url":"https://api.github.com/repos/vispy/vispy/forks","keys_url":"https://api.github.com/repos/vispy/vispy/keys{/key_id}","collaborators_url":"https://api.github.com/repos/vispy/vispy/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/vispy/vispy/teams","hooks_url":"https://api.github.com/repos/vispy/vispy/hooks","issue_events_url":"https://api.github.com/repos/vispy/vispy/issues/events{/number}","events_url":"https://api.github.com/repos/vispy/vispy/events","assignees_url":"https://api.github.com/repos/vispy/vispy/assignees{/user}","branches_url":"https://api.github.com/repos/vispy/vispy/branches{/branch}","tags_url":"https://api.github.com/repos/vispy/vispy/tags","blobs_url":"https://api.github.com/repos/vispy/vispy/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/vispy/vispy/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/vispy/vispy/git/refs{/sha}","trees_url":"https://api.github.com/repos/vispy/vispy/git/trees{/sha}","statuses_url":"https://api.github.com/repos/vispy/vispy/statuses/{sha}","languages_url":"https://api.github.com/repos/vispy/vispy/languages","stargazers_url":"https://api.github.com/repos/vispy/vispy/stargazers","contributors_url":"https://api.github.com/repos/vispy/vispy/contributors","subscribers_url":"https://api.github.com/repos/vispy/vispy/subscribers","subscription_url":"https://api.github.com/repos/vispy/vispy/subscription","commits_url":"https://api.github.com/repos/vispy/vispy/commits{/sha}","git_commits_url":"https://api.github.com/repos/vispy/vispy/git/commits{/sha}","comments_url":"https://api.github.com/repos/vispy/vispy/comments{/number}","issue_comment_url":"https://api.github.com/repos/vispy/vispy/issues/comments/{number}","contents_url":"https://api.github.com/repos/vispy/vispy/contents/{+path}","compare_url":"https://api.github.com/repos/vispy/vispy/compare/{base}...{head}","merges_url":"https://api.github.com/repos/vispy/vispy/merges","archive_url":"https://api.github.com/repos/vispy/vispy/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/vispy/vispy/downloads","issues_url":"https://api.github.com/repos/vispy/vispy/issues{/number}","pulls_url":"https://api.github.com/repos/vispy/vispy/pulls{/number}","milestones_url":"https://api.github.com/repos/vispy/vispy/milestones{/number}","notifications_url":"https://api.github.com/repos/vispy/vispy/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/vispy/vispy/labels{/name}","releases_url":"https://api.github.com/repos/vispy/vispy/releases{/id}","created_at":"2013-03-21T18:43:22Z","updated_at":"2014-09-06T19:16:22Z","pushed_at":"2014-09-06T18:23:50Z","git_url":"git://github.com/vispy/vispy.git","ssh_url":"git@github.com:vispy/vispy.git","clone_url":"https://github.com/vispy/vispy.git","svn_url":"https://github.com/vispy/vispy","homepage":"http://vispy.org","size":22150,"stargazers_count":221,"watchers_count":221,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"forks_count":38,"mirror_url":null,"open_issues_count":104,"forks":38,"open_issues":104,"watchers":221,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/vispy/vispy/pulls/540"},"html":{"href":"https://github.com/vispy/vispy/pull/540"},"issue":{"href":"https://api.github.com/repos/vispy/vispy/issues/540"},"comments":{"href":"https://api.github.com/repos/vispy/vispy/issues/540/comments"},"review_comments":{"href":"https://api.github.com/repos/vispy/vispy/pulls/540/comments"},"review_comment":{"href":"https://api.github.com/repos/vispy/vispy/pulls/comments/{number}"},"commits":{"href":"https://api.github.com/repos/vispy/vispy/pulls/540/commits"},"statuses":{"href":"https://api.github.com/repos/vispy/vispy/statuses/aa7d82b80d53d650b4593dbef5e0e33fb7075ce6"}}}}