{"action":"created","issue":{"url":"https://api.github.com/repos/nengo/nengo-gui/issues/965","repository_url":"https://api.github.com/repos/nengo/nengo-gui","labels_url":"https://api.github.com/repos/nengo/nengo-gui/issues/965/labels{/name}","comments_url":"https://api.github.com/repos/nengo/nengo-gui/issues/965/comments","events_url":"https://api.github.com/repos/nengo/nengo-gui/issues/965/events","html_url":"https://github.com/nengo/nengo-gui/pull/965","id":327963670,"node_id":"MDExOlB1bGxSZXF1ZXN0MTkxNjIzMTY1","number":965,"title":"Added hooks registered per model","user":{"login":"tcstewar","id":2380772,"node_id":"MDQ6VXNlcjIzODA3NzI=","avatar_url":"https://avatars3.githubusercontent.com/u/2380772?v=4","gravatar_id":"","url":"https://api.github.com/users/tcstewar","html_url":"https://github.com/tcstewar","followers_url":"https://api.github.com/users/tcstewar/followers","following_url":"https://api.github.com/users/tcstewar/following{/other_user}","gists_url":"https://api.github.com/users/tcstewar/gists{/gist_id}","starred_url":"https://api.github.com/users/tcstewar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tcstewar/subscriptions","organizations_url":"https://api.github.com/users/tcstewar/orgs","repos_url":"https://api.github.com/users/tcstewar/repos","events_url":"https://api.github.com/users/tcstewar/events{/privacy}","received_events_url":"https://api.github.com/users/tcstewar/received_events","type":"User","site_admin":false},"labels":[{"id":213937520,"node_id":"MDU6TGFiZWwyMTM5Mzc1MjA=","url":"https://api.github.com/repos/nengo/nengo-gui/labels/work%20in%20progress","name":"work in progress","color":"fbca04","default":false}],"state":"open","locked":false,"assignee":{"login":"jgosmann","id":850157,"node_id":"MDQ6VXNlcjg1MDE1Nw==","avatar_url":"https://avatars3.githubusercontent.com/u/850157?v=4","gravatar_id":"","url":"https://api.github.com/users/jgosmann","html_url":"https://github.com/jgosmann","followers_url":"https://api.github.com/users/jgosmann/followers","following_url":"https://api.github.com/users/jgosmann/following{/other_user}","gists_url":"https://api.github.com/users/jgosmann/gists{/gist_id}","starred_url":"https://api.github.com/users/jgosmann/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jgosmann/subscriptions","organizations_url":"https://api.github.com/users/jgosmann/orgs","repos_url":"https://api.github.com/users/jgosmann/repos","events_url":"https://api.github.com/users/jgosmann/events{/privacy}","received_events_url":"https://api.github.com/users/jgosmann/received_events","type":"User","site_admin":false},"assignees":[{"login":"jgosmann","id":850157,"node_id":"MDQ6VXNlcjg1MDE1Nw==","avatar_url":"https://avatars3.githubusercontent.com/u/850157?v=4","gravatar_id":"","url":"https://api.github.com/users/jgosmann","html_url":"https://github.com/jgosmann","followers_url":"https://api.github.com/users/jgosmann/followers","following_url":"https://api.github.com/users/jgosmann/following{/other_user}","gists_url":"https://api.github.com/users/jgosmann/gists{/gist_id}","starred_url":"https://api.github.com/users/jgosmann/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jgosmann/subscriptions","organizations_url":"https://api.github.com/users/jgosmann/orgs","repos_url":"https://api.github.com/users/jgosmann/repos","events_url":"https://api.github.com/users/jgosmann/events{/privacy}","received_events_url":"https://api.github.com/users/jgosmann/received_events","type":"User","site_admin":false}],"milestone":null,"comments":10,"created_at":"2018-05-31T01:45:54Z","updated_at":"2018-06-11T22:17:01Z","closed_at":null,"author_association":"CONTRIBUTOR","pull_request":{"url":"https://api.github.com/repos/nengo/nengo-gui/pulls/965","html_url":"https://github.com/nengo/nengo-gui/pull/965","diff_url":"https://github.com/nengo/nengo-gui/pull/965.diff","patch_url":"https://github.com/nengo/nengo-gui/pull/965.patch"},"body":"This is another implementation of hooks (see #957 and #953 for the previous attempts).  \r\n\r\nIn #953 , the hooks were implemented by just having magic variables `on_step`, `on_pause`, etc, and if you happened to define these, then the GUI would call them.  However, this is a) rather magical, and b) rather non-discoverable, and c) rather annoying to debug if you're using a branch that doesn't support them.\r\n\r\nSo, @jgosmann implemented a decorator-based approach.  It interacted with the ExecutionEnvironment system in nengo_gui to figure out which model we should be attaching the hook to (since we might have multiple pages open looking at different models).  This works great.  However, if we run outside of the ExecutionEnvironment (which happens when embedding inside Jupyter notebooks), then the hooks are attached globally.  This is fine for multiple open notebooks (since those are run in different kernels), but if there are multiple cells in the notebook that use nengo_gui, or if you re-execute a cell that uses hooks, then you will now have the same hook running multiple times.\r\n\r\nIn this PR, I do the decorator registration approach, but you also have to specify the model (i.e. the `nengo.Network` instance) that you're attaching the hook to.  This means we don't have to do anything with the ExecutionEnvironment, and it works fine and consistently in both normal nengo_gui and in Jupyter notebooks.\r\n\r\nThe syntax for this hook system is as follows:\r\n\r\n```python\r\nmodel = nengo.Network()\r\n\r\n@nengo_gui.hooks.on_start(model)\r\ndef on_start(sim):\r\n    print('Start')\r\n    \r\n@nengo_gui.hooks.on_close(model)\r\ndef on_close(sim):\r\n    print('Close')\r\n    \r\n@nengo_gui.hooks.on_pause(model)\r\ndef on_pause(sim):\r\n    print('Pause')\r\n    \r\n@nengo_gui.hooks.on_continue(model)\r\ndef on_continue(sim):\r\n    print('Continue')\r\n    \r\n@nengo_gui.hooks.on_step(model)\r\ndef on_step(sim):\r\n    print('Step')\r\n```"},"comment":{"url":"https://api.github.com/repos/nengo/nengo-gui/issues/comments/396404852","html_url":"https://github.com/nengo/nengo-gui/pull/965#issuecomment-396404852","issue_url":"https://api.github.com/repos/nengo/nengo-gui/issues/965","id":396404852,"node_id":"MDEyOklzc3VlQ29tbWVudDM5NjQwNDg1Mg==","user":{"login":"tcstewar","id":2380772,"node_id":"MDQ6VXNlcjIzODA3NzI=","avatar_url":"https://avatars3.githubusercontent.com/u/2380772?v=4","gravatar_id":"","url":"https://api.github.com/users/tcstewar","html_url":"https://github.com/tcstewar","followers_url":"https://api.github.com/users/tcstewar/followers","following_url":"https://api.github.com/users/tcstewar/following{/other_user}","gists_url":"https://api.github.com/users/tcstewar/gists{/gist_id}","starred_url":"https://api.github.com/users/tcstewar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tcstewar/subscriptions","organizations_url":"https://api.github.com/users/tcstewar/orgs","repos_url":"https://api.github.com/users/tcstewar/repos","events_url":"https://api.github.com/users/tcstewar/events{/privacy}","received_events_url":"https://api.github.com/users/tcstewar/received_events","type":"User","site_admin":false},"created_at":"2018-06-11T22:17:01Z","updated_at":"2018-06-11T22:17:01Z","author_association":"CONTRIBUTOR","body":"> If I'm in a notebook and I say that I want something to happen when I press \"play\", I expect that to happen for all the GUI cells in the notebook.\r\n\r\nI'm having difficulty coming up with generic things I would want to have happen based on GUI events, rather than model-specific things.  Usually I'm doing things like updating plots based on data from the simulator, or sending a motor command to stop a particular motor that this particular model controls, or opening/closing an i/o connection that this model needs to run.  Are there other use cases that people have in mind?\r\n\r\nMaybe my problem here is that I called these things \"hooks\", which is leading people to think they are generic across whatever model you're working with.  What I really want is I want to be able to say \"hey, when running this model, do this extra thing based on the GUI state\".  Is there a better name for that than \"hooks\"?  Because it never crossed my mind during the entire development process that someone might want this to be generic across a bunch of different models within a notebook."}}
{"actor":{"display_login":"tcstewar"}}