{
 "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
}