Skip to content

Instantly share code, notes, and snippets.

@rsignell-usgs
Last active May 3, 2018 14:03
Show Gist options
  • Save rsignell-usgs/642899a940de708609a28e25ca801908 to your computer and use it in GitHub Desktop.
Save rsignell-usgs/642899a940de708609a28e25ca801908 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Testing parallel tidal analysis with Utide and Dask Delayed\n",
"====\n",
"We have a 3D (time,lat,lon) cube of water level data and we want to run a tidal analysis function (\"solve\" from Utide) at each lon,lat grid point (or every other lat,lon grid point). This is embarrassingly parallel, and we could use other python parallel approaches, but can we use Dask Delayed?"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
" <div class=\"bk-root\">\n",
" <a href=\"https://bokeh.pydata.org\" target=\"_blank\" class=\"bk-logo bk-logo-small bk-logo-notebook\"></a>\n",
" <span id=\"a0afb7a7-3b77-4d35-9c7d-3ba10d436baa\">Loading BokehJS ...</span>\n",
" </div>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/javascript": [
"\n",
"(function(root) {\n",
" function now() {\n",
" return new Date();\n",
" }\n",
"\n",
" var force = true;\n",
"\n",
" if (typeof (root._bokeh_onload_callbacks) === \"undefined\" || force === true) {\n",
" root._bokeh_onload_callbacks = [];\n",
" root._bokeh_is_loading = undefined;\n",
" }\n",
"\n",
" var JS_MIME_TYPE = 'application/javascript';\n",
" var HTML_MIME_TYPE = 'text/html';\n",
" var EXEC_MIME_TYPE = 'application/vnd.bokehjs_exec.v0+json';\n",
" var CLASS_NAME = 'output_bokeh rendered_html';\n",
"\n",
" /**\n",
" * Render data to the DOM node\n",
" */\n",
" function render(props, node) {\n",
" var script = document.createElement(\"script\");\n",
" node.appendChild(script);\n",
" }\n",
"\n",
" /**\n",
" * Handle when an output is cleared or removed\n",
" */\n",
" function handleClearOutput(event, handle) {\n",
" var cell = handle.cell;\n",
"\n",
" var id = cell.output_area._bokeh_element_id;\n",
" var server_id = cell.output_area._bokeh_server_id;\n",
" // Clean up Bokeh references\n",
" if (id !== undefined) {\n",
" Bokeh.index[id].model.document.clear();\n",
" delete Bokeh.index[id];\n",
" }\n",
"\n",
" if (server_id !== undefined) {\n",
" // Clean up Bokeh references\n",
" var cmd = \"from bokeh.io.state import curstate; print(curstate().uuid_to_server['\" + server_id + \"'].get_sessions()[0].document.roots[0]._id)\";\n",
" cell.notebook.kernel.execute(cmd, {\n",
" iopub: {\n",
" output: function(msg) {\n",
" var element_id = msg.content.text.trim();\n",
" Bokeh.index[element_id].model.document.clear();\n",
" delete Bokeh.index[element_id];\n",
" }\n",
" }\n",
" });\n",
" // Destroy server and session\n",
" var cmd = \"import bokeh.io.notebook as ion; ion.destroy_server('\" + server_id + \"')\";\n",
" cell.notebook.kernel.execute(cmd);\n",
" }\n",
" }\n",
"\n",
" /**\n",
" * Handle when a new output is added\n",
" */\n",
" function handleAddOutput(event, handle) {\n",
" var output_area = handle.output_area;\n",
" var output = handle.output;\n",
"\n",
" // limit handleAddOutput to display_data with EXEC_MIME_TYPE content only\n",
" if ((output.output_type != \"display_data\") || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n",
" return\n",
" }\n",
"\n",
" var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n",
"\n",
" if (output.metadata[EXEC_MIME_TYPE][\"id\"] !== undefined) {\n",
" toinsert[0].firstChild.textContent = output.data[JS_MIME_TYPE];\n",
" // store reference to embed id on output_area\n",
" output_area._bokeh_element_id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n",
" }\n",
" if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n",
" var bk_div = document.createElement(\"div\");\n",
" bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n",
" var script_attrs = bk_div.children[0].attributes;\n",
" for (var i = 0; i < script_attrs.length; i++) {\n",
" toinsert[0].firstChild.setAttribute(script_attrs[i].name, script_attrs[i].value);\n",
" }\n",
" // store reference to server id on output_area\n",
" output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n",
" }\n",
" }\n",
"\n",
" function register_renderer(events, OutputArea) {\n",
"\n",
" function append_mime(data, metadata, element) {\n",
" // create a DOM node to render to\n",
" var toinsert = this.create_output_subarea(\n",
" metadata,\n",
" CLASS_NAME,\n",
" EXEC_MIME_TYPE\n",
" );\n",
" this.keyboard_manager.register_events(toinsert);\n",
" // Render to node\n",
" var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n",
" render(props, toinsert[0]);\n",
" element.append(toinsert);\n",
" return toinsert\n",
" }\n",
"\n",
" /* Handle when an output is cleared or removed */\n",
" events.on('clear_output.CodeCell', handleClearOutput);\n",
" events.on('delete.Cell', handleClearOutput);\n",
"\n",
" /* Handle when a new output is added */\n",
" events.on('output_added.OutputArea', handleAddOutput);\n",
"\n",
" /**\n",
" * Register the mime type and append_mime function with output_area\n",
" */\n",
" OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n",
" /* Is output safe? */\n",
" safe: true,\n",
" /* Index of renderer in `output_area.display_order` */\n",
" index: 0\n",
" });\n",
" }\n",
"\n",
" // register the mime type if in Jupyter Notebook environment and previously unregistered\n",
" if (root.Jupyter !== undefined) {\n",
" var events = require('base/js/events');\n",
" var OutputArea = require('notebook/js/outputarea').OutputArea;\n",
"\n",
" if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n",
" register_renderer(events, OutputArea);\n",
" }\n",
" }\n",
"\n",
" \n",
" if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n",
" root._bokeh_timeout = Date.now() + 5000;\n",
" root._bokeh_failed_load = false;\n",
" }\n",
"\n",
" var NB_LOAD_WARNING = {'data': {'text/html':\n",
" \"<div style='background-color: #fdd'>\\n\"+\n",
" \"<p>\\n\"+\n",
" \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n",
" \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n",
" \"</p>\\n\"+\n",
" \"<ul>\\n\"+\n",
" \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n",
" \"<li>use INLINE resources instead, as so:</li>\\n\"+\n",
" \"</ul>\\n\"+\n",
" \"<code>\\n\"+\n",
" \"from bokeh.resources import INLINE\\n\"+\n",
" \"output_notebook(resources=INLINE)\\n\"+\n",
" \"</code>\\n\"+\n",
" \"</div>\"}};\n",
"\n",
" function display_loaded() {\n",
" var el = document.getElementById(\"a0afb7a7-3b77-4d35-9c7d-3ba10d436baa\");\n",
" if (el != null) {\n",
" el.textContent = \"BokehJS is loading...\";\n",
" }\n",
" if (root.Bokeh !== undefined) {\n",
" if (el != null) {\n",
" el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n",
" }\n",
" } else if (Date.now() < root._bokeh_timeout) {\n",
" setTimeout(display_loaded, 100)\n",
" }\n",
" }\n",
"\n",
"\n",
" function run_callbacks() {\n",
" try {\n",
" root._bokeh_onload_callbacks.forEach(function(callback) { callback() });\n",
" }\n",
" finally {\n",
" delete root._bokeh_onload_callbacks\n",
" }\n",
" console.info(\"Bokeh: all callbacks have finished\");\n",
" }\n",
"\n",
" function load_libs(js_urls, callback) {\n",
" root._bokeh_onload_callbacks.push(callback);\n",
" if (root._bokeh_is_loading > 0) {\n",
" console.log(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n",
" return null;\n",
" }\n",
" if (js_urls == null || js_urls.length === 0) {\n",
" run_callbacks();\n",
" return null;\n",
" }\n",
" console.log(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n",
" root._bokeh_is_loading = js_urls.length;\n",
" for (var i = 0; i < js_urls.length; i++) {\n",
" var url = js_urls[i];\n",
" var s = document.createElement('script');\n",
" s.src = url;\n",
" s.async = false;\n",
" s.onreadystatechange = s.onload = function() {\n",
" root._bokeh_is_loading--;\n",
" if (root._bokeh_is_loading === 0) {\n",
" console.log(\"Bokeh: all BokehJS libraries loaded\");\n",
" run_callbacks()\n",
" }\n",
" };\n",
" s.onerror = function() {\n",
" console.warn(\"failed to load library \" + url);\n",
" };\n",
" console.log(\"Bokeh: injecting script tag for BokehJS library: \", url);\n",
" document.getElementsByTagName(\"head\")[0].appendChild(s);\n",
" }\n",
" };var element = document.getElementById(\"a0afb7a7-3b77-4d35-9c7d-3ba10d436baa\");\n",
" if (element == null) {\n",
" console.log(\"Bokeh: ERROR: autoload.js configured with elementid 'a0afb7a7-3b77-4d35-9c7d-3ba10d436baa' but no matching script tag was found. \")\n",
" return false;\n",
" }\n",
"\n",
" var js_urls = [\"https://cdn.pydata.org/bokeh/dev/bokeh-0.12.15dev1.min.js\", \"https://cdn.pydata.org/bokeh/dev/bokeh-widgets-0.12.15dev1.min.js\", \"https://cdn.pydata.org/bokeh/dev/bokeh-tables-0.12.15dev1.min.js\", \"https://cdn.pydata.org/bokeh/dev/bokeh-gl-0.12.15dev1.min.js\"];\n",
"\n",
" var inline_js = [\n",
" function(Bokeh) {\n",
" Bokeh.set_log_level(\"info\");\n",
" },\n",
" \n",
" function(Bokeh) {\n",
" \n",
" },\n",
" function(Bokeh) {\n",
" console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/dev/bokeh-0.12.15dev1.min.css\");\n",
" Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/dev/bokeh-0.12.15dev1.min.css\");\n",
" console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/dev/bokeh-widgets-0.12.15dev1.min.css\");\n",
" Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/dev/bokeh-widgets-0.12.15dev1.min.css\");\n",
" console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/dev/bokeh-tables-0.12.15dev1.min.css\");\n",
" Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/dev/bokeh-tables-0.12.15dev1.min.css\");\n",
" }\n",
" ];\n",
"\n",
" function run_inline_js() {\n",
" \n",
" if ((root.Bokeh !== undefined) || (force === true)) {\n",
" for (var i = 0; i < inline_js.length; i++) {\n",
" inline_js[i].call(root, root.Bokeh);\n",
" }if (force === true) {\n",
" display_loaded();\n",
" }} else if (Date.now() < root._bokeh_timeout) {\n",
" setTimeout(run_inline_js, 100);\n",
" } else if (!root._bokeh_failed_load) {\n",
" console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n",
" root._bokeh_failed_load = true;\n",
" } else if (force !== true) {\n",
" var cell = $(document.getElementById(\"a0afb7a7-3b77-4d35-9c7d-3ba10d436baa\")).parents('.cell').data().cell;\n",
" cell.output_area.append_execute_result(NB_LOAD_WARNING)\n",
" }\n",
"\n",
" }\n",
"\n",
" if (root._bokeh_is_loading === 0) {\n",
" console.log(\"Bokeh: BokehJS loaded, going straight to plotting\");\n",
" run_inline_js();\n",
" } else {\n",
" load_libs(js_urls, function() {\n",
" console.log(\"Bokeh: BokehJS plotting callback run at\", now());\n",
" run_inline_js();\n",
" });\n",
" }\n",
"}(window));"
],
"application/vnd.bokehjs_load.v0+json": "\n(function(root) {\n function now() {\n return new Date();\n }\n\n var force = true;\n\n if (typeof (root._bokeh_onload_callbacks) === \"undefined\" || force === true) {\n root._bokeh_onload_callbacks = [];\n root._bokeh_is_loading = undefined;\n }\n\n \n\n \n if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n var NB_LOAD_WARNING = {'data': {'text/html':\n \"<div style='background-color: #fdd'>\\n\"+\n \"<p>\\n\"+\n \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n \"</p>\\n\"+\n \"<ul>\\n\"+\n \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n \"<li>use INLINE resources instead, as so:</li>\\n\"+\n \"</ul>\\n\"+\n \"<code>\\n\"+\n \"from bokeh.resources import INLINE\\n\"+\n \"output_notebook(resources=INLINE)\\n\"+\n \"</code>\\n\"+\n \"</div>\"}};\n\n function display_loaded() {\n var el = document.getElementById(\"a0afb7a7-3b77-4d35-9c7d-3ba10d436baa\");\n if (el != null) {\n el.textContent = \"BokehJS is loading...\";\n }\n if (root.Bokeh !== undefined) {\n if (el != null) {\n el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n }\n } else if (Date.now() < root._bokeh_timeout) {\n setTimeout(display_loaded, 100)\n }\n }\n\n\n function run_callbacks() {\n try {\n root._bokeh_onload_callbacks.forEach(function(callback) { callback() });\n }\n finally {\n delete root._bokeh_onload_callbacks\n }\n console.info(\"Bokeh: all callbacks have finished\");\n }\n\n function load_libs(js_urls, callback) {\n root._bokeh_onload_callbacks.push(callback);\n if (root._bokeh_is_loading > 0) {\n console.log(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n }\n if (js_urls == null || js_urls.length === 0) {\n run_callbacks();\n return null;\n }\n console.log(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n root._bokeh_is_loading = js_urls.length;\n for (var i = 0; i < js_urls.length; i++) {\n var url = js_urls[i];\n var s = document.createElement('script');\n s.src = url;\n s.async = false;\n s.onreadystatechange = s.onload = function() {\n root._bokeh_is_loading--;\n if (root._bokeh_is_loading === 0) {\n console.log(\"Bokeh: all BokehJS libraries loaded\");\n run_callbacks()\n }\n };\n s.onerror = function() {\n console.warn(\"failed to load library \" + url);\n };\n console.log(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.getElementsByTagName(\"head\")[0].appendChild(s);\n }\n };var element = document.getElementById(\"a0afb7a7-3b77-4d35-9c7d-3ba10d436baa\");\n if (element == null) {\n console.log(\"Bokeh: ERROR: autoload.js configured with elementid 'a0afb7a7-3b77-4d35-9c7d-3ba10d436baa' but no matching script tag was found. \")\n return false;\n }\n\n var js_urls = [\"https://cdn.pydata.org/bokeh/dev/bokeh-0.12.15dev1.min.js\", \"https://cdn.pydata.org/bokeh/dev/bokeh-widgets-0.12.15dev1.min.js\", \"https://cdn.pydata.org/bokeh/dev/bokeh-tables-0.12.15dev1.min.js\", \"https://cdn.pydata.org/bokeh/dev/bokeh-gl-0.12.15dev1.min.js\"];\n\n var inline_js = [\n function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\n \n function(Bokeh) {\n \n },\n function(Bokeh) {\n console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/dev/bokeh-0.12.15dev1.min.css\");\n Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/dev/bokeh-0.12.15dev1.min.css\");\n console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/dev/bokeh-widgets-0.12.15dev1.min.css\");\n Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/dev/bokeh-widgets-0.12.15dev1.min.css\");\n console.log(\"Bokeh: injecting CSS: https://cdn.pydata.org/bokeh/dev/bokeh-tables-0.12.15dev1.min.css\");\n Bokeh.embed.inject_css(\"https://cdn.pydata.org/bokeh/dev/bokeh-tables-0.12.15dev1.min.css\");\n }\n ];\n\n function run_inline_js() {\n \n if ((root.Bokeh !== undefined) || (force === true)) {\n for (var i = 0; i < inline_js.length; i++) {\n inline_js[i].call(root, root.Bokeh);\n }if (force === true) {\n display_loaded();\n }} else if (Date.now() < root._bokeh_timeout) {\n setTimeout(run_inline_js, 100);\n } else if (!root._bokeh_failed_load) {\n console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n root._bokeh_failed_load = true;\n } else if (force !== true) {\n var cell = $(document.getElementById(\"a0afb7a7-3b77-4d35-9c7d-3ba10d436baa\")).parents('.cell').data().cell;\n cell.output_area.append_execute_result(NB_LOAD_WARNING)\n }\n\n }\n\n if (root._bokeh_is_loading === 0) {\n console.log(\"Bokeh: BokehJS loaded, going straight to plotting\");\n run_inline_js();\n } else {\n load_libs(js_urls, function() {\n console.log(\"Bokeh: BokehJS plotting callback run at\", now());\n run_inline_js();\n });\n }\n}(window));"
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%matplotlib inline\n",
"\n",
"import xarray as xr\n",
"import matplotlib.pyplot as plt\n",
"import gcsfs\n",
"\n",
"from dask.diagnostics import Profiler, ResourceProfiler, CacheProfiler\n",
"from dask.diagnostics import visualize\n",
"\n",
"from bokeh.io import output_notebook\n",
"output_notebook()\n",
"\n",
"from utide import solve\n",
"import numpy as np\n",
"import warnings"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"scrolled": true
},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "a4eb1ba3549c449ab08e6c973f19c9a6",
"version_major": 2,
"version_minor": 0
},
"text/html": [
"<p>Failed to display Jupyter Widget of type <code>VBox</code>.</p>\n",
"<p>\n",
" If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean\n",
" that the widgets JavaScript is still loading. If this message persists, it\n",
" likely means that the widgets JavaScript library is either not installed or\n",
" not enabled. See the <a href=\"https://ipywidgets.readthedocs.io/en/stable/user_install.html\">Jupyter\n",
" Widgets Documentation</a> for setup instructions.\n",
"</p>\n",
"<p>\n",
" If you're reading this message in another frontend (for example, a static\n",
" rendering on GitHub or <a href=\"https://nbviewer.jupyter.org/\">NBViewer</a>),\n",
" it may mean that your frontend doesn't currently support widgets.\n",
"</p>\n"
],
"text/plain": [
"VBox(children=(HTML(value='<h2>KubeCluster</h2>'), HBox(children=(HTML(value='\\n<div>\\n <style scoped>\\n .dataframe tbody tr th:only-of-type {\\n vertical-align: middle;\\n }\\n\\n .dataframe tbody tr th {\\n vertical-align: top;\\n }\\n\\n .dataframe thead th {\\n text-align: right;\\n }\\n </style>\\n <table style=\"text-align: right;\">\\n <tr><th>Workers</th> <td>0</td></tr>\\n <tr><th>Cores</th> <td>0</td></tr>\\n <tr><th>Memory</th> <td>0 B</td></tr>\\n </table>\\n</div>\\n', layout=Layout(min_width='150px')), Accordion(children=(HBox(children=(IntText(value=0, description='Workers', layout=Layout(width='150px')), Button(description='Scale', layout=Layout(width='150px'), style=ButtonStyle()))), HBox(children=(IntText(value=0, description='Minimum', layout=Layout(width='150px')), IntText(value=0, description='Maximum', layout=Layout(width='150px')), Button(description='Adapt', layout=Layout(width='150px'), style=ButtonStyle())))), layout=Layout(min_width='500px'), selected_index=None, _titles={'0': 'Manual Scaling', '1': 'Adaptive Scaling'}))), HTML(value='<p><b>Dashboard: </b><a href=\"/user/rsignell-usgs/proxy/8787/status\" target=\"_blank\">/user/rsignell-usgs/proxy/8787/status</a></p>\\n')))"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"from dask.distributed import Client, progress, LocalCluster\n",
"from dask_kubernetes import KubeCluster\n",
"\n",
"cluster = KubeCluster.from_yaml('/home/jovyan/myworker.yml')\n",
"cluster.scale(20)\n",
"cluster"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"<table style=\"border: 2px solid white;\">\n",
"<tr>\n",
"<td style=\"vertical-align: top; border: 0px solid white\">\n",
"<h3>Client</h3>\n",
"<ul>\n",
" <li><b>Scheduler: </b>tcp://10.23.122.12:38562\n",
" <li><b>Dashboard: </b><a href='/user/rsignell-usgs/proxy/8787/status' target='_blank'>/user/rsignell-usgs/proxy/8787/status</a>\n",
"</ul>\n",
"</td>\n",
"<td style=\"vertical-align: top; border: 0px solid white\">\n",
"<h3>Cluster</h3>\n",
"<ul>\n",
" <li><b>Workers: </b>0</li>\n",
" <li><b>Cores: </b>0</li>\n",
" <li><b>Memory: </b>0 B</li>\n",
"</ul>\n",
"</td>\n",
"</tr>\n",
"</table>"
],
"text/plain": [
"<Client: scheduler='tcp://10.23.122.12:38562' processes=0 cores=0>"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"client = Client(cluster)\n",
"client"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Open Zarr data with Xarray"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"#fs = gcsfs.GCSFileSystem(project='pangeo-181919', token='browser', access='read_only')\n",
"fs = gcsfs.GCSFileSystem(project='pangeo-181919', access='read_only')"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"gcsmap = gcsfs.mapping.GCSMap('pangeo-data/rsignell/ocean_his_tide_zeta',\n",
" gcs=fs, check=False, create=False)\n",
"\n",
"ds = xr.open_zarr(gcsmap, decode_times=False)"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"xarray.Dataset {\n",
"dimensions:\n",
"\teta_rho = 324 ;\n",
"\tocean_time = 1441 ;\n",
"\txi_rho = 1542 ;\n",
"\n",
"variables:\n",
"\tfloat64 lat_rho(eta_rho, xi_rho) ;\n",
"\t\tlat_rho:field = lat_rho, scalar ;\n",
"\t\tlat_rho:long_name = latitude of RHO-points ;\n",
"\t\tlat_rho:standard_name = latitude ;\n",
"\t\tlat_rho:units = degree_north ;\n",
"\tfloat64 lon_rho(eta_rho, xi_rho) ;\n",
"\t\tlon_rho:field = lon_rho, scalar ;\n",
"\t\tlon_rho:long_name = longitude of RHO-points ;\n",
"\t\tlon_rho:standard_name = longitude ;\n",
"\t\tlon_rho:units = degree_east ;\n",
"\tfloat64 ocean_time(ocean_time) ;\n",
"\t\tocean_time:calendar = julian ;\n",
"\t\tocean_time:field = time, scalar, series ;\n",
"\t\tocean_time:long_name = time since initialization ;\n",
"\t\tocean_time:units = seconds since 0001-01-01 00:00:00 ;\n",
"\tfloat32 zeta(ocean_time, eta_rho, xi_rho) ;\n",
"\t\tzeta:field = free-surface, scalar, series ;\n",
"\t\tzeta:grid = grid ;\n",
"\t\tzeta:location = face ;\n",
"\t\tzeta:long_name = free-surface ;\n",
"\t\tzeta:time = ocean_time ;\n",
"\t\tzeta:units = meter ;\n",
"\n",
"// global attributes:\n",
"\t:CPP_options = GSB, ADD_FSOBC, ADD_M2OBC, ANA_BSFLUX, ANA_BTFLUX, ANA_FSOBC, ANA_INITIAL, ANA_M2OBC, ANA_SMFLUX, ANA_SSFLUX, ANA_STFLUX, ASSUMED_SHAPE, DJ_GRADPS, DOUBLE_PRECISION, GLS_MIXING, KANTHA_CLAYSON, MASKING, MIX_S_UV, MPI, NONLINEAR, !NONLIN_EOS, N2S2_HORAVG, POWER_LAW, PROFILE, K_GSCHEME, RAMP_TIDES, !RST_SINGLE, SOLVE3D, SSH_TIDES, TS_C4HADVECTION, TS_C4VADVECTION, TS_FIXED, UV_ADV, UV_COR, UV_U3HADVECTION, UV_C4VADVECTION, UV_LOGDRAG, UV_TIDES, UV_VIS2, VAR_RHO_2D, WET_DRY ;\n",
"\t:Conventions = CF-1.4 ;\n",
"\t:NCO = 4.7.3 ;\n",
"\t:NLM_LBC = \n",
"EDGE: WEST SOUTH EAST NORTH \n",
"zeta: Cha Cha Cha Cha \n",
"ubar: Fla Fla Fla Fla \n",
"vbar: Fla Fla Fla Fla \n",
"u: Gra Gra Gra Gra \n",
"v: Gra Gra Gra Gra \n",
"temp: Gra Gra Gra Gra \n",
"salt: Gra Gra Gra Gra \n",
"tke: Gra Gra Gra Gra ;\n",
"\t:ana_file = ROMS/Functionals/ana_btflux.h, ROMS/Functionals/ana_fsobc.h, ROMS/Functionals/ana_initial.h, ROMS/Functionals/ana_m2obc.h, ROMS/Functionals/ana_smflux.h, ROMS/Functionals/ana_stflux.h ;\n",
"\t:code_dir = /cxfs/projects/usgs/hazards/cmgp/woodshole/aaretxabaleta/models/COAWST ;\n",
"\t:compiler_command = /opt/intel/impi/5.0.1.035/intel64/bin/mpif90 ;\n",
"\t:compiler_flags = -heap-arrays -fp-model precise -ip -O3 -xW -free ;\n",
"\t:compiler_system = ifort ;\n",
"\t:cpu = x86_64 ;\n",
"\t:file = ocean_his_gsb_tides_55nb.nc ;\n",
"\t:format = netCDF-3 64bit offset file ;\n",
"\t:frc_file_01 = ../forcings/tide_forc_GSB_55.nc ;\n",
"\t:grd_file = ../grids/GSB_55nb.nc ;\n",
"\t:header_dir = /cxfs/projects/usgs/hazards/cmgp/woodshole/aaretxabaleta/projects/GSB_tides_55nb ;\n",
"\t:header_file = gsb.h ;\n",
"\t:his_file = ocean_his_gsb_tides_55nb.nc ;\n",
"\t:history = Mon Mar 12 09:36:34 2018: ncks -O -v ocean_time,zeta,lon_rho,lat_rho ocean_his_gsb_tides_55nb.nc /home/rsignell/ocean_his_zeta.nc\n",
"ROMS/TOMS, Version 3.7, Monday - February 26, 2018 - 10:23:23 AM ;\n",
"\t:os = Linux ;\n",
"\t:rst_file = ocean_rst.nc ;\n",
"\t:script_file = ;\n",
"\t:svn_rev = ;\n",
"\t:svn_url = https:://myroms.org/svn/src ;\n",
"\t:tiling = 036x010 ;\n",
"\t:title = Great south Bay ;\n",
"\t:type = ROMS/TOMS history file ;\n",
"\t:var_info = varinfo.dat ;\n",
"}"
]
}
],
"source": [
"ds.info()"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"#client.get_versions(check=True)"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"1441 324 1542\n"
]
}
],
"source": [
"dt, n, m = ds['zeta'].shape\n",
"print(dt,n,m)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<xarray.DataArray 'zeta' (ocean_time: 1441, eta_rho: 324, xi_rho: 1542)>\n",
"dask.array<shape=(1441, 324, 1542), dtype=float32, chunksize=(91, 41, 193)>\n",
"Coordinates:\n",
" lat_rho (eta_rho, xi_rho) float64 dask.array<shape=(324, 1542), chunksize=(81, 771)>\n",
" lon_rho (eta_rho, xi_rho) float64 dask.array<shape=(324, 1542), chunksize=(81, 771)>\n",
" * ocean_time (ocean_time) float64 0.0 1.8e+03 3.6e+03 5.4e+03 7.2e+03 ...\n",
"Dimensions without coordinates: eta_rho, xi_rho\n",
"Attributes:\n",
" field: free-surface, scalar, series\n",
" grid: grid\n",
" location: face\n",
" long_name: free-surface\n",
" time: ocean_time\n",
" units: meter"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ds['zeta']"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"nsub=4"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: user 5.82 s, sys: 877 ms, total: 6.7 s\n",
"Wall time: 10.2 s\n"
]
}
],
"source": [
"%time z = ds['zeta'][:,::nsub,::nsub].load().values"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [],
"source": [
"# convert time to days\n",
"t = ds['ocean_time'].values/(3600.*24)"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"outputs": [],
"source": [
"# nominal latitude for tide calcs\n",
"lat = 40.7"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: user 111 ms, sys: 136 ms, total: 247 ms\n",
"Wall time: 113 ms\n"
]
}
],
"source": [
"%%time\n",
"# analyze tides at single cell as a test\n",
"with warnings.catch_warnings():\n",
" warnings.simplefilter(\"ignore\")\n",
" acoef = solve(t=t, u=z[:,20,20], v=None, lat=lat, \n",
" trend=False, nodal=False, Rayleigh_min=0.95, method='ols',\n",
" conf_int='linear', verbose=False)"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"0.6128407747092631"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# M2 amplitude\n",
"acoef['A'][0]"
]
},
{
"cell_type": "code",
"execution_count": 16,
"metadata": {},
"outputs": [],
"source": [
"import dask.array as da\n",
"from dask import delayed"
]
},
{
"cell_type": "code",
"execution_count": 17,
"metadata": {},
"outputs": [],
"source": [
"usolve = delayed(solve)"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [],
"source": [
"kk,jj,ii = z.shape"
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: user 8.96 s, sys: 515 ms, total: 9.47 s\n",
"Wall time: 8.85 s\n"
]
}
],
"source": [
"%%time \n",
"# set up the Dask delayed task list\n",
"coefs = [usolve(t=t, u=z[:,j,i], v=None, lat=lat, \n",
" trend=False, nodal=False, verbose=False, Rayleigh_min=0.95, method='ols',\n",
" conf_int='linear') for j in range(jj) for i in range(ii)]"
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: user 1min 24s, sys: 5.48 s, total: 1min 29s\n",
"Wall time: 1min 52s\n"
]
}
],
"source": [
"# compute tidal analysis (parallel)\n",
"%time total = delayed(coefs).compute()"
]
},
{
"cell_type": "code",
"execution_count": 21,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: user 1h 10min 7s, sys: 1h 20min 31s, total: 2h 30min 38s\n",
"Wall time: 1h 15min 56s\n"
]
}
],
"source": [
"%%time\n",
"# compute tidal analysis in a regular loop (serial) \n",
"with warnings.catch_warnings():\n",
" warnings.simplefilter(\"ignore\")\n",
" bcoef = [solve(t=t, u=z[:,j,i], v=None, lat=lat, \n",
" trend=False, nodal=False, Rayleigh_min=0.95, method='ols',\n",
" conf_int='linear', verbose=False) for j in range(jj) for i in range(ii)]"
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [],
"source": [
"m2amp = [f['A'][0] for f in total]"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"31266"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"len(m2amp)"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [],
"source": [
"m2amp = np.array(m2amp).reshape((jj,ii))"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib inline\n",
"import matplotlib.pyplot as plt"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 864x576 with 2 Axes>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"plt.figure(figsize=(12,8))\n",
"plt.pcolormesh(m2amp)\n",
"plt.colorbar()\n",
"plt.title('M2 Elevation Amplitude');"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python [default]",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.4"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment