{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# idr0001: Sysgro\n", "\n", "<a href=\"https://idr.openmicroscopy.org/webclient/?show=screen-3\">Sysgro screen</a>\n", "<table><tr>\n", "<td>A quick look at one of the studies in the IDR, Sysgro.</td>\n", "<td><img src=\"https://idr.openmicroscopy.org/webclient/render_image/1230601/6/0/?c=1|50:300$00FF00,2|100:800$0000FF&m=c&p=normal&ia=0&q=0.9\" width=\"200px\"/></td>\n", "<td><img src=\"https://idr.openmicroscopy.org/webclient/render_image/1232528/6/0/?c=1|50:300$00FF00,2|100:800$0000FF&m=c&p=normal&ia=0&q=0.9\" width=\"200px\"/></td>\n", "<td><img src=\"https://idr.openmicroscopy.org/webclient/render_image/1275942/6/0/?c=1|50:300$00FF00,2|100:800$0000FF&m=c&p=normal&ia=0&q=0.9\" width=\"200px\"/></td>\n", "</tr></table>" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Dependencies\n", "\n", " * [Matplotlib](https://matplotlib.org/)\n", " * [NumPy](https://www.numpy.org/)" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import matplotlib\n", "import numpy as np\n", "import matplotlib.pyplot as plt\n", "import matplotlib.cm as cm\n", "import matplotlib.patches as mpatches\n", "\n", "matplotlib.rcParams['figure.figsize'] = (12.0, 8.0)\n", "\n", "from idr import connection" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": true }, "outputs": [], "source": [ "screen = \"idr0001-graml-sysgro/screenA\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Connect to the IDR server" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": true }, "outputs": [], "source": [ "conn = connection()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Load information about Sysgro" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": true }, "outputs": [], "source": [ "idr0001 = [x for x in conn.listScreens(2) if x.name == screen][0]" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "u'idr0001-graml-sysgro/screenA'" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "idr0001.name" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Publication Title\n", "A Genomic Multiprocess Survey of Machineries that Control and Link Cell Shape, Microtubule Organization, and Cell-Cycle Progression\n", "\n", "Screen Description\n", "Primary screen of fission yeast knock out mutants looking for genes controlling cell shape, microtubules, and cell-cycle progression. 262 genes controlling specific aspects of those processes are identifed, validated, and functionally annotated.\n" ] } ], "source": [ "print idr0001.description" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", " PubMed ID: 25373780 http://www.ncbi.nlm.nih.gov/pubmed/25373780\n", " Authors: Graml V, Studera X, Lawson JL, Chessel A, Geymonat M, Bortfeld-Miller M, Walter T, Wagstaff L, Piddini E, Carazo-Salas RE.\n", " Imaging Method: spinning disk confocal microscopy\n", "\n" ] } ], "source": [ "annotations = idr0001.getAnnotation().getMapValueAsMap()\n", "print \"\"\"\n", " PubMed ID: %(PubMed ID)s\n", " Authors: %(Publication Authors)s\n", " Imaging Method: %(Imaging Method)s\n", "\"\"\" % annotations" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Plates: 192\n", "Images: 109728\n" ] } ], "source": [ "plates = 0\n", "images = 0\n", "for plate in idr0001.listChildren():\n", " plates += 1\n", " for well in plate.listChildren():\n", " images += len(list(well.listChildren()))\n", "print \"Plates:\", plates\n", "print \"Images:\", images" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": true, "scrolled": true }, "outputs": [], "source": [ "total = None\n", "for plate in idr0001.listChildren():\n", " grid = plate.getWellGrid()\n", " single = np.zeros((len(grid), len(grid[0])))\n", " if total is None:\n", " total = np.zeros((len(grid), len(grid[0])))\n", " for x, row in enumerate(grid):\n", " for y, col in enumerate(row):\n", " single[x][y] = grid[x][y].getImage().getROICount()\n", " total += single\n", " break # Continue to tally all ROIs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Disconnect when done loading data" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": true }, "outputs": [], "source": [ "conn.close()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Display results" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [ { "data": { "application/javascript": [ "/* Put everything inside the global mpl namespace */\n", "window.mpl = {};\n", "\n", "\n", "mpl.get_websocket_type = function() {\n", " if (typeof(WebSocket) !== 'undefined') {\n", " return WebSocket;\n", " } else if (typeof(MozWebSocket) !== 'undefined') {\n", " return MozWebSocket;\n", " } else {\n", " alert('Your browser does not have WebSocket support.' +\n", " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", " 'Firefox 4 and 5 are also supported but you ' +\n", " 'have to enable WebSockets in about:config.');\n", " };\n", "}\n", "\n", "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", " this.id = figure_id;\n", "\n", " this.ws = websocket;\n", "\n", " this.supports_binary = (this.ws.binaryType != undefined);\n", "\n", " if (!this.supports_binary) {\n", " var warnings = document.getElementById(\"mpl-warnings\");\n", " if (warnings) {\n", " warnings.style.display = 'block';\n", " warnings.textContent = (\n", " \"This browser does not support binary websocket messages. \" +\n", " \"Performance may be slow.\");\n", " }\n", " }\n", "\n", " this.imageObj = new Image();\n", "\n", " this.context = undefined;\n", " this.message = undefined;\n", " this.canvas = undefined;\n", " this.rubberband_canvas = undefined;\n", " this.rubberband_context = undefined;\n", " this.format_dropdown = undefined;\n", "\n", " this.image_mode = 'full';\n", "\n", " this.root = $('<div/>');\n", " this._root_extra_style(this.root)\n", " this.root.attr('style', 'display: inline-block');\n", "\n", " $(parent_element).append(this.root);\n", "\n", " this._init_header(this);\n", " this._init_canvas(this);\n", " this._init_toolbar(this);\n", "\n", " var fig = this;\n", "\n", " this.waiting = false;\n", "\n", " this.ws.onopen = function () {\n", " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", " fig.send_message(\"send_image_mode\", {});\n", " if (mpl.ratio != 1) {\n", " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", " }\n", " fig.send_message(\"refresh\", {});\n", " }\n", "\n", " this.imageObj.onload = function() {\n", " if (fig.image_mode == 'full') {\n", " // Full images could contain transparency (where diff images\n", " // almost always do), so we need to clear the canvas so that\n", " // there is no ghosting.\n", " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", " }\n", " fig.context.drawImage(fig.imageObj, 0, 0);\n", " };\n", "\n", " this.imageObj.onunload = function() {\n", " this.ws.close();\n", " }\n", "\n", " this.ws.onmessage = this._make_on_message_function(this);\n", "\n", " this.ondownload = ondownload;\n", "}\n", "\n", "mpl.figure.prototype._init_header = function() {\n", " var titlebar = $(\n", " '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n", " 'ui-helper-clearfix\"/>');\n", " var titletext = $(\n", " '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n", " 'text-align: center; padding: 3px;\"/>');\n", " titlebar.append(titletext)\n", " this.root.append(titlebar);\n", " this.header = titletext[0];\n", "}\n", "\n", "\n", "\n", "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", "\n", "}\n", "\n", "\n", "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", "\n", "}\n", "\n", "mpl.figure.prototype._init_canvas = function() {\n", " var fig = this;\n", "\n", " var canvas_div = $('<div/>');\n", "\n", " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", "\n", " function canvas_keyboard_event(event) {\n", " return fig.key_event(event, event['data']);\n", " }\n", "\n", " canvas_div.keydown('key_press', canvas_keyboard_event);\n", " canvas_div.keyup('key_release', canvas_keyboard_event);\n", " this.canvas_div = canvas_div\n", " this._canvas_extra_style(canvas_div)\n", " this.root.append(canvas_div);\n", "\n", " var canvas = $('<canvas/>');\n", " canvas.addClass('mpl-canvas');\n", " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", "\n", " this.canvas = canvas[0];\n", " this.context = canvas[0].getContext(\"2d\");\n", "\n", " var backingStore = this.context.backingStorePixelRatio ||\n", "\tthis.context.webkitBackingStorePixelRatio ||\n", "\tthis.context.mozBackingStorePixelRatio ||\n", "\tthis.context.msBackingStorePixelRatio ||\n", "\tthis.context.oBackingStorePixelRatio ||\n", "\tthis.context.backingStorePixelRatio || 1;\n", "\n", " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", "\n", " var rubberband = $('<canvas/>');\n", " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", "\n", " var pass_mouse_events = true;\n", "\n", " canvas_div.resizable({\n", " start: function(event, ui) {\n", " pass_mouse_events = false;\n", " },\n", " resize: function(event, ui) {\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " stop: function(event, ui) {\n", " pass_mouse_events = true;\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " });\n", "\n", " function mouse_event_fn(event) {\n", " if (pass_mouse_events)\n", " return fig.mouse_event(event, event['data']);\n", " }\n", "\n", " rubberband.mousedown('button_press', mouse_event_fn);\n", " rubberband.mouseup('button_release', mouse_event_fn);\n", " // Throttle sequential mouse events to 1 every 20ms.\n", " rubberband.mousemove('motion_notify', mouse_event_fn);\n", "\n", " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", "\n", " canvas_div.on(\"wheel\", function (event) {\n", " event = event.originalEvent;\n", " event['data'] = 'scroll'\n", " if (event.deltaY < 0) {\n", " event.step = 1;\n", " } else {\n", " event.step = -1;\n", " }\n", " mouse_event_fn(event);\n", " });\n", "\n", " canvas_div.append(canvas);\n", " canvas_div.append(rubberband);\n", "\n", " this.rubberband = rubberband;\n", " this.rubberband_canvas = rubberband[0];\n", " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", " this.rubberband_context.strokeStyle = \"#000000\";\n", "\n", " this._resize_canvas = function(width, height) {\n", " // Keep the size of the canvas, canvas container, and rubber band\n", " // canvas in synch.\n", " canvas_div.css('width', width)\n", " canvas_div.css('height', height)\n", "\n", " canvas.attr('width', width * mpl.ratio);\n", " canvas.attr('height', height * mpl.ratio);\n", " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", "\n", " rubberband.attr('width', width);\n", " rubberband.attr('height', height);\n", " }\n", "\n", " // Set the figure to an initial 600x600px, this will subsequently be updated\n", " // upon first draw.\n", " this._resize_canvas(600, 600);\n", "\n", " // Disable right mouse context menu.\n", " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", " return false;\n", " });\n", "\n", " function set_focus () {\n", " canvas.focus();\n", " canvas_div.focus();\n", " }\n", "\n", " window.setTimeout(set_focus, 100);\n", "}\n", "\n", "mpl.figure.prototype._init_toolbar = function() {\n", " var fig = this;\n", "\n", " var nav_element = $('<div/>')\n", " nav_element.attr('style', 'width: 100%');\n", " this.root.append(nav_element);\n", "\n", " // Define a callback function for later on.\n", " function toolbar_event(event) {\n", " return fig.toolbar_button_onclick(event['data']);\n", " }\n", " function toolbar_mouse_event(event) {\n", " return fig.toolbar_button_onmouseover(event['data']);\n", " }\n", "\n", " for(var toolbar_ind in mpl.toolbar_items) {\n", " var name = mpl.toolbar_items[toolbar_ind][0];\n", " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", " var image = mpl.toolbar_items[toolbar_ind][2];\n", " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", "\n", " if (!name) {\n", " // put a spacer in here.\n", " continue;\n", " }\n", " var button = $('<button/>');\n", " button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n", " 'ui-button-icon-only');\n", " button.attr('role', 'button');\n", " button.attr('aria-disabled', 'false');\n", " button.click(method_name, toolbar_event);\n", " button.mouseover(tooltip, toolbar_mouse_event);\n", "\n", " var icon_img = $('<span/>');\n", " icon_img.addClass('ui-button-icon-primary ui-icon');\n", " icon_img.addClass(image);\n", " icon_img.addClass('ui-corner-all');\n", "\n", " var tooltip_span = $('<span/>');\n", " tooltip_span.addClass('ui-button-text');\n", " tooltip_span.html(tooltip);\n", "\n", " button.append(icon_img);\n", " button.append(tooltip_span);\n", "\n", " nav_element.append(button);\n", " }\n", "\n", " var fmt_picker_span = $('<span/>');\n", "\n", " var fmt_picker = $('<select/>');\n", " fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n", " fmt_picker_span.append(fmt_picker);\n", " nav_element.append(fmt_picker_span);\n", " this.format_dropdown = fmt_picker[0];\n", "\n", " for (var ind in mpl.extensions) {\n", " var fmt = mpl.extensions[ind];\n", " var option = $(\n", " '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n", " fmt_picker.append(option)\n", " }\n", "\n", " // Add hover states to the ui-buttons\n", " $( \".ui-button\" ).hover(\n", " function() { $(this).addClass(\"ui-state-hover\");},\n", " function() { $(this).removeClass(\"ui-state-hover\");}\n", " );\n", "\n", " var status_bar = $('<span class=\"mpl-message\"/>');\n", " nav_element.append(status_bar);\n", " this.message = status_bar[0];\n", "}\n", "\n", "mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n", " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n", " // which will in turn request a refresh of the image.\n", " this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n", "}\n", "\n", "mpl.figure.prototype.send_message = function(type, properties) {\n", " properties['type'] = type;\n", " properties['figure_id'] = this.id;\n", " this.ws.send(JSON.stringify(properties));\n", "}\n", "\n", "mpl.figure.prototype.send_draw_message = function() {\n", " if (!this.waiting) {\n", " this.waiting = true;\n", " this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n", " }\n", "}\n", "\n", "\n", "mpl.figure.prototype.handle_save = function(fig, msg) {\n", " var format_dropdown = fig.format_dropdown;\n", " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n", " fig.ondownload(fig, format);\n", "}\n", "\n", "\n", "mpl.figure.prototype.handle_resize = function(fig, msg) {\n", " var size = msg['size'];\n", " if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n", " fig._resize_canvas(size[0], size[1]);\n", " fig.send_message(\"refresh\", {});\n", " };\n", "}\n", "\n", "mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n", " var x0 = msg['x0'] / mpl.ratio;\n", " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n", " var x1 = msg['x1'] / mpl.ratio;\n", " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n", " x0 = Math.floor(x0) + 0.5;\n", " y0 = Math.floor(y0) + 0.5;\n", " x1 = Math.floor(x1) + 0.5;\n", " y1 = Math.floor(y1) + 0.5;\n", " var min_x = Math.min(x0, x1);\n", " var min_y = Math.min(y0, y1);\n", " var width = Math.abs(x1 - x0);\n", " var height = Math.abs(y1 - y0);\n", "\n", " fig.rubberband_context.clearRect(\n", " 0, 0, fig.canvas.width, fig.canvas.height);\n", "\n", " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n", "}\n", "\n", "mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n", " // Updates the figure title.\n", " fig.header.textContent = msg['label'];\n", "}\n", "\n", "mpl.figure.prototype.handle_cursor = function(fig, msg) {\n", " var cursor = msg['cursor'];\n", " switch(cursor)\n", " {\n", " case 0:\n", " cursor = 'pointer';\n", " break;\n", " case 1:\n", " cursor = 'default';\n", " break;\n", " case 2:\n", " cursor = 'crosshair';\n", " break;\n", " case 3:\n", " cursor = 'move';\n", " break;\n", " }\n", " fig.rubberband_canvas.style.cursor = cursor;\n", "}\n", "\n", "mpl.figure.prototype.handle_message = function(fig, msg) {\n", " fig.message.textContent = msg['message'];\n", "}\n", "\n", "mpl.figure.prototype.handle_draw = function(fig, msg) {\n", " // Request the server to send over a new figure.\n", " fig.send_draw_message();\n", "}\n", "\n", "mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n", " fig.image_mode = msg['mode'];\n", "}\n", "\n", "mpl.figure.prototype.updated_canvas_event = function() {\n", " // Called whenever the canvas gets updated.\n", " this.send_message(\"ack\", {});\n", "}\n", "\n", "// A function to construct a web socket function for onmessage handling.\n", "// Called in the figure constructor.\n", "mpl.figure.prototype._make_on_message_function = function(fig) {\n", " return function socket_on_message(evt) {\n", " if (evt.data instanceof Blob) {\n", " /* FIXME: We get \"Resource interpreted as Image but\n", " * transferred with MIME type text/plain:\" errors on\n", " * Chrome. But how to set the MIME type? It doesn't seem\n", " * to be part of the websocket stream */\n", " evt.data.type = \"image/png\";\n", "\n", " /* Free the memory for the previous frames */\n", " if (fig.imageObj.src) {\n", " (window.URL || window.webkitURL).revokeObjectURL(\n", " fig.imageObj.src);\n", " }\n", "\n", " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n", " evt.data);\n", " fig.updated_canvas_event();\n", " fig.waiting = false;\n", " return;\n", " }\n", " else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n", " fig.imageObj.src = evt.data;\n", " fig.updated_canvas_event();\n", " fig.waiting = false;\n", " return;\n", " }\n", "\n", " var msg = JSON.parse(evt.data);\n", " var msg_type = msg['type'];\n", "\n", " // Call the \"handle_{type}\" callback, which takes\n", " // the figure and JSON message as its only arguments.\n", " try {\n", " var callback = fig[\"handle_\" + msg_type];\n", " } catch (e) {\n", " console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n", " return;\n", " }\n", "\n", " if (callback) {\n", " try {\n", " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n", " callback(fig, msg);\n", " } catch (e) {\n", " console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n", " }\n", " }\n", " };\n", "}\n", "\n", "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n", "mpl.findpos = function(e) {\n", " //this section is from http://www.quirksmode.org/js/events_properties.html\n", " var targ;\n", " if (!e)\n", " e = window.event;\n", " if (e.target)\n", " targ = e.target;\n", " else if (e.srcElement)\n", " targ = e.srcElement;\n", " if (targ.nodeType == 3) // defeat Safari bug\n", " targ = targ.parentNode;\n", "\n", " // jQuery normalizes the pageX and pageY\n", " // pageX,Y are the mouse positions relative to the document\n", " // offset() returns the position of the element relative to the document\n", " var x = e.pageX - $(targ).offset().left;\n", " var y = e.pageY - $(targ).offset().top;\n", "\n", " return {\"x\": x, \"y\": y};\n", "};\n", "\n", "/*\n", " * return a copy of an object with only non-object keys\n", " * we need this to avoid circular references\n", " * http://stackoverflow.com/a/24161582/3208463\n", " */\n", "function simpleKeys (original) {\n", " return Object.keys(original).reduce(function (obj, key) {\n", " if (typeof original[key] !== 'object')\n", " obj[key] = original[key]\n", " return obj;\n", " }, {});\n", "}\n", "\n", "mpl.figure.prototype.mouse_event = function(event, name) {\n", " var canvas_pos = mpl.findpos(event)\n", "\n", " if (name === 'button_press')\n", " {\n", " this.canvas.focus();\n", " this.canvas_div.focus();\n", " }\n", "\n", " var x = canvas_pos.x * mpl.ratio;\n", " var y = canvas_pos.y * mpl.ratio;\n", "\n", " this.send_message(name, {x: x, y: y, button: event.button,\n", " step: event.step,\n", " guiEvent: simpleKeys(event)});\n", "\n", " /* This prevents the web browser from automatically changing to\n", " * the text insertion cursor when the button is pressed. We want\n", " * to control all of the cursor setting manually through the\n", " * 'cursor' event from matplotlib */\n", " event.preventDefault();\n", " return false;\n", "}\n", "\n", "mpl.figure.prototype._key_event_extra = function(event, name) {\n", " // Handle any extra behaviour associated with a key event\n", "}\n", "\n", "mpl.figure.prototype.key_event = function(event, name) {\n", "\n", " // Prevent repeat events\n", " if (name == 'key_press')\n", " {\n", " if (event.which === this._key)\n", " return;\n", " else\n", " this._key = event.which;\n", " }\n", " if (name == 'key_release')\n", " this._key = null;\n", "\n", " var value = '';\n", " if (event.ctrlKey && event.which != 17)\n", " value += \"ctrl+\";\n", " if (event.altKey && event.which != 18)\n", " value += \"alt+\";\n", " if (event.shiftKey && event.which != 16)\n", " value += \"shift+\";\n", "\n", " value += 'k';\n", " value += event.which.toString();\n", "\n", " this._key_event_extra(event, name);\n", "\n", " this.send_message(name, {key: value,\n", " guiEvent: simpleKeys(event)});\n", " return false;\n", "}\n", "\n", "mpl.figure.prototype.toolbar_button_onclick = function(name) {\n", " if (name == 'download') {\n", " this.handle_save(this, null);\n", " } else {\n", " this.send_message(\"toolbar_button\", {name: name});\n", " }\n", "};\n", "\n", "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n", " this.message.textContent = tooltip;\n", "};\n", "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", "\n", "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n", "\n", "mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n", " // Create a \"websocket\"-like object which calls the given IPython comm\n", " // object with the appropriate methods. Currently this is a non binary\n", " // socket, so there is still some room for performance tuning.\n", " var ws = {};\n", "\n", " ws.close = function() {\n", " comm.close()\n", " };\n", " ws.send = function(m) {\n", " //console.log('sending', m);\n", " comm.send(m);\n", " };\n", " // Register the callback with on_msg.\n", " comm.on_msg(function(msg) {\n", " //console.log('receiving', msg['content']['data'], msg);\n", " // Pass the mpl event to the overriden (by mpl) onmessage function.\n", " ws.onmessage(msg['content']['data'])\n", " });\n", " return ws;\n", "}\n", "\n", "mpl.mpl_figure_comm = function(comm, msg) {\n", " // This is the function which gets called when the mpl process\n", " // starts-up an IPython Comm through the \"matplotlib\" channel.\n", "\n", " var id = msg.content.data.id;\n", " // Get hold of the div created by the display call when the Comm\n", " // socket was opened in Python.\n", " var element = $(\"#\" + id);\n", " var ws_proxy = comm_websocket_adapter(comm)\n", "\n", " function ondownload(figure, format) {\n", " window.open(figure.imageObj.src);\n", " }\n", "\n", " var fig = new mpl.figure(id, ws_proxy,\n", " ondownload,\n", " element.get(0));\n", "\n", " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n", " // web socket which is closed, not our websocket->open comm proxy.\n", " ws_proxy.onopen();\n", "\n", " fig.parent_element = element.get(0);\n", " fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n", " if (!fig.cell_info) {\n", " console.error(\"Failed to find cell for figure\", id, fig);\n", " return;\n", " }\n", "\n", " var output_index = fig.cell_info[2]\n", " var cell = fig.cell_info[0];\n", "\n", "};\n", "\n", "mpl.figure.prototype.handle_close = function(fig, msg) {\n", " var width = fig.canvas.width/mpl.ratio\n", " fig.root.unbind('remove')\n", "\n", " // Update the output cell to use the data from the current canvas.\n", " fig.push_to_output();\n", " var dataURL = fig.canvas.toDataURL();\n", " // Re-enable the keyboard manager in IPython - without this line, in FF,\n", " // the notebook keyboard shortcuts fail.\n", " IPython.keyboard_manager.enable()\n", " $(fig.parent_element).html('<img src=\"' + dataURL + '\" width=\"' + width + '\">');\n", " fig.close_ws(fig, msg);\n", "}\n", "\n", "mpl.figure.prototype.close_ws = function(fig, msg){\n", " fig.send_message('closing', msg);\n", " // fig.ws.close()\n", "}\n", "\n", "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n", " // Turn the data on the canvas into data in the output cell.\n", " var width = this.canvas.width/mpl.ratio\n", " var dataURL = this.canvas.toDataURL();\n", " this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n", "}\n", "\n", "mpl.figure.prototype.updated_canvas_event = function() {\n", " // Tell IPython that the notebook contents must change.\n", " IPython.notebook.set_dirty(true);\n", " this.send_message(\"ack\", {});\n", " var fig = this;\n", " // Wait a second, then push the new image to the DOM so\n", " // that it is saved nicely (might be nice to debounce this).\n", " setTimeout(function () { fig.push_to_output() }, 1000);\n", "}\n", "\n", "mpl.figure.prototype._init_toolbar = function() {\n", " var fig = this;\n", "\n", " var nav_element = $('<div/>')\n", " nav_element.attr('style', 'width: 100%');\n", " this.root.append(nav_element);\n", "\n", " // Define a callback function for later on.\n", " function toolbar_event(event) {\n", " return fig.toolbar_button_onclick(event['data']);\n", " }\n", " function toolbar_mouse_event(event) {\n", " return fig.toolbar_button_onmouseover(event['data']);\n", " }\n", "\n", " for(var toolbar_ind in mpl.toolbar_items){\n", " var name = mpl.toolbar_items[toolbar_ind][0];\n", " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", " var image = mpl.toolbar_items[toolbar_ind][2];\n", " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", "\n", " if (!name) { continue; };\n", "\n", " var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n", " button.click(method_name, toolbar_event);\n", " button.mouseover(tooltip, toolbar_mouse_event);\n", " nav_element.append(button);\n", " }\n", "\n", " // Add the status bar.\n", " var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n", " nav_element.append(status_bar);\n", " this.message = status_bar[0];\n", "\n", " // Add the close button to the window.\n", " var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n", " var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n", " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", " buttongrp.append(button);\n", " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", " titlebar.prepend(buttongrp);\n", "}\n", "\n", "mpl.figure.prototype._root_extra_style = function(el){\n", " var fig = this\n", " el.on(\"remove\", function(){\n", "\tfig.close_ws(fig, {});\n", " });\n", "}\n", "\n", "mpl.figure.prototype._canvas_extra_style = function(el){\n", " // this is important to make the div 'focusable\n", " el.attr('tabindex', 0)\n", " // reach out to IPython and tell the keyboard manager to turn it's self\n", " // off when our div gets focus\n", "\n", " // location in version 3\n", " if (IPython.notebook.keyboard_manager) {\n", " IPython.notebook.keyboard_manager.register_events(el);\n", " }\n", " else {\n", " // location in version 2\n", " IPython.keyboard_manager.register_events(el);\n", " }\n", "\n", "}\n", "\n", "mpl.figure.prototype._key_event_extra = function(event, name) {\n", " var manager = IPython.notebook.keyboard_manager;\n", " if (!manager)\n", " manager = IPython.keyboard_manager;\n", "\n", " // Check for shift+enter\n", " if (event.shiftKey && event.which == 13) {\n", " this.canvas_div.blur();\n", " // select the cell after this one\n", " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", " IPython.notebook.select(index + 1);\n", " }\n", "}\n", "\n", "mpl.figure.prototype.handle_save = function(fig, msg) {\n", " fig.ondownload(fig, null);\n", "}\n", "\n", "\n", "mpl.find_output_cell = function(html_output) {\n", " // Return the cell and output element which can be found *uniquely* in the notebook.\n", " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", " // IPython event is triggered only after the cells have been serialised, which for\n", " // our purposes (turning an active figure into a static one), is too late.\n", " var cells = IPython.notebook.get_cells();\n", " var ncells = cells.length;\n", " for (var i=0; i<ncells; i++) {\n", " var cell = cells[i];\n", " if (cell.cell_type === 'code'){\n", " for (var j=0; j<cell.output_area.outputs.length; j++) {\n", " var data = cell.output_area.outputs[j];\n", " if (data.data) {\n", " // IPython >= 3 moved mimebundle to data attribute of output\n", " data = data.data;\n", " }\n", " if (data['text/html'] == html_output) {\n", " return [cell, data, j];\n", " }\n", " }\n", " }\n", " }\n", "}\n", "\n", "// Register the function which deals with the matplotlib target/channel.\n", "// The kernel may be null if the page has been refreshed.\n", "if (IPython.notebook.kernel != null) {\n", " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", "}\n" ], "text/plain": [ "<IPython.core.display.Javascript object>" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "<img src=\"data:image/png;base64,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\" width=\"600\">" ], "text/plain": [ "<IPython.core.display.HTML object>" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plt.title('ROIs per well of %s' % plate.id)\n", "plt.pcolor(total)\n", "plt.colorbar()\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ "### License\n", "\n", "Copyright (C) 2017 University of Dundee. All Rights Reserved.\n", "\n", "This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.\n", "\n", "This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA." ] } ], "metadata": { "kernelspec": { "display_name": "OMERO Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.13" } }, "nbformat": 4, "nbformat_minor": 2 }