diff --git a/catalog/catalog.json b/catalog/catalog.json index 4c6e2e27e69f2a667ba51ab45feaad7e966b94e3..96697fbf85ce84099da89e7c21b34dce5d9b21ae 100644 --- a/catalog/catalog.json +++ b/catalog/catalog.json @@ -28,6 +28,11 @@ "rel": "child", "href": "./alaska_et_2020_gfdl_historical_simulation/collection.json", "type": "application/json" + }, + { + "rel": "child", + "href": "./cprep_tasmax_day_I35txdetrp1-DeltaSD-A12L01K00_rcp26_r6i1p1_I35Land_20060101-20991231/collection.json", + "type": "application/json" } ] } \ No newline at end of file diff --git a/catalog/cprep_tasmax_day_I35txdetrp1-DeltaSD-A12L01K00_rcp26_r6i1p1_I35Land_20060101-20991231/collection.json b/catalog/cprep_tasmax_day_I35txdetrp1-DeltaSD-A12L01K00_rcp26_r6i1p1_I35Land_20060101-20991231/collection.json new file mode 100644 index 0000000000000000000000000000000000000000..66c6c13c584f7b2a6c30da7139a68c02d23f3da1 --- /dev/null +++ b/catalog/cprep_tasmax_day_I35txdetrp1-DeltaSD-A12L01K00_rcp26_r6i1p1_I35Land_20060101-20991231/collection.json @@ -0,0 +1,181 @@ +{ + "type": "Collection", + "id": "cprep_tasmax_day_I35txdetrp1-DeltaSD-A12L01K00_rcp26_r6i1p1_I35Land_20060101-20991231", + "stac_version": "1.0.0", + "description": "cprep_tasmax_day_I35txdetrp1-DeltaSD-A12L01K00_rcp26_r6i1p1_I35Land_20060101-20991231", + "links": [ + { + "rel": "root", + "href": "../catalog.json", + "type": "application/json" + }, + { + "rel": "parent", + "href": "../catalog.json", + "type": "application/json" + } + ], + "stac_extensions": [ + "https://stac-extensions.github.io/datacube/v2.2.0/schema.json" + ], + "cube:dimensions": { + "time": { + "type": "temporal", + "description": "time", + "extent": [ + "2006-01-01T12:00:00Z", + "2099-12-31T12:00:00Z" + ], + "step": "P0DT0H0M0.0864S" + }, + "lon": { + "type": "spatial", + "description": "longitude", + "axis": "x", + "extent": [ + 251.05, + 269.95 + ], + "step": null, + "reference_system": "{\"$schema\":\"https://proj.org/schemas/v0.5/projjson.schema.json\",\"type\":\"ProjectedCRS\",\"name\":\"unknown\",\"base_crs\":{\"name\":\"unknown\",\"datum\":{\"type\":\"GeodeticReferenceFrame\",\"name\":\"unknown\",\"ellipsoid\":{\"name\":\"WGS 84\",\"semi_major_axis\":6378137,\"inverse_flattening\":298.257223563}},\"coordinate_system\":{\"subtype\":\"ellipsoidal\",\"axis\":[{\"name\":\"Longitude\",\"abbreviation\":\"lon\",\"direction\":\"east\",\"unit\":\"degree\"},{\"name\":\"Latitude\",\"abbreviation\":\"lat\",\"direction\":\"north\",\"unit\":\"degree\"},{\"name\":\"Ellipsoidal height\",\"abbreviation\":\"h\",\"direction\":\"up\",\"unit\":\"metre\"}]}},\"conversion\":{\"name\":\"unknown\",\"method\":{\"name\":\"Equidistant Cylindrical\",\"id\":{\"authority\":\"EPSG\",\"code\":1028}},\"parameters\":[{\"name\":\"Latitude of 1st standard parallel\",\"value\":0,\"unit\":\"degree\",\"id\":{\"authority\":\"EPSG\",\"code\":8823}},{\"name\":\"Latitude of natural origin\",\"value\":0,\"unit\":\"degree\",\"id\":{\"authority\":\"EPSG\",\"code\":8801}},{\"name\":\"Longitude of natural origin\",\"value\":0,\"unit\":\"degree\",\"id\":{\"authority\":\"EPSG\",\"code\":8802}},{\"name\":\"False easting\",\"value\":0,\"unit\":{\"type\":\"LinearUnit\",\"name\":\"unknown\",\"conversion_factor\":111319.490793274},\"id\":{\"authority\":\"EPSG\",\"code\":8806}},{\"name\":\"False northing\",\"value\":0,\"unit\":{\"type\":\"LinearUnit\",\"name\":\"unknown\",\"conversion_factor\":111319.490793274},\"id\":{\"authority\":\"EPSG\",\"code\":8807}}]},\"coordinate_system\":{\"subtype\":\"Cartesian\",\"axis\":[{\"name\":\"Easting\",\"abbreviation\":\"E\",\"direction\":\"east\",\"unit\":{\"type\":\"LinearUnit\",\"name\":\"unknown\",\"conversion_factor\":111319.490793274}},{\"name\":\"Northing\",\"abbreviation\":\"N\",\"direction\":\"north\",\"unit\":{\"type\":\"LinearUnit\",\"name\":\"unknown\",\"conversion_factor\":111319.490793274}},{\"name\":\"Ellipsoidal height\",\"abbreviation\":\"h\",\"direction\":\"up\",\"unit\":\"metre\"}]}}" + }, + "lat": { + "type": "spatial", + "axis": "y", + "description": "latitude", + "extent": [ + 26.05, + 39.95 + ], + "step": null, + "reference_system": "{\"$schema\":\"https://proj.org/schemas/v0.5/projjson.schema.json\",\"type\":\"ProjectedCRS\",\"name\":\"unknown\",\"base_crs\":{\"name\":\"unknown\",\"datum\":{\"type\":\"GeodeticReferenceFrame\",\"name\":\"unknown\",\"ellipsoid\":{\"name\":\"WGS 84\",\"semi_major_axis\":6378137,\"inverse_flattening\":298.257223563}},\"coordinate_system\":{\"subtype\":\"ellipsoidal\",\"axis\":[{\"name\":\"Longitude\",\"abbreviation\":\"lon\",\"direction\":\"east\",\"unit\":\"degree\"},{\"name\":\"Latitude\",\"abbreviation\":\"lat\",\"direction\":\"north\",\"unit\":\"degree\"},{\"name\":\"Ellipsoidal height\",\"abbreviation\":\"h\",\"direction\":\"up\",\"unit\":\"metre\"}]}},\"conversion\":{\"name\":\"unknown\",\"method\":{\"name\":\"Equidistant Cylindrical\",\"id\":{\"authority\":\"EPSG\",\"code\":1028}},\"parameters\":[{\"name\":\"Latitude of 1st standard parallel\",\"value\":0,\"unit\":\"degree\",\"id\":{\"authority\":\"EPSG\",\"code\":8823}},{\"name\":\"Latitude of natural origin\",\"value\":0,\"unit\":\"degree\",\"id\":{\"authority\":\"EPSG\",\"code\":8801}},{\"name\":\"Longitude of natural origin\",\"value\":0,\"unit\":\"degree\",\"id\":{\"authority\":\"EPSG\",\"code\":8802}},{\"name\":\"False easting\",\"value\":0,\"unit\":{\"type\":\"LinearUnit\",\"name\":\"unknown\",\"conversion_factor\":111319.490793274},\"id\":{\"authority\":\"EPSG\",\"code\":8806}},{\"name\":\"False northing\",\"value\":0,\"unit\":{\"type\":\"LinearUnit\",\"name\":\"unknown\",\"conversion_factor\":111319.490793274},\"id\":{\"authority\":\"EPSG\",\"code\":8807}}]},\"coordinate_system\":{\"subtype\":\"Cartesian\",\"axis\":[{\"name\":\"Easting\",\"abbreviation\":\"E\",\"direction\":\"east\",\"unit\":{\"type\":\"LinearUnit\",\"name\":\"unknown\",\"conversion_factor\":111319.490793274}},{\"name\":\"Northing\",\"abbreviation\":\"N\",\"direction\":\"north\",\"unit\":{\"type\":\"LinearUnit\",\"name\":\"unknown\",\"conversion_factor\":111319.490793274}},{\"name\":\"Ellipsoidal height\",\"abbreviation\":\"h\",\"direction\":\"up\",\"unit\":\"metre\"}]}}" + }, + "bnds": { + "type": "bounds", + "description": null, + "extent": [ + 0, + 1 + ] + } + }, + "cube:variables": { + "height": { + "dimensions": [], + "type": "data", + "description": null, + "unit": "m" + }, + "i_offset": { + "dimensions": [], + "type": "data", + "description": null, + "unit": null + }, + "j_offset": { + "dimensions": [], + "type": "data", + "description": null, + "unit": null + }, + "lat_bnds": { + "dimensions": [ + "lat", + "bnds" + ], + "type": "data", + "description": null, + "unit": null + }, + "lon_bnds": { + "dimensions": [ + "lon", + "bnds" + ], + "type": "data", + "description": null, + "unit": null + }, + "tasmax": { + "dimensions": [ + "time", + "lat", + "lon" + ], + "type": "data", + "description": "Daily Maximum Near-Surface Air Temperature (resid + trend)", + "unit": "K" + }, + "time_bnds": { + "dimensions": [ + "time", + "bnds" + ], + "type": "data", + "description": "time axis boundaries", + "unit": null + } + }, + "extent": { + "spatial": { + "bbox": [ + [ + 251.05, + 26.05, + 269.95, + 39.95 + ] + ] + }, + "temporal": { + "interval": [ + [ + "2006-01-01T12:00:00Z", + "2099-12-31T12:00:00Z" + ] + ] + } + }, + "license": "CC0-1.0", + "assets": { + "zarr-s3-osn": { + "href": "s3://mdmf/gdp/cprep/cprep_tasmax_day_I35txdetrp1-DeltaSD-A12L01K00_rcp26_r6i1p1_I35Land_20060101-20991231.zarr/", + "type": "application/vnd+zarr", + "description": "Open Storage Network Pod S3 API access to collection zarr group", + "xarray:open_kwargs": { + "chunks": {}, + "engine": "zarr", + "consolidated": true + }, + "xarray:storage_options": { + "anon": true, + "client_kwargs": { + "endpoint_url": "https://usgs.osn.mghpcc.org/" + } + }, + "roles": [ + "data", + "zarr", + "s3" + ] + }, + "zarr-s3": { + "href": "s3://nhgf-development/workspace/DataConversion/gdp/cprep/cprep_tasmax_day_I35txdetrp1-DeltaSD-A12L01K00_rcp26_r6i1p1_I35Land_20060101-20991231.zarr/", + "type": "application/vnd+zarr", + "description": "S3 access to collection zarr group", + "xarray:open_kwargs": { + "chunks": {}, + "engine": "zarr", + "consolidated": true + }, + "xarray:storage_options": { + "requester_pays": true + }, + "roles": [ + "data", + "zarr", + "s3" + ] + } + } +} \ No newline at end of file diff --git a/workflows/archive/alaska_et_2020_ccsm4_historical_simulation_create_collection_from_zarr.ipynb b/workflows/archive/alaska_et_2020_ccsm4_historical_simulation_create_collection_from_zarr.ipynb index af637ec4f8940ddf56a5caa2c236863496c15112..f9024e8f89c72bd51e43b220860ce58ce1c37a83 100644 --- a/workflows/archive/alaska_et_2020_ccsm4_historical_simulation_create_collection_from_zarr.ipynb +++ b/workflows/archive/alaska_et_2020_ccsm4_historical_simulation_create_collection_from_zarr.ipynb @@ -7,8 +7,8 @@ "tags": [] }, "source": [ - "# CONUS404 Daily Zarr -> Collection Exploratory Workflow\n", - "This is a workflow for transforming the CONUS404 daily zarr dataset into a [STAC collection](https://github.com/radiantearth/stac-spec/blob/master/collection-spec/collection-spec.md). We use the [datacube extension](https://github.com/stac-extensions/datacube) to define the spatial and temporal dimensions of the zarr store, as well as the variables it contains.\n", + "# alaska_et_2020_ccsm4_historical_simulation Zarr -> Collection Workflow\n", + "This is a workflow to build a [STAC collection](https://github.com/radiantearth/stac-spec/blob/master/collection-spec/collection-spec.md) from the zarr asset for the dataset named above. We use the [datacube extension](https://github.com/stac-extensions/datacube) to define the spatial and temporal dimensions of the zarr store, as well as the variables it contains.\n", "\n", "To simplify this workflow so that it can scale to many datasets, a few simplifying suggestions and assumptions are made:\n", "1. For USGS data, we can use the CC0-1.0 license. For all other data we can use Unlicense. Ref: https://spdx.org/licenses/\n", diff --git a/workflows/archive/alaska_et_2020_era-interim_reanalysis_create_collection_from_zarr.ipynb b/workflows/archive/alaska_et_2020_era-interim_reanalysis_create_collection_from_zarr.ipynb index e385f15e621602e1d087d1421fb83f914cdf9b6a..6c161d855e7475fa8543d889e5a101f1dfea1e52 100644 --- a/workflows/archive/alaska_et_2020_era-interim_reanalysis_create_collection_from_zarr.ipynb +++ b/workflows/archive/alaska_et_2020_era-interim_reanalysis_create_collection_from_zarr.ipynb @@ -7,8 +7,8 @@ "tags": [] }, "source": [ - "# CONUS404 Daily Zarr -> Collection Exploratory Workflow\n", - "This is a workflow for transforming the CONUS404 daily zarr dataset into a [STAC collection](https://github.com/radiantearth/stac-spec/blob/master/collection-spec/collection-spec.md). We use the [datacube extension](https://github.com/stac-extensions/datacube) to define the spatial and temporal dimensions of the zarr store, as well as the variables it contains.\n", + "# alaska_et_2020_era-interim_reanalysis Zarr -> Collection Workflow\n", + "This is a workflow to build a [STAC collection](https://github.com/radiantearth/stac-spec/blob/master/collection-spec/collection-spec.md) from the zarr asset for the dataset named above. We use the [datacube extension](https://github.com/stac-extensions/datacube) to define the spatial and temporal dimensions of the zarr store, as well as the variables it contains.\n", "\n", "To simplify this workflow so that it can scale to many datasets, a few simplifying suggestions and assumptions are made:\n", "1. For USGS data, we can use the CC0-1.0 license. For all other data we can use Unlicense. Ref: https://spdx.org/licenses/\n", diff --git a/workflows/archive/alaska_et_2020_gfdl_historical_simulation_create_collection_from_zarr.ipynb b/workflows/archive/alaska_et_2020_gfdl_historical_simulation_create_collection_from_zarr.ipynb index 9ba8fc2e8495f3afdfbe1e3259c01c2f3b6c7dd8..8ea56f9338c313ee83a101cf296596d175c80514 100644 --- a/workflows/archive/alaska_et_2020_gfdl_historical_simulation_create_collection_from_zarr.ipynb +++ b/workflows/archive/alaska_et_2020_gfdl_historical_simulation_create_collection_from_zarr.ipynb @@ -7,8 +7,8 @@ "tags": [] }, "source": [ - "# CONUS404 Daily Zarr -> Collection Exploratory Workflow\n", - "This is a workflow for transforming the CONUS404 daily zarr dataset into a [STAC collection](https://github.com/radiantearth/stac-spec/blob/master/collection-spec/collection-spec.md). We use the [datacube extension](https://github.com/stac-extensions/datacube) to define the spatial and temporal dimensions of the zarr store, as well as the variables it contains.\n", + "# alaska_et_2020_gfdl_historical_simulation Zarr -> Collection Workflow\n", + "This is a workflow to build a [STAC collection](https://github.com/radiantearth/stac-spec/blob/master/collection-spec/collection-spec.md) from the zarr asset for the dataset named above. We use the [datacube extension](https://github.com/stac-extensions/datacube) to define the spatial and temporal dimensions of the zarr store, as well as the variables it contains.\n", "\n", "To simplify this workflow so that it can scale to many datasets, a few simplifying suggestions and assumptions are made:\n", "1. For USGS data, we can use the CC0-1.0 license. For all other data we can use Unlicense. Ref: https://spdx.org/licenses/\n", @@ -17,12 +17,650 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "id": "201e0945-de55-45ff-b095-c2af009a4e62", "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "data": { + "application/javascript": [ + "(function(root) {\n", + " function now() {\n", + " return new Date();\n", + " }\n", + "\n", + " var force = true;\n", + " var py_version = '3.3.2'.replace('rc', '-rc.').replace('.dev', '-dev.');\n", + " var reloading = false;\n", + " var Bokeh = root.Bokeh;\n", + "\n", + " if (typeof (root._bokeh_timeout) === \"undefined\" || force) {\n", + " root._bokeh_timeout = Date.now() + 5000;\n", + " root._bokeh_failed_load = false;\n", + " }\n", + "\n", + " function run_callbacks() {\n", + " try {\n", + " root._bokeh_onload_callbacks.forEach(function(callback) {\n", + " if (callback != null)\n", + " callback();\n", + " });\n", + " } finally {\n", + " delete root._bokeh_onload_callbacks;\n", + " }\n", + " console.debug(\"Bokeh: all callbacks have finished\");\n", + " }\n", + "\n", + " function load_libs(css_urls, js_urls, js_modules, js_exports, callback) {\n", + " if (css_urls == null) css_urls = [];\n", + " if (js_urls == null) js_urls = [];\n", + " if (js_modules == null) js_modules = [];\n", + " if (js_exports == null) js_exports = {};\n", + "\n", + " root._bokeh_onload_callbacks.push(callback);\n", + "\n", + " if (root._bokeh_is_loading > 0) {\n", + " console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n", + " return null;\n", + " }\n", + " if (js_urls.length === 0 && js_modules.length === 0 && Object.keys(js_exports).length === 0) {\n", + " run_callbacks();\n", + " return null;\n", + " }\n", + " if (!reloading) {\n", + " console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n", + " }\n", + "\n", + " function on_load() {\n", + " root._bokeh_is_loading--;\n", + " if (root._bokeh_is_loading === 0) {\n", + " console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n", + " run_callbacks()\n", + " }\n", + " }\n", + " window._bokeh_on_load = on_load\n", + "\n", + " function on_error() {\n", + " console.error(\"failed to load \" + url);\n", + " }\n", + "\n", + " var skip = [];\n", + " if (window.requirejs) {\n", + " window.requirejs.config({'packages': {}, 'paths': {'jspanel': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/jspanel', 'jspanel-modal': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/modal/jspanel.modal', 'jspanel-tooltip': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/tooltip/jspanel.tooltip', 'jspanel-hint': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/hint/jspanel.hint', 'jspanel-layout': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/layout/jspanel.layout', 'jspanel-contextmenu': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/contextmenu/jspanel.contextmenu', 'jspanel-dock': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/dock/jspanel.dock', 'gridstack': 'https://cdn.jsdelivr.net/npm/gridstack@7.2.3/dist/gridstack-all', 'notyf': 'https://cdn.jsdelivr.net/npm/notyf@3/notyf.min'}, 'shim': {'jspanel': {'exports': 'jsPanel'}, 'gridstack': {'exports': 'GridStack'}}});\n", + " require([\"jspanel\"], function(jsPanel) {\n", + "\twindow.jsPanel = jsPanel\n", + "\ton_load()\n", + " })\n", + " require([\"jspanel-modal\"], function() {\n", + "\ton_load()\n", + " })\n", + " require([\"jspanel-tooltip\"], function() {\n", + "\ton_load()\n", + " })\n", + " require([\"jspanel-hint\"], function() {\n", + "\ton_load()\n", + " })\n", + " require([\"jspanel-layout\"], function() {\n", + "\ton_load()\n", + " })\n", + " require([\"jspanel-contextmenu\"], function() {\n", + "\ton_load()\n", + " })\n", + " require([\"jspanel-dock\"], function() {\n", + "\ton_load()\n", + " })\n", + " require([\"gridstack\"], function(GridStack) {\n", + "\twindow.GridStack = GridStack\n", + "\ton_load()\n", + " })\n", + " require([\"notyf\"], function() {\n", + "\ton_load()\n", + " })\n", + " root._bokeh_is_loading = css_urls.length + 9;\n", + " } else {\n", + " root._bokeh_is_loading = css_urls.length + js_urls.length + js_modules.length + Object.keys(js_exports).length;\n", + " }\n", + "\n", + " var existing_stylesheets = []\n", + " var links = document.getElementsByTagName('link')\n", + " for (var i = 0; i < links.length; i++) {\n", + " var link = links[i]\n", + " if (link.href != null) {\n", + "\texisting_stylesheets.push(link.href)\n", + " }\n", + " }\n", + " for (var i = 0; i < css_urls.length; i++) {\n", + " var url = css_urls[i];\n", + " if (existing_stylesheets.indexOf(url) !== -1) {\n", + "\ton_load()\n", + "\tcontinue;\n", + " }\n", + " const element = document.createElement(\"link\");\n", + " element.onload = on_load;\n", + " element.onerror = on_error;\n", + " element.rel = \"stylesheet\";\n", + " element.type = \"text/css\";\n", + " element.href = url;\n", + " console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n", + " document.body.appendChild(element);\n", + " } if (((window['jsPanel'] !== undefined) && (!(window['jsPanel'] instanceof HTMLElement))) || window.requirejs) {\n", + " var urls = ['https://cdn.holoviz.org/panel/1.3.6/dist/bundled/floatpanel/jspanel4@4.12.0/dist/jspanel.js', 'https://cdn.holoviz.org/panel/1.3.6/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/modal/jspanel.modal.js', 'https://cdn.holoviz.org/panel/1.3.6/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/tooltip/jspanel.tooltip.js', 'https://cdn.holoviz.org/panel/1.3.6/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/hint/jspanel.hint.js', 'https://cdn.holoviz.org/panel/1.3.6/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/layout/jspanel.layout.js', 'https://cdn.holoviz.org/panel/1.3.6/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/contextmenu/jspanel.contextmenu.js', 'https://cdn.holoviz.org/panel/1.3.6/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/dock/jspanel.dock.js'];\n", + " for (var i = 0; i < urls.length; i++) {\n", + " skip.push(urls[i])\n", + " }\n", + " } if (((window['GridStack'] !== undefined) && (!(window['GridStack'] instanceof HTMLElement))) || window.requirejs) {\n", + " var urls = ['https://cdn.holoviz.org/panel/1.3.6/dist/bundled/gridstack/gridstack@7.2.3/dist/gridstack-all.js'];\n", + " for (var i = 0; i < urls.length; i++) {\n", + " skip.push(urls[i])\n", + " }\n", + " } if (((window['Notyf'] !== undefined) && (!(window['Notyf'] instanceof HTMLElement))) || window.requirejs) {\n", + " var urls = ['https://cdn.holoviz.org/panel/1.3.6/dist/bundled/notificationarea/notyf@3/notyf.min.js'];\n", + " for (var i = 0; i < urls.length; i++) {\n", + " skip.push(urls[i])\n", + " }\n", + " } var existing_scripts = []\n", + " var scripts = document.getElementsByTagName('script')\n", + " for (var i = 0; i < scripts.length; i++) {\n", + " var script = scripts[i]\n", + " if (script.src != null) {\n", + "\texisting_scripts.push(script.src)\n", + " }\n", + " }\n", + " for (var i = 0; i < js_urls.length; i++) {\n", + " var url = js_urls[i];\n", + " if (skip.indexOf(url) !== -1 || existing_scripts.indexOf(url) !== -1) {\n", + "\tif (!window.requirejs) {\n", + "\t on_load();\n", + "\t}\n", + "\tcontinue;\n", + " }\n", + " var element = document.createElement('script');\n", + " element.onload = on_load;\n", + " element.onerror = on_error;\n", + " element.async = false;\n", + " element.src = url;\n", + " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", + " document.head.appendChild(element);\n", + " }\n", + " for (var i = 0; i < js_modules.length; i++) {\n", + " var url = js_modules[i];\n", + " if (skip.indexOf(url) !== -1 || existing_scripts.indexOf(url) !== -1) {\n", + "\tif (!window.requirejs) {\n", + "\t on_load();\n", + "\t}\n", + "\tcontinue;\n", + " }\n", + " var element = document.createElement('script');\n", + " element.onload = on_load;\n", + " element.onerror = on_error;\n", + " element.async = false;\n", + " element.src = url;\n", + " element.type = \"module\";\n", + " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", + " document.head.appendChild(element);\n", + " }\n", + " for (const name in js_exports) {\n", + " var url = js_exports[name];\n", + " if (skip.indexOf(url) >= 0 || root[name] != null) {\n", + "\tif (!window.requirejs) {\n", + "\t on_load();\n", + "\t}\n", + "\tcontinue;\n", + " }\n", + " var element = document.createElement('script');\n", + " element.onerror = on_error;\n", + " element.async = false;\n", + " element.type = \"module\";\n", + " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", + " element.textContent = `\n", + " import ${name} from \"${url}\"\n", + " window.${name} = ${name}\n", + " window._bokeh_on_load()\n", + " `\n", + " document.head.appendChild(element);\n", + " }\n", + " if (!js_urls.length && !js_modules.length) {\n", + " on_load()\n", + " }\n", + " };\n", + "\n", + " function inject_raw_css(css) {\n", + " const element = document.createElement(\"style\");\n", + " element.appendChild(document.createTextNode(css));\n", + " document.body.appendChild(element);\n", + " }\n", + "\n", + " var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-3.3.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.3.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.3.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.3.2.min.js\", \"https://cdn.holoviz.org/panel/1.3.6/dist/panel.min.js\"];\n", + " var js_modules = [];\n", + " var js_exports = {};\n", + " var css_urls = [];\n", + " var inline_js = [ function(Bokeh) {\n", + " Bokeh.set_log_level(\"info\");\n", + " },\n", + "function(Bokeh) {} // ensure no trailing comma for IE\n", + " ];\n", + "\n", + " function run_inline_js() {\n", + " if ((root.Bokeh !== undefined) || (force === true)) {\n", + " for (var i = 0; i < inline_js.length; i++) {\n", + "\ttry {\n", + " inline_js[i].call(root, root.Bokeh);\n", + "\t} catch(e) {\n", + "\t if (!reloading) {\n", + "\t throw e;\n", + "\t }\n", + "\t}\n", + " }\n", + " // Cache old bokeh versions\n", + " if (Bokeh != undefined && !reloading) {\n", + "\tvar NewBokeh = root.Bokeh;\n", + "\tif (Bokeh.versions === undefined) {\n", + "\t Bokeh.versions = new Map();\n", + "\t}\n", + "\tif (NewBokeh.version !== Bokeh.version) {\n", + "\t Bokeh.versions.set(NewBokeh.version, NewBokeh)\n", + "\t}\n", + "\troot.Bokeh = Bokeh;\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", + " }\n", + " root._bokeh_is_initializing = false\n", + " }\n", + "\n", + " function load_or_wait() {\n", + " // Implement a backoff loop that tries to ensure we do not load multiple\n", + " // versions of Bokeh and its dependencies at the same time.\n", + " // In recent versions we use the root._bokeh_is_initializing flag\n", + " // to determine whether there is an ongoing attempt to initialize\n", + " // bokeh, however for backward compatibility we also try to ensure\n", + " // that we do not start loading a newer (Panel>=1.0 and Bokeh>3) version\n", + " // before older versions are fully initialized.\n", + " if (root._bokeh_is_initializing && Date.now() > root._bokeh_timeout) {\n", + " root._bokeh_is_initializing = false;\n", + " root._bokeh_onload_callbacks = undefined;\n", + " console.log(\"Bokeh: BokehJS was loaded multiple times but one version failed to initialize.\");\n", + " load_or_wait();\n", + " } else if (root._bokeh_is_initializing || (typeof root._bokeh_is_initializing === \"undefined\" && root._bokeh_onload_callbacks !== undefined)) {\n", + " setTimeout(load_or_wait, 100);\n", + " } else {\n", + " root._bokeh_is_initializing = true\n", + " root._bokeh_onload_callbacks = []\n", + " var bokeh_loaded = Bokeh != null && (Bokeh.version === py_version || (Bokeh.versions !== undefined && Bokeh.versions.has(py_version)));\n", + " if (!reloading && !bokeh_loaded) {\n", + "\troot.Bokeh = undefined;\n", + " }\n", + " load_libs(css_urls, js_urls, js_modules, js_exports, function() {\n", + "\tconsole.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n", + "\trun_inline_js();\n", + " });\n", + " }\n", + " }\n", + " // Give older versions of the autoload script a head-start to ensure\n", + " // they initialize before we start loading newer version.\n", + " setTimeout(load_or_wait, 100)\n", + "}(window));" + ], + "application/vnd.holoviews_load.v0+json": "(function(root) {\n function now() {\n return new Date();\n }\n\n var force = true;\n var py_version = '3.3.2'.replace('rc', '-rc.').replace('.dev', '-dev.');\n var reloading = false;\n var Bokeh = root.Bokeh;\n\n if (typeof (root._bokeh_timeout) === \"undefined\" || force) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n function run_callbacks() {\n try {\n root._bokeh_onload_callbacks.forEach(function(callback) {\n if (callback != null)\n callback();\n });\n } finally {\n delete root._bokeh_onload_callbacks;\n }\n console.debug(\"Bokeh: all callbacks have finished\");\n }\n\n function load_libs(css_urls, js_urls, js_modules, js_exports, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n if (js_modules == null) js_modules = [];\n if (js_exports == null) js_exports = {};\n\n root._bokeh_onload_callbacks.push(callback);\n\n if (root._bokeh_is_loading > 0) {\n console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n }\n if (js_urls.length === 0 && js_modules.length === 0 && Object.keys(js_exports).length === 0) {\n run_callbacks();\n return null;\n }\n if (!reloading) {\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n }\n\n function on_load() {\n root._bokeh_is_loading--;\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n run_callbacks()\n }\n }\n window._bokeh_on_load = on_load\n\n function on_error() {\n console.error(\"failed to load \" + url);\n }\n\n var skip = [];\n if (window.requirejs) {\n window.requirejs.config({'packages': {}, 'paths': {'jspanel': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/jspanel', 'jspanel-modal': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/modal/jspanel.modal', 'jspanel-tooltip': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/tooltip/jspanel.tooltip', 'jspanel-hint': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/hint/jspanel.hint', 'jspanel-layout': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/layout/jspanel.layout', 'jspanel-contextmenu': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/contextmenu/jspanel.contextmenu', 'jspanel-dock': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/dock/jspanel.dock', 'gridstack': 'https://cdn.jsdelivr.net/npm/gridstack@7.2.3/dist/gridstack-all', 'notyf': 'https://cdn.jsdelivr.net/npm/notyf@3/notyf.min'}, 'shim': {'jspanel': {'exports': 'jsPanel'}, 'gridstack': {'exports': 'GridStack'}}});\n require([\"jspanel\"], function(jsPanel) {\n\twindow.jsPanel = jsPanel\n\ton_load()\n })\n require([\"jspanel-modal\"], function() {\n\ton_load()\n })\n require([\"jspanel-tooltip\"], function() {\n\ton_load()\n })\n require([\"jspanel-hint\"], function() {\n\ton_load()\n })\n require([\"jspanel-layout\"], function() {\n\ton_load()\n })\n require([\"jspanel-contextmenu\"], function() {\n\ton_load()\n })\n require([\"jspanel-dock\"], function() {\n\ton_load()\n })\n require([\"gridstack\"], function(GridStack) {\n\twindow.GridStack = GridStack\n\ton_load()\n })\n require([\"notyf\"], function() {\n\ton_load()\n })\n root._bokeh_is_loading = css_urls.length + 9;\n } else {\n root._bokeh_is_loading = css_urls.length + js_urls.length + js_modules.length + Object.keys(js_exports).length;\n }\n\n var existing_stylesheets = []\n var links = document.getElementsByTagName('link')\n for (var i = 0; i < links.length; i++) {\n var link = links[i]\n if (link.href != null) {\n\texisting_stylesheets.push(link.href)\n }\n }\n for (var i = 0; i < css_urls.length; i++) {\n var url = css_urls[i];\n if (existing_stylesheets.indexOf(url) !== -1) {\n\ton_load()\n\tcontinue;\n }\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error;\n element.rel = \"stylesheet\";\n element.type = \"text/css\";\n element.href = url;\n console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n document.body.appendChild(element);\n } if (((window['jsPanel'] !== undefined) && (!(window['jsPanel'] instanceof HTMLElement))) || window.requirejs) {\n var urls = ['https://cdn.holoviz.org/panel/1.3.6/dist/bundled/floatpanel/jspanel4@4.12.0/dist/jspanel.js', 'https://cdn.holoviz.org/panel/1.3.6/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/modal/jspanel.modal.js', 'https://cdn.holoviz.org/panel/1.3.6/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/tooltip/jspanel.tooltip.js', 'https://cdn.holoviz.org/panel/1.3.6/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/hint/jspanel.hint.js', 'https://cdn.holoviz.org/panel/1.3.6/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/layout/jspanel.layout.js', 'https://cdn.holoviz.org/panel/1.3.6/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/contextmenu/jspanel.contextmenu.js', 'https://cdn.holoviz.org/panel/1.3.6/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/dock/jspanel.dock.js'];\n for (var i = 0; i < urls.length; i++) {\n skip.push(urls[i])\n }\n } if (((window['GridStack'] !== undefined) && (!(window['GridStack'] instanceof HTMLElement))) || window.requirejs) {\n var urls = ['https://cdn.holoviz.org/panel/1.3.6/dist/bundled/gridstack/gridstack@7.2.3/dist/gridstack-all.js'];\n for (var i = 0; i < urls.length; i++) {\n skip.push(urls[i])\n }\n } if (((window['Notyf'] !== undefined) && (!(window['Notyf'] instanceof HTMLElement))) || window.requirejs) {\n var urls = ['https://cdn.holoviz.org/panel/1.3.6/dist/bundled/notificationarea/notyf@3/notyf.min.js'];\n for (var i = 0; i < urls.length; i++) {\n skip.push(urls[i])\n }\n } var existing_scripts = []\n var scripts = document.getElementsByTagName('script')\n for (var i = 0; i < scripts.length; i++) {\n var script = scripts[i]\n if (script.src != null) {\n\texisting_scripts.push(script.src)\n }\n }\n for (var i = 0; i < js_urls.length; i++) {\n var url = js_urls[i];\n if (skip.indexOf(url) !== -1 || existing_scripts.indexOf(url) !== -1) {\n\tif (!window.requirejs) {\n\t on_load();\n\t}\n\tcontinue;\n }\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n for (var i = 0; i < js_modules.length; i++) {\n var url = js_modules[i];\n if (skip.indexOf(url) !== -1 || existing_scripts.indexOf(url) !== -1) {\n\tif (!window.requirejs) {\n\t on_load();\n\t}\n\tcontinue;\n }\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n element.type = \"module\";\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n for (const name in js_exports) {\n var url = js_exports[name];\n if (skip.indexOf(url) >= 0 || root[name] != null) {\n\tif (!window.requirejs) {\n\t on_load();\n\t}\n\tcontinue;\n }\n var element = document.createElement('script');\n element.onerror = on_error;\n element.async = false;\n element.type = \"module\";\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n element.textContent = `\n import ${name} from \"${url}\"\n window.${name} = ${name}\n window._bokeh_on_load()\n `\n document.head.appendChild(element);\n }\n if (!js_urls.length && !js_modules.length) {\n on_load()\n }\n };\n\n function inject_raw_css(css) {\n const element = document.createElement(\"style\");\n element.appendChild(document.createTextNode(css));\n document.body.appendChild(element);\n }\n\n var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-3.3.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.3.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.3.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.3.2.min.js\", \"https://cdn.holoviz.org/panel/1.3.6/dist/panel.min.js\"];\n var js_modules = [];\n var js_exports = {};\n var css_urls = [];\n var inline_js = [ function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\nfunction(Bokeh) {} // ensure no trailing comma for IE\n ];\n\n function run_inline_js() {\n if ((root.Bokeh !== undefined) || (force === true)) {\n for (var i = 0; i < inline_js.length; i++) {\n\ttry {\n inline_js[i].call(root, root.Bokeh);\n\t} catch(e) {\n\t if (!reloading) {\n\t throw e;\n\t }\n\t}\n }\n // Cache old bokeh versions\n if (Bokeh != undefined && !reloading) {\n\tvar NewBokeh = root.Bokeh;\n\tif (Bokeh.versions === undefined) {\n\t Bokeh.versions = new Map();\n\t}\n\tif (NewBokeh.version !== Bokeh.version) {\n\t Bokeh.versions.set(NewBokeh.version, NewBokeh)\n\t}\n\troot.Bokeh = Bokeh;\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 }\n root._bokeh_is_initializing = false\n }\n\n function load_or_wait() {\n // Implement a backoff loop that tries to ensure we do not load multiple\n // versions of Bokeh and its dependencies at the same time.\n // In recent versions we use the root._bokeh_is_initializing flag\n // to determine whether there is an ongoing attempt to initialize\n // bokeh, however for backward compatibility we also try to ensure\n // that we do not start loading a newer (Panel>=1.0 and Bokeh>3) version\n // before older versions are fully initialized.\n if (root._bokeh_is_initializing && Date.now() > root._bokeh_timeout) {\n root._bokeh_is_initializing = false;\n root._bokeh_onload_callbacks = undefined;\n console.log(\"Bokeh: BokehJS was loaded multiple times but one version failed to initialize.\");\n load_or_wait();\n } else if (root._bokeh_is_initializing || (typeof root._bokeh_is_initializing === \"undefined\" && root._bokeh_onload_callbacks !== undefined)) {\n setTimeout(load_or_wait, 100);\n } else {\n root._bokeh_is_initializing = true\n root._bokeh_onload_callbacks = []\n var bokeh_loaded = Bokeh != null && (Bokeh.version === py_version || (Bokeh.versions !== undefined && Bokeh.versions.has(py_version)));\n if (!reloading && !bokeh_loaded) {\n\troot.Bokeh = undefined;\n }\n load_libs(css_urls, js_urls, js_modules, js_exports, function() {\n\tconsole.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n\trun_inline_js();\n });\n }\n }\n // Give older versions of the autoload script a head-start to ensure\n // they initialize before we start loading newer version.\n setTimeout(load_or_wait, 100)\n}(window));" + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/javascript": [ + "\n", + "if ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n", + " window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n", + "}\n", + "\n", + "\n", + " function JupyterCommManager() {\n", + " }\n", + "\n", + " JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n", + " if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n", + " var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n", + " comm_manager.register_target(comm_id, function(comm) {\n", + " comm.on_msg(msg_handler);\n", + " });\n", + " } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n", + " window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n", + " comm.onMsg = msg_handler;\n", + " });\n", + " } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n", + " google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n", + " var messages = comm.messages[Symbol.asyncIterator]();\n", + " function processIteratorResult(result) {\n", + " var message = result.value;\n", + " console.log(message)\n", + " var content = {data: message.data, comm_id};\n", + " var buffers = []\n", + " for (var buffer of message.buffers || []) {\n", + " buffers.push(new DataView(buffer))\n", + " }\n", + " var metadata = message.metadata || {};\n", + " var msg = {content, buffers, metadata}\n", + " msg_handler(msg);\n", + " return messages.next().then(processIteratorResult);\n", + " }\n", + " return messages.next().then(processIteratorResult);\n", + " })\n", + " }\n", + " }\n", + "\n", + " JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n", + " if (comm_id in window.PyViz.comms) {\n", + " return window.PyViz.comms[comm_id];\n", + " } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n", + " var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n", + " var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n", + " if (msg_handler) {\n", + " comm.on_msg(msg_handler);\n", + " }\n", + " } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n", + " var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n", + " comm.open();\n", + " if (msg_handler) {\n", + " comm.onMsg = msg_handler;\n", + " }\n", + " } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n", + " var comm_promise = google.colab.kernel.comms.open(comm_id)\n", + " comm_promise.then((comm) => {\n", + " window.PyViz.comms[comm_id] = comm;\n", + " if (msg_handler) {\n", + " var messages = comm.messages[Symbol.asyncIterator]();\n", + " function processIteratorResult(result) {\n", + " var message = result.value;\n", + " var content = {data: message.data};\n", + " var metadata = message.metadata || {comm_id};\n", + " var msg = {content, metadata}\n", + " msg_handler(msg);\n", + " return messages.next().then(processIteratorResult);\n", + " }\n", + " return messages.next().then(processIteratorResult);\n", + " }\n", + " }) \n", + " var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n", + " return comm_promise.then((comm) => {\n", + " comm.send(data, metadata, buffers, disposeOnDone);\n", + " });\n", + " };\n", + " var comm = {\n", + " send: sendClosure\n", + " };\n", + " }\n", + " window.PyViz.comms[comm_id] = comm;\n", + " return comm;\n", + " }\n", + " window.PyViz.comm_manager = new JupyterCommManager();\n", + " \n", + "\n", + "\n", + "var JS_MIME_TYPE = 'application/javascript';\n", + "var HTML_MIME_TYPE = 'text/html';\n", + "var EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\n", + "var CLASS_NAME = 'output';\n", + "\n", + "/**\n", + " * Render data to the DOM node\n", + " */\n", + "function render(props, node) {\n", + " var div = document.createElement(\"div\");\n", + " var script = document.createElement(\"script\");\n", + " node.appendChild(div);\n", + " node.appendChild(script);\n", + "}\n", + "\n", + "/**\n", + " * Handle when a new output is added\n", + " */\n", + "function handle_add_output(event, handle) {\n", + " var output_area = handle.output_area;\n", + " var output = handle.output;\n", + " if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n", + " return\n", + " }\n", + " var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n", + " var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n", + " if (id !== undefined) {\n", + " var nchildren = toinsert.length;\n", + " var html_node = toinsert[nchildren-1].children[0];\n", + " html_node.innerHTML = output.data[HTML_MIME_TYPE];\n", + " var scripts = [];\n", + " var nodelist = html_node.querySelectorAll(\"script\");\n", + " for (var i in nodelist) {\n", + " if (nodelist.hasOwnProperty(i)) {\n", + " scripts.push(nodelist[i])\n", + " }\n", + " }\n", + "\n", + " scripts.forEach( function (oldScript) {\n", + " var newScript = document.createElement(\"script\");\n", + " var attrs = [];\n", + " var nodemap = oldScript.attributes;\n", + " for (var j in nodemap) {\n", + " if (nodemap.hasOwnProperty(j)) {\n", + " attrs.push(nodemap[j])\n", + " }\n", + " }\n", + " attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n", + " newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n", + " oldScript.parentNode.replaceChild(newScript, oldScript);\n", + " });\n", + " if (JS_MIME_TYPE in output.data) {\n", + " toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n", + " }\n", + " output_area._hv_plot_id = id;\n", + " if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n", + " window.PyViz.plot_index[id] = Bokeh.index[id];\n", + " } else {\n", + " window.PyViz.plot_index[id] = null;\n", + " }\n", + " } else 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[toinsert.length - 1].childNodes[1].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", + "/**\n", + " * Handle when an output is cleared or removed\n", + " */\n", + "function handle_clear_output(event, handle) {\n", + " var id = handle.cell.output_area._hv_plot_id;\n", + " var server_id = handle.cell.output_area._bokeh_server_id;\n", + " if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n", + " var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n", + " if (server_id !== null) {\n", + " comm.send({event_type: 'server_delete', 'id': server_id});\n", + " return;\n", + " } else if (comm !== null) {\n", + " comm.send({event_type: 'delete', 'id': id});\n", + " }\n", + " delete PyViz.plot_index[id];\n", + " if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n", + " var doc = window.Bokeh.index[id].model.document\n", + " doc.clear();\n", + " const i = window.Bokeh.documents.indexOf(doc);\n", + " if (i > -1) {\n", + " window.Bokeh.documents.splice(i, 1);\n", + " }\n", + " }\n", + "}\n", + "\n", + "/**\n", + " * Handle kernel restart event\n", + " */\n", + "function handle_kernel_cleanup(event, handle) {\n", + " delete PyViz.comms[\"hv-extension-comm\"];\n", + " window.PyViz.plot_index = {}\n", + "}\n", + "\n", + "/**\n", + " * Handle update_display_data messages\n", + " */\n", + "function handle_update_output(event, handle) {\n", + " handle_clear_output(event, {cell: {output_area: handle.output_area}})\n", + " handle_add_output(event, handle)\n", + "}\n", + "\n", + "function register_renderer(events, OutputArea) {\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", + " events.on('output_added.OutputArea', handle_add_output);\n", + " events.on('output_updated.OutputArea', handle_update_output);\n", + " events.on('clear_output.CodeCell', handle_clear_output);\n", + " events.on('delete.Cell', handle_clear_output);\n", + " events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n", + "\n", + " OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n", + " safe: true,\n", + " index: 0\n", + " });\n", + "}\n", + "\n", + "if (window.Jupyter !== undefined) {\n", + " try {\n", + " var events = require('base/js/events');\n", + " var OutputArea = require('notebook/js/outputarea').OutputArea;\n", + " if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n", + " register_renderer(events, OutputArea);\n", + " }\n", + " } catch(err) {\n", + " }\n", + "}\n" + ], + "application/vnd.holoviews_load.v0+json": "\nif ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n}\n\n\n function JupyterCommManager() {\n }\n\n JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n comm_manager.register_target(comm_id, function(comm) {\n comm.on_msg(msg_handler);\n });\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n comm.onMsg = msg_handler;\n });\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n console.log(message)\n var content = {data: message.data, comm_id};\n var buffers = []\n for (var buffer of message.buffers || []) {\n buffers.push(new DataView(buffer))\n }\n var metadata = message.metadata || {};\n var msg = {content, buffers, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n })\n }\n }\n\n JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n if (comm_id in window.PyViz.comms) {\n return window.PyViz.comms[comm_id];\n } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n if (msg_handler) {\n comm.on_msg(msg_handler);\n }\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n comm.open();\n if (msg_handler) {\n comm.onMsg = msg_handler;\n }\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n var comm_promise = google.colab.kernel.comms.open(comm_id)\n comm_promise.then((comm) => {\n window.PyViz.comms[comm_id] = comm;\n if (msg_handler) {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n var content = {data: message.data};\n var metadata = message.metadata || {comm_id};\n var msg = {content, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n }\n }) \n var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n return comm_promise.then((comm) => {\n comm.send(data, metadata, buffers, disposeOnDone);\n });\n };\n var comm = {\n send: sendClosure\n };\n }\n window.PyViz.comms[comm_id] = comm;\n return comm;\n }\n window.PyViz.comm_manager = new JupyterCommManager();\n \n\n\nvar JS_MIME_TYPE = 'application/javascript';\nvar HTML_MIME_TYPE = 'text/html';\nvar EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\nvar CLASS_NAME = 'output';\n\n/**\n * Render data to the DOM node\n */\nfunction render(props, node) {\n var div = document.createElement(\"div\");\n var script = document.createElement(\"script\");\n node.appendChild(div);\n node.appendChild(script);\n}\n\n/**\n * Handle when a new output is added\n */\nfunction handle_add_output(event, handle) {\n var output_area = handle.output_area;\n var output = handle.output;\n if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n return\n }\n var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n if (id !== undefined) {\n var nchildren = toinsert.length;\n var html_node = toinsert[nchildren-1].children[0];\n html_node.innerHTML = output.data[HTML_MIME_TYPE];\n var scripts = [];\n var nodelist = html_node.querySelectorAll(\"script\");\n for (var i in nodelist) {\n if (nodelist.hasOwnProperty(i)) {\n scripts.push(nodelist[i])\n }\n }\n\n scripts.forEach( function (oldScript) {\n var newScript = document.createElement(\"script\");\n var attrs = [];\n var nodemap = oldScript.attributes;\n for (var j in nodemap) {\n if (nodemap.hasOwnProperty(j)) {\n attrs.push(nodemap[j])\n }\n }\n attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n oldScript.parentNode.replaceChild(newScript, oldScript);\n });\n if (JS_MIME_TYPE in output.data) {\n toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n }\n output_area._hv_plot_id = id;\n if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n window.PyViz.plot_index[id] = Bokeh.index[id];\n } else {\n window.PyViz.plot_index[id] = null;\n }\n } else 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[toinsert.length - 1].childNodes[1].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/**\n * Handle when an output is cleared or removed\n */\nfunction handle_clear_output(event, handle) {\n var id = handle.cell.output_area._hv_plot_id;\n var server_id = handle.cell.output_area._bokeh_server_id;\n if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n if (server_id !== null) {\n comm.send({event_type: 'server_delete', 'id': server_id});\n return;\n } else if (comm !== null) {\n comm.send({event_type: 'delete', 'id': id});\n }\n delete PyViz.plot_index[id];\n if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n var doc = window.Bokeh.index[id].model.document\n doc.clear();\n const i = window.Bokeh.documents.indexOf(doc);\n if (i > -1) {\n window.Bokeh.documents.splice(i, 1);\n }\n }\n}\n\n/**\n * Handle kernel restart event\n */\nfunction handle_kernel_cleanup(event, handle) {\n delete PyViz.comms[\"hv-extension-comm\"];\n window.PyViz.plot_index = {}\n}\n\n/**\n * Handle update_display_data messages\n */\nfunction handle_update_output(event, handle) {\n handle_clear_output(event, {cell: {output_area: handle.output_area}})\n handle_add_output(event, handle)\n}\n\nfunction register_renderer(events, OutputArea) {\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 events.on('output_added.OutputArea', handle_add_output);\n events.on('output_updated.OutputArea', handle_update_output);\n events.on('clear_output.CodeCell', handle_clear_output);\n events.on('delete.Cell', handle_clear_output);\n events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n\n OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n safe: true,\n index: 0\n });\n}\n\nif (window.Jupyter !== undefined) {\n try {\n var events = require('base/js/events');\n var OutputArea = require('notebook/js/outputarea').OutputArea;\n if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n register_renderer(events, OutputArea);\n }\n } catch(err) {\n }\n}\n" + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "<style>*[data-root-id],\n", + "*[data-root-id] > * {\n", + " box-sizing: border-box;\n", + " font-family: var(--jp-ui-font-family);\n", + " font-size: var(--jp-ui-font-size1);\n", + " color: var(--vscode-editor-foreground, var(--jp-ui-font-color1));\n", + "}\n", + "\n", + "/* Override VSCode background color */\n", + ".cell-output-ipywidget-background:has(\n", + " > .cell-output-ipywidget-background > .lm-Widget > *[data-root-id]\n", + " ),\n", + ".cell-output-ipywidget-background:has(> .lm-Widget > *[data-root-id]) {\n", + " background-color: transparent !important;\n", + "}\n", + "</style>" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/vnd.holoviews_exec.v0+json": "", + "text/html": [ + "<div id='p1002'>\n", + " <div id=\"beeadda7-c8a4-4837-9968-aafd05156841\" data-root-id=\"p1002\" style=\"display: contents;\"></div>\n", + "</div>\n", + "<script type=\"application/javascript\">(function(root) {\n", + " var docs_json = {\"798ac8a4-d458-41b6-9f4b-194347fd9f22\":{\"version\":\"3.3.2\",\"title\":\"Bokeh Application\",\"roots\":[{\"type\":\"object\",\"name\":\"panel.models.browser.BrowserInfo\",\"id\":\"p1002\"},{\"type\":\"object\",\"name\":\"panel.models.comm_manager.CommManager\",\"id\":\"p1003\",\"attributes\":{\"plot_id\":\"p1002\",\"comm_id\":\"b907cc722a2948fcb3323552595d694c\",\"client_comm_id\":\"db5d543f0c67431da89f67833616aa53\"}}],\"defs\":[{\"type\":\"model\",\"name\":\"ReactiveHTML1\"},{\"type\":\"model\",\"name\":\"FlexBox1\",\"properties\":[{\"name\":\"align_content\",\"kind\":\"Any\",\"default\":\"flex-start\"},{\"name\":\"align_items\",\"kind\":\"Any\",\"default\":\"flex-start\"},{\"name\":\"flex_direction\",\"kind\":\"Any\",\"default\":\"row\"},{\"name\":\"flex_wrap\",\"kind\":\"Any\",\"default\":\"wrap\"},{\"name\":\"justify_content\",\"kind\":\"Any\",\"default\":\"flex-start\"}]},{\"type\":\"model\",\"name\":\"FloatPanel1\",\"properties\":[{\"name\":\"config\",\"kind\":\"Any\",\"default\":{\"type\":\"map\"}},{\"name\":\"contained\",\"kind\":\"Any\",\"default\":true},{\"name\":\"position\",\"kind\":\"Any\",\"default\":\"right-top\"},{\"name\":\"offsetx\",\"kind\":\"Any\",\"default\":null},{\"name\":\"offsety\",\"kind\":\"Any\",\"default\":null},{\"name\":\"theme\",\"kind\":\"Any\",\"default\":\"primary\"},{\"name\":\"status\",\"kind\":\"Any\",\"default\":\"normalized\"}]},{\"type\":\"model\",\"name\":\"GridStack1\",\"properties\":[{\"name\":\"mode\",\"kind\":\"Any\",\"default\":\"warn\"},{\"name\":\"ncols\",\"kind\":\"Any\",\"default\":null},{\"name\":\"nrows\",\"kind\":\"Any\",\"default\":null},{\"name\":\"allow_resize\",\"kind\":\"Any\",\"default\":true},{\"name\":\"allow_drag\",\"kind\":\"Any\",\"default\":true},{\"name\":\"state\",\"kind\":\"Any\",\"default\":[]}]},{\"type\":\"model\",\"name\":\"drag1\",\"properties\":[{\"name\":\"slider_width\",\"kind\":\"Any\",\"default\":5},{\"name\":\"slider_color\",\"kind\":\"Any\",\"default\":\"black\"},{\"name\":\"value\",\"kind\":\"Any\",\"default\":50}]},{\"type\":\"model\",\"name\":\"click1\",\"properties\":[{\"name\":\"terminal_output\",\"kind\":\"Any\",\"default\":\"\"},{\"name\":\"debug_name\",\"kind\":\"Any\",\"default\":\"\"},{\"name\":\"clears\",\"kind\":\"Any\",\"default\":0}]},{\"type\":\"model\",\"name\":\"copy_to_clipboard1\",\"properties\":[{\"name\":\"fill\",\"kind\":\"Any\",\"default\":\"none\"},{\"name\":\"value\",\"kind\":\"Any\",\"default\":null}]},{\"type\":\"model\",\"name\":\"FastWrapper1\",\"properties\":[{\"name\":\"object\",\"kind\":\"Any\",\"default\":null},{\"name\":\"style\",\"kind\":\"Any\",\"default\":null}]},{\"type\":\"model\",\"name\":\"NotificationAreaBase1\",\"properties\":[{\"name\":\"js_events\",\"kind\":\"Any\",\"default\":{\"type\":\"map\"}},{\"name\":\"position\",\"kind\":\"Any\",\"default\":\"bottom-right\"},{\"name\":\"_clear\",\"kind\":\"Any\",\"default\":0}]},{\"type\":\"model\",\"name\":\"NotificationArea1\",\"properties\":[{\"name\":\"js_events\",\"kind\":\"Any\",\"default\":{\"type\":\"map\"}},{\"name\":\"notifications\",\"kind\":\"Any\",\"default\":[]},{\"name\":\"position\",\"kind\":\"Any\",\"default\":\"bottom-right\"},{\"name\":\"_clear\",\"kind\":\"Any\",\"default\":0},{\"name\":\"types\",\"kind\":\"Any\",\"default\":[{\"type\":\"map\",\"entries\":[[\"type\",\"warning\"],[\"background\",\"#ffc107\"],[\"icon\",{\"type\":\"map\",\"entries\":[[\"className\",\"fas fa-exclamation-triangle\"],[\"tagName\",\"i\"],[\"color\",\"white\"]]}]]},{\"type\":\"map\",\"entries\":[[\"type\",\"info\"],[\"background\",\"#007bff\"],[\"icon\",{\"type\":\"map\",\"entries\":[[\"className\",\"fas fa-info-circle\"],[\"tagName\",\"i\"],[\"color\",\"white\"]]}]]}]}]},{\"type\":\"model\",\"name\":\"Notification\",\"properties\":[{\"name\":\"background\",\"kind\":\"Any\",\"default\":null},{\"name\":\"duration\",\"kind\":\"Any\",\"default\":3000},{\"name\":\"icon\",\"kind\":\"Any\",\"default\":null},{\"name\":\"message\",\"kind\":\"Any\",\"default\":\"\"},{\"name\":\"notification_type\",\"kind\":\"Any\",\"default\":null},{\"name\":\"_destroyed\",\"kind\":\"Any\",\"default\":false}]},{\"type\":\"model\",\"name\":\"TemplateActions1\",\"properties\":[{\"name\":\"open_modal\",\"kind\":\"Any\",\"default\":0},{\"name\":\"close_modal\",\"kind\":\"Any\",\"default\":0}]},{\"type\":\"model\",\"name\":\"BootstrapTemplateActions1\",\"properties\":[{\"name\":\"open_modal\",\"kind\":\"Any\",\"default\":0},{\"name\":\"close_modal\",\"kind\":\"Any\",\"default\":0}]},{\"type\":\"model\",\"name\":\"MaterialTemplateActions1\",\"properties\":[{\"name\":\"open_modal\",\"kind\":\"Any\",\"default\":0},{\"name\":\"close_modal\",\"kind\":\"Any\",\"default\":0}]}]}};\n", + " var render_items = [{\"docid\":\"798ac8a4-d458-41b6-9f4b-194347fd9f22\",\"roots\":{\"p1002\":\"beeadda7-c8a4-4837-9968-aafd05156841\"},\"root_ids\":[\"p1002\"]}];\n", + " var docs = Object.values(docs_json)\n", + " if (!docs) {\n", + " return\n", + " }\n", + " const py_version = docs[0].version.replace('rc', '-rc.').replace('.dev', '-dev.')\n", + " function embed_document(root) {\n", + " var Bokeh = get_bokeh(root)\n", + " Bokeh.embed.embed_items_notebook(docs_json, render_items);\n", + " for (const render_item of render_items) {\n", + " for (const root_id of render_item.root_ids) {\n", + "\tconst id_el = document.getElementById(root_id)\n", + "\tif (id_el.children.length && (id_el.children[0].className === 'bk-root')) {\n", + "\t const root_el = id_el.children[0]\n", + "\t root_el.id = root_el.id + '-rendered'\n", + "\t}\n", + " }\n", + " }\n", + " }\n", + " function get_bokeh(root) {\n", + " if (root.Bokeh === undefined) {\n", + " return null\n", + " } else if (root.Bokeh.version !== py_version) {\n", + " if (root.Bokeh.versions === undefined || !root.Bokeh.versions.has(py_version)) {\n", + "\treturn null\n", + " }\n", + " return root.Bokeh.versions.get(py_version);\n", + " } else if (root.Bokeh.version === py_version) {\n", + " return root.Bokeh\n", + " }\n", + " return null\n", + " }\n", + " function is_loaded(root) {\n", + " var Bokeh = get_bokeh(root)\n", + " return (Bokeh != null && Bokeh.Panel !== undefined)\n", + " }\n", + " if (is_loaded(root)) {\n", + " embed_document(root);\n", + " } else {\n", + " var attempts = 0;\n", + " var timer = setInterval(function(root) {\n", + " if (is_loaded(root)) {\n", + " clearInterval(timer);\n", + " embed_document(root);\n", + " } else if (document.readyState == \"complete\") {\n", + " attempts++;\n", + " if (attempts > 200) {\n", + " clearInterval(timer);\n", + "\t var Bokeh = get_bokeh(root)\n", + "\t if (Bokeh == null || Bokeh.Panel == null) {\n", + " console.warn(\"Panel: ERROR: Unable to run Panel code because Bokeh or Panel library is missing\");\n", + "\t } else {\n", + "\t console.warn(\"Panel: WARNING: Attempting to render but not all required libraries could be resolved.\")\n", + "\t embed_document(root)\n", + "\t }\n", + " }\n", + " }\n", + " }, 25, root)\n", + " }\n", + "})(window);</script>" + ] + }, + "metadata": { + "application/vnd.holoviews_exec.v0+json": { + "id": "p1002" + } + }, + "output_type": "display_data" + } + ], "source": [ "import pystac\n", "from pystac.extensions.datacube import CollectionDatacubeExtension, AssetDatacubeExtension, AdditionalDimension, DatacubeExtension\n", @@ -51,7 +689,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "id": "adf6c59d-58cd-48b1-a5fd-3bb205a3ef56", "metadata": { "tags": [] @@ -74,7 +712,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "id": "482d204d-b5b6-40e5-ac42-55b459be1097", "metadata": { "tags": [] @@ -99,7 +737,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "id": "dd6fa323-132a-4794-8c80-576933f547a0", "metadata": { "tags": [] @@ -121,7 +759,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "id": "e1441cd4-e94c-4902-af46-8f1af470eb6b", "metadata": { "tags": [] @@ -153,12 +791,694 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "id": "708f2cf5-79ab-49af-8067-de31d0d13ee6", "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "<div><svg style=\"position: absolute; width: 0; height: 0; overflow: hidden\">\n", + "<defs>\n", + "<symbol id=\"icon-database\" viewBox=\"0 0 32 32\">\n", + "<path d=\"M16 0c-8.837 0-16 2.239-16 5v4c0 2.761 7.163 5 16 5s16-2.239 16-5v-4c0-2.761-7.163-5-16-5z\"></path>\n", + "<path d=\"M16 17c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z\"></path>\n", + "<path d=\"M16 26c-8.837 0-16-2.239-16-5v6c0 2.761 7.163 5 16 5s16-2.239 16-5v-6c0 2.761-7.163 5-16 5z\"></path>\n", + "</symbol>\n", + "<symbol id=\"icon-file-text2\" viewBox=\"0 0 32 32\">\n", + "<path d=\"M28.681 7.159c-0.694-0.947-1.662-2.053-2.724-3.116s-2.169-2.030-3.116-2.724c-1.612-1.182-2.393-1.319-2.841-1.319h-15.5c-1.378 0-2.5 1.121-2.5 2.5v27c0 1.378 1.122 2.5 2.5 2.5h23c1.378 0 2.5-1.122 2.5-2.5v-19.5c0-0.448-0.137-1.23-1.319-2.841zM24.543 5.457c0.959 0.959 1.712 1.825 2.268 2.543h-4.811v-4.811c0.718 0.556 1.584 1.309 2.543 2.268zM28 29.5c0 0.271-0.229 0.5-0.5 0.5h-23c-0.271 0-0.5-0.229-0.5-0.5v-27c0-0.271 0.229-0.5 0.5-0.5 0 0 15.499-0 15.5 0v7c0 0.552 0.448 1 1 1h7v19.5z\"></path>\n", + "<path d=\"M23 26h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z\"></path>\n", + "<path d=\"M23 22h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z\"></path>\n", + "<path d=\"M23 18h-14c-0.552 0-1-0.448-1-1s0.448-1 1-1h14c0.552 0 1 0.448 1 1s-0.448 1-1 1z\"></path>\n", + "</symbol>\n", + "</defs>\n", + "</svg>\n", + "<style>/* CSS stylesheet for displaying xarray objects in jupyterlab.\n", + " *\n", + " */\n", + "\n", + ":root {\n", + " --xr-font-color0: var(--jp-content-font-color0, rgba(0, 0, 0, 1));\n", + " --xr-font-color2: var(--jp-content-font-color2, rgba(0, 0, 0, 0.54));\n", + " --xr-font-color3: var(--jp-content-font-color3, rgba(0, 0, 0, 0.38));\n", + " --xr-border-color: var(--jp-border-color2, #e0e0e0);\n", + " --xr-disabled-color: var(--jp-layout-color3, #bdbdbd);\n", + " --xr-background-color: var(--jp-layout-color0, white);\n", + " --xr-background-color-row-even: var(--jp-layout-color1, white);\n", + " --xr-background-color-row-odd: var(--jp-layout-color2, #eeeeee);\n", + "}\n", + "\n", + "html[theme=dark],\n", + "body[data-theme=dark],\n", + "body.vscode-dark {\n", + " --xr-font-color0: rgba(255, 255, 255, 1);\n", + " --xr-font-color2: rgba(255, 255, 255, 0.54);\n", + " --xr-font-color3: rgba(255, 255, 255, 0.38);\n", + " --xr-border-color: #1F1F1F;\n", + " --xr-disabled-color: #515151;\n", + " --xr-background-color: #111111;\n", + " --xr-background-color-row-even: #111111;\n", + " --xr-background-color-row-odd: #313131;\n", + "}\n", + "\n", + ".xr-wrap {\n", + " display: block !important;\n", + " min-width: 300px;\n", + " max-width: 700px;\n", + "}\n", + "\n", + ".xr-text-repr-fallback {\n", + " /* fallback to plain text repr when CSS is not injected (untrusted notebook) */\n", + " display: none;\n", + "}\n", + "\n", + ".xr-header {\n", + " padding-top: 6px;\n", + " padding-bottom: 6px;\n", + " margin-bottom: 4px;\n", + " border-bottom: solid 1px var(--xr-border-color);\n", + "}\n", + "\n", + ".xr-header > div,\n", + ".xr-header > ul {\n", + " display: inline;\n", + " margin-top: 0;\n", + " margin-bottom: 0;\n", + "}\n", + "\n", + ".xr-obj-type,\n", + ".xr-array-name {\n", + " margin-left: 2px;\n", + " margin-right: 10px;\n", + "}\n", + "\n", + ".xr-obj-type {\n", + " color: var(--xr-font-color2);\n", + "}\n", + "\n", + ".xr-sections {\n", + " padding-left: 0 !important;\n", + " display: grid;\n", + " grid-template-columns: 150px auto auto 1fr 20px 20px;\n", + "}\n", + "\n", + ".xr-section-item {\n", + " display: contents;\n", + "}\n", + "\n", + ".xr-section-item input {\n", + " display: none;\n", + "}\n", + "\n", + ".xr-section-item input + label {\n", + " color: var(--xr-disabled-color);\n", + "}\n", + "\n", + ".xr-section-item input:enabled + label {\n", + " cursor: pointer;\n", + " color: var(--xr-font-color2);\n", + "}\n", + "\n", + ".xr-section-item input:enabled + label:hover {\n", + " color: var(--xr-font-color0);\n", + "}\n", + "\n", + ".xr-section-summary {\n", + " grid-column: 1;\n", + " color: var(--xr-font-color2);\n", + " font-weight: 500;\n", + "}\n", + "\n", + ".xr-section-summary > span {\n", + " display: inline-block;\n", + " padding-left: 0.5em;\n", + "}\n", + "\n", + ".xr-section-summary-in:disabled + label {\n", + " color: var(--xr-font-color2);\n", + "}\n", + "\n", + ".xr-section-summary-in + label:before {\n", + " display: inline-block;\n", + " content: '►';\n", + " font-size: 11px;\n", + " width: 15px;\n", + " text-align: center;\n", + "}\n", + "\n", + ".xr-section-summary-in:disabled + label:before {\n", + " color: var(--xr-disabled-color);\n", + "}\n", + "\n", + ".xr-section-summary-in:checked + label:before {\n", + " content: '▼';\n", + "}\n", + "\n", + ".xr-section-summary-in:checked + label > span {\n", + " display: none;\n", + "}\n", + "\n", + ".xr-section-summary,\n", + ".xr-section-inline-details {\n", + " padding-top: 4px;\n", + " padding-bottom: 4px;\n", + "}\n", + "\n", + ".xr-section-inline-details {\n", + " grid-column: 2 / -1;\n", + "}\n", + "\n", + ".xr-section-details {\n", + " display: none;\n", + " grid-column: 1 / -1;\n", + " margin-bottom: 5px;\n", + "}\n", + "\n", + ".xr-section-summary-in:checked ~ .xr-section-details {\n", + " display: contents;\n", + "}\n", + "\n", + ".xr-array-wrap {\n", + " grid-column: 1 / -1;\n", + " display: grid;\n", + " grid-template-columns: 20px auto;\n", + "}\n", + "\n", + ".xr-array-wrap > label {\n", + " grid-column: 1;\n", + " vertical-align: top;\n", + "}\n", + "\n", + ".xr-preview {\n", + " color: var(--xr-font-color3);\n", + "}\n", + "\n", + ".xr-array-preview,\n", + ".xr-array-data {\n", + " padding: 0 5px !important;\n", + " grid-column: 2;\n", + "}\n", + "\n", + ".xr-array-data,\n", + ".xr-array-in:checked ~ .xr-array-preview {\n", + " display: none;\n", + "}\n", + "\n", + ".xr-array-in:checked ~ .xr-array-data,\n", + ".xr-array-preview {\n", + " display: inline-block;\n", + "}\n", + "\n", + ".xr-dim-list {\n", + " display: inline-block !important;\n", + " list-style: none;\n", + " padding: 0 !important;\n", + " margin: 0;\n", + "}\n", + "\n", + ".xr-dim-list li {\n", + " display: inline-block;\n", + " padding: 0;\n", + " margin: 0;\n", + "}\n", + "\n", + ".xr-dim-list:before {\n", + " content: '(';\n", + "}\n", + "\n", + ".xr-dim-list:after {\n", + " content: ')';\n", + "}\n", + "\n", + ".xr-dim-list li:not(:last-child):after {\n", + " content: ',';\n", + " padding-right: 5px;\n", + "}\n", + "\n", + ".xr-has-index {\n", + " font-weight: bold;\n", + "}\n", + "\n", + ".xr-var-list,\n", + ".xr-var-item {\n", + " display: contents;\n", + "}\n", + "\n", + ".xr-var-item > div,\n", + ".xr-var-item label,\n", + ".xr-var-item > .xr-var-name span {\n", + " background-color: var(--xr-background-color-row-even);\n", + " margin-bottom: 0;\n", + "}\n", + "\n", + ".xr-var-item > .xr-var-name:hover span {\n", + " padding-right: 5px;\n", + "}\n", + "\n", + ".xr-var-list > li:nth-child(odd) > div,\n", + ".xr-var-list > li:nth-child(odd) > label,\n", + ".xr-var-list > li:nth-child(odd) > .xr-var-name span {\n", + " background-color: var(--xr-background-color-row-odd);\n", + "}\n", + "\n", + ".xr-var-name {\n", + " grid-column: 1;\n", + "}\n", + "\n", + ".xr-var-dims {\n", + " grid-column: 2;\n", + "}\n", + "\n", + ".xr-var-dtype {\n", + " grid-column: 3;\n", + " text-align: right;\n", + " color: var(--xr-font-color2);\n", + "}\n", + "\n", + ".xr-var-preview {\n", + " grid-column: 4;\n", + "}\n", + "\n", + ".xr-index-preview {\n", + " grid-column: 2 / 5;\n", + " color: var(--xr-font-color2);\n", + "}\n", + "\n", + ".xr-var-name,\n", + ".xr-var-dims,\n", + ".xr-var-dtype,\n", + ".xr-preview,\n", + ".xr-attrs dt {\n", + " white-space: nowrap;\n", + " overflow: hidden;\n", + " text-overflow: ellipsis;\n", + " padding-right: 10px;\n", + "}\n", + "\n", + ".xr-var-name:hover,\n", + ".xr-var-dims:hover,\n", + ".xr-var-dtype:hover,\n", + ".xr-attrs dt:hover {\n", + " overflow: visible;\n", + " width: auto;\n", + " z-index: 1;\n", + "}\n", + "\n", + ".xr-var-attrs,\n", + ".xr-var-data,\n", + ".xr-index-data {\n", + " display: none;\n", + " background-color: var(--xr-background-color) !important;\n", + " padding-bottom: 5px !important;\n", + "}\n", + "\n", + ".xr-var-attrs-in:checked ~ .xr-var-attrs,\n", + ".xr-var-data-in:checked ~ .xr-var-data,\n", + ".xr-index-data-in:checked ~ .xr-index-data {\n", + " display: block;\n", + "}\n", + "\n", + ".xr-var-data > table {\n", + " float: right;\n", + "}\n", + "\n", + ".xr-var-name span,\n", + ".xr-var-data,\n", + ".xr-index-name div,\n", + ".xr-index-data,\n", + ".xr-attrs {\n", + " padding-left: 25px !important;\n", + "}\n", + "\n", + ".xr-attrs,\n", + ".xr-var-attrs,\n", + ".xr-var-data,\n", + ".xr-index-data {\n", + " grid-column: 1 / -1;\n", + "}\n", + "\n", + "dl.xr-attrs {\n", + " padding: 0;\n", + " margin: 0;\n", + " display: grid;\n", + " grid-template-columns: 125px auto;\n", + "}\n", + "\n", + ".xr-attrs dt,\n", + ".xr-attrs dd {\n", + " padding: 0;\n", + " margin: 0;\n", + " float: left;\n", + " padding-right: 10px;\n", + " width: auto;\n", + "}\n", + "\n", + ".xr-attrs dt {\n", + " font-weight: normal;\n", + " grid-column: 1;\n", + "}\n", + "\n", + ".xr-attrs dt:hover span {\n", + " display: inline-block;\n", + " background: var(--xr-background-color);\n", + " padding-right: 10px;\n", + "}\n", + "\n", + ".xr-attrs dd {\n", + " grid-column: 2;\n", + " white-space: pre-wrap;\n", + " word-break: break-all;\n", + "}\n", + "\n", + ".xr-icon-database,\n", + ".xr-icon-file-text2,\n", + ".xr-no-icon {\n", + " display: inline-block;\n", + " vertical-align: middle;\n", + " width: 1em;\n", + " height: 1.5em !important;\n", + " stroke-width: 0;\n", + " stroke: currentColor;\n", + " fill: currentColor;\n", + "}\n", + "</style><pre class='xr-text-repr-fallback'><xarray.Dataset>\n", + "Dimensions: (time: 22326, y: 262, x: 262)\n", + "Coordinates:\n", + " lat (y, x) float32 dask.array<chunksize=(131, 131), meta=np.ndarray>\n", + " lon (y, x) float32 dask.array<chunksize=(131, 131), meta=np.ndarray>\n", + " * time (time) datetime64[ns] 1979-04-01 ... 2100-09-30\n", + " * x (x) float64 -2.61e+06 -2.59e+06 ... 2.59e+06 2.61e+06\n", + " * y (y) float64 -5.414e+06 -5.394e+06 ... -1.936e+05\n", + "Data variables:\n", + " et0 (time, y, x) float32 dask.array<chunksize=(100, 131, 131), meta=np.ndarray>\n", + " polar_stereographic |S64 ...\n", + "Attributes: (12/27)\n", + " Conventions: CF\n", + " DODS.strlen: 0\n", + " Metadata_Conventions: Unidata Dataset Discovery v1.0\n", + " NCO: "4.5.4"\n", + " acknowledgment: NULL\n", + " cdm_data_type: grid\n", + " ... ...\n", + " publisher_name: David Watkins\n", + " publisher_url: https://water.usgs.gov/\n", + " source: Dynamically Downscaled GFDL-CM3 Historical and RCP...\n", + " time_coverage_end: \n", + " time_coverage_start: \n", + " title: Gridded 20km Daily Reference Evapotranspiration fo...</pre><div class='xr-wrap' style='display:none'><div class='xr-header'><div class='xr-obj-type'>xarray.Dataset</div></div><ul class='xr-sections'><li class='xr-section-item'><input id='section-77fd8e30-2208-447d-bebe-a69e6a8145cd' class='xr-section-summary-in' type='checkbox' disabled ><label for='section-77fd8e30-2208-447d-bebe-a69e6a8145cd' class='xr-section-summary' title='Expand/collapse section'>Dimensions:</label><div class='xr-section-inline-details'><ul class='xr-dim-list'><li><span class='xr-has-index'>time</span>: 22326</li><li><span class='xr-has-index'>y</span>: 262</li><li><span class='xr-has-index'>x</span>: 262</li></ul></div><div class='xr-section-details'></div></li><li class='xr-section-item'><input id='section-de7ba60d-7b54-4f39-9f6a-16b0c7b1c3fb' class='xr-section-summary-in' type='checkbox' checked><label for='section-de7ba60d-7b54-4f39-9f6a-16b0c7b1c3fb' class='xr-section-summary' >Coordinates: <span>(5)</span></label><div class='xr-section-inline-details'></div><div class='xr-section-details'><ul class='xr-var-list'><li class='xr-var-item'><div class='xr-var-name'><span>lat</span></div><div class='xr-var-dims'>(y, x)</div><div class='xr-var-dtype'>float32</div><div class='xr-var-preview xr-preview'>dask.array<chunksize=(131, 131), meta=np.ndarray></div><input id='attrs-030bf548-3a4c-47f4-aae3-a18ade5f68f8' class='xr-var-attrs-in' type='checkbox' ><label for='attrs-030bf548-3a4c-47f4-aae3-a18ade5f68f8' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-2b834c83-2750-4275-9824-779679c072d5' class='xr-var-data-in' type='checkbox'><label for='data-2b834c83-2750-4275-9824-779679c072d5' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'><dt><span>long_name :</span></dt><dd>latitude</dd><dt><span>units :</span></dt><dd>degrees_north</dd></dl></div><div class='xr-var-data'><table>\n", + " <tr>\n", + " <td>\n", + " <table style=\"border-collapse: collapse;\">\n", + " <thead>\n", + " <tr>\n", + " <td> </td>\n", + " <th> Array </th>\n", + " <th> Chunk </th>\n", + " </tr>\n", + " </thead>\n", + " <tbody>\n", + " \n", + " <tr>\n", + " <th> Bytes </th>\n", + " <td> 268.14 kiB </td>\n", + " <td> 67.04 kiB </td>\n", + " </tr>\n", + " \n", + " <tr>\n", + " <th> Shape </th>\n", + " <td> (262, 262) </td>\n", + " <td> (131, 131) </td>\n", + " </tr>\n", + " <tr>\n", + " <th> Dask graph </th>\n", + " <td colspan=\"2\"> 4 chunks in 2 graph layers </td>\n", + " </tr>\n", + " <tr>\n", + " <th> Data type </th>\n", + " <td colspan=\"2\"> float32 numpy.ndarray </td>\n", + " </tr>\n", + " </tbody>\n", + " </table>\n", + " </td>\n", + " <td>\n", + " <svg width=\"170\" height=\"170\" style=\"stroke:rgb(0,0,0);stroke-width:1\" >\n", + "\n", + " <!-- Horizontal lines -->\n", + " <line x1=\"0\" y1=\"0\" x2=\"120\" y2=\"0\" style=\"stroke-width:2\" />\n", + " <line x1=\"0\" y1=\"60\" x2=\"120\" y2=\"60\" />\n", + " <line x1=\"0\" y1=\"120\" x2=\"120\" y2=\"120\" style=\"stroke-width:2\" />\n", + "\n", + " <!-- Vertical lines -->\n", + " <line x1=\"0\" y1=\"0\" x2=\"0\" y2=\"120\" style=\"stroke-width:2\" />\n", + " <line x1=\"60\" y1=\"0\" x2=\"60\" y2=\"120\" />\n", + " <line x1=\"120\" y1=\"0\" x2=\"120\" y2=\"120\" style=\"stroke-width:2\" />\n", + "\n", + " <!-- Colored Rectangle -->\n", + " <polygon points=\"0.0,0.0 120.0,0.0 120.0,120.0 0.0,120.0\" style=\"fill:#ECB172A0;stroke-width:0\"/>\n", + "\n", + " <!-- Text -->\n", + " <text x=\"60.000000\" y=\"140.000000\" font-size=\"1.0rem\" font-weight=\"100\" text-anchor=\"middle\" >262</text>\n", + " <text x=\"140.000000\" y=\"60.000000\" font-size=\"1.0rem\" font-weight=\"100\" text-anchor=\"middle\" transform=\"rotate(-90,140.000000,60.000000)\">262</text>\n", + "</svg>\n", + " </td>\n", + " </tr>\n", + "</table></div></li><li class='xr-var-item'><div class='xr-var-name'><span>lon</span></div><div class='xr-var-dims'>(y, x)</div><div class='xr-var-dtype'>float32</div><div class='xr-var-preview xr-preview'>dask.array<chunksize=(131, 131), meta=np.ndarray></div><input id='attrs-9d1b0af5-1d33-4855-8eb5-9df5bc619eb5' class='xr-var-attrs-in' type='checkbox' ><label for='attrs-9d1b0af5-1d33-4855-8eb5-9df5bc619eb5' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-db034acd-8d86-4464-a379-98e8b427d9b2' class='xr-var-data-in' type='checkbox'><label for='data-db034acd-8d86-4464-a379-98e8b427d9b2' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'><dt><span>long_name :</span></dt><dd>longitude</dd><dt><span>units :</span></dt><dd>degrees_east</dd></dl></div><div class='xr-var-data'><table>\n", + " <tr>\n", + " <td>\n", + " <table style=\"border-collapse: collapse;\">\n", + " <thead>\n", + " <tr>\n", + " <td> </td>\n", + " <th> Array </th>\n", + " <th> Chunk </th>\n", + " </tr>\n", + " </thead>\n", + " <tbody>\n", + " \n", + " <tr>\n", + " <th> Bytes </th>\n", + " <td> 268.14 kiB </td>\n", + " <td> 67.04 kiB </td>\n", + " </tr>\n", + " \n", + " <tr>\n", + " <th> Shape </th>\n", + " <td> (262, 262) </td>\n", + " <td> (131, 131) </td>\n", + " </tr>\n", + " <tr>\n", + " <th> Dask graph </th>\n", + " <td colspan=\"2\"> 4 chunks in 2 graph layers </td>\n", + " </tr>\n", + " <tr>\n", + " <th> Data type </th>\n", + " <td colspan=\"2\"> float32 numpy.ndarray </td>\n", + " </tr>\n", + " </tbody>\n", + " </table>\n", + " </td>\n", + " <td>\n", + " <svg width=\"170\" height=\"170\" style=\"stroke:rgb(0,0,0);stroke-width:1\" >\n", + "\n", + " <!-- Horizontal lines -->\n", + " <line x1=\"0\" y1=\"0\" x2=\"120\" y2=\"0\" style=\"stroke-width:2\" />\n", + " <line x1=\"0\" y1=\"60\" x2=\"120\" y2=\"60\" />\n", + " <line x1=\"0\" y1=\"120\" x2=\"120\" y2=\"120\" style=\"stroke-width:2\" />\n", + "\n", + " <!-- Vertical lines -->\n", + " <line x1=\"0\" y1=\"0\" x2=\"0\" y2=\"120\" style=\"stroke-width:2\" />\n", + " <line x1=\"60\" y1=\"0\" x2=\"60\" y2=\"120\" />\n", + " <line x1=\"120\" y1=\"0\" x2=\"120\" y2=\"120\" style=\"stroke-width:2\" />\n", + "\n", + " <!-- Colored Rectangle -->\n", + " <polygon points=\"0.0,0.0 120.0,0.0 120.0,120.0 0.0,120.0\" style=\"fill:#ECB172A0;stroke-width:0\"/>\n", + "\n", + " <!-- Text -->\n", + " <text x=\"60.000000\" y=\"140.000000\" font-size=\"1.0rem\" font-weight=\"100\" text-anchor=\"middle\" >262</text>\n", + " <text x=\"140.000000\" y=\"60.000000\" font-size=\"1.0rem\" font-weight=\"100\" text-anchor=\"middle\" transform=\"rotate(-90,140.000000,60.000000)\">262</text>\n", + "</svg>\n", + " </td>\n", + " </tr>\n", + "</table></div></li><li class='xr-var-item'><div class='xr-var-name'><span class='xr-has-index'>time</span></div><div class='xr-var-dims'>(time)</div><div class='xr-var-dtype'>datetime64[ns]</div><div class='xr-var-preview xr-preview'>1979-04-01 ... 2100-09-30</div><input id='attrs-6c43e040-b1fc-4c11-9d3f-456f91e211e5' class='xr-var-attrs-in' type='checkbox' ><label for='attrs-6c43e040-b1fc-4c11-9d3f-456f91e211e5' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-514b1e67-a848-4501-bd80-0cab9354941b' class='xr-var-data-in' type='checkbox'><label for='data-514b1e67-a848-4501-bd80-0cab9354941b' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'><dt><span>long_name :</span></dt><dd>time</dd></dl></div><div class='xr-var-data'><pre>array(['1979-04-01T00:00:00.000000000', '1979-04-02T00:00:00.000000000',\n", + " '1979-04-03T00:00:00.000000000', ..., '2100-09-28T00:00:00.000000000',\n", + " '2100-09-29T00:00:00.000000000', '2100-09-30T00:00:00.000000000'],\n", + " dtype='datetime64[ns]')</pre></div></li><li class='xr-var-item'><div class='xr-var-name'><span class='xr-has-index'>x</span></div><div class='xr-var-dims'>(x)</div><div class='xr-var-dtype'>float64</div><div class='xr-var-preview xr-preview'>-2.61e+06 -2.59e+06 ... 2.61e+06</div><input id='attrs-3ea03b41-9ff8-4b28-b47e-c7ebb7258682' class='xr-var-attrs-in' type='checkbox' ><label for='attrs-3ea03b41-9ff8-4b28-b47e-c7ebb7258682' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-762ea601-801b-4456-bcbe-1acb18aa5b6c' class='xr-var-data-in' type='checkbox'><label for='data-762ea601-801b-4456-bcbe-1acb18aa5b6c' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'><dt><span>long_name :</span></dt><dd>x coordinate of projection</dd><dt><span>standard_name :</span></dt><dd>projection_x_coordinate</dd><dt><span>units :</span></dt><dd>m</dd></dl></div><div class='xr-var-data'><pre>array([-2610000., -2590000., -2570000., ..., 2570000., 2590000., 2610000.])</pre></div></li><li class='xr-var-item'><div class='xr-var-name'><span class='xr-has-index'>y</span></div><div class='xr-var-dims'>(y)</div><div class='xr-var-dtype'>float64</div><div class='xr-var-preview xr-preview'>-5.414e+06 ... -1.936e+05</div><input id='attrs-58db0cc3-d420-4798-99d0-8cd73f63c24b' class='xr-var-attrs-in' type='checkbox' ><label for='attrs-58db0cc3-d420-4798-99d0-8cd73f63c24b' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-73ec47ce-a443-44f8-b08d-849f52dff480' class='xr-var-data-in' type='checkbox'><label for='data-73ec47ce-a443-44f8-b08d-849f52dff480' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'><dt><span>long_name :</span></dt><dd>y coordinate of projection</dd><dt><span>standard_name :</span></dt><dd>projection_y_coordinate</dd><dt><span>units :</span></dt><dd>m</dd></dl></div><div class='xr-var-data'><pre>array([-5413582.2906, -5393582.2906, -5373582.2906, ..., -233582.2906,\n", + " -213582.2906, -193582.2906])</pre></div></li></ul></div></li><li class='xr-section-item'><input id='section-20e0ce57-99aa-48d6-aa95-8a94f3614d22' class='xr-section-summary-in' type='checkbox' checked><label for='section-20e0ce57-99aa-48d6-aa95-8a94f3614d22' class='xr-section-summary' >Data variables: <span>(2)</span></label><div class='xr-section-inline-details'></div><div class='xr-section-details'><ul class='xr-var-list'><li class='xr-var-item'><div class='xr-var-name'><span>et0</span></div><div class='xr-var-dims'>(time, y, x)</div><div class='xr-var-dtype'>float32</div><div class='xr-var-preview xr-preview'>dask.array<chunksize=(100, 131, 131), meta=np.ndarray></div><input id='attrs-fe9709a7-d6ec-4952-b576-37df83c8301f' class='xr-var-attrs-in' type='checkbox' ><label for='attrs-fe9709a7-d6ec-4952-b576-37df83c8301f' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-92817d44-ea32-46f3-bcca-0477f3d19593' class='xr-var-data-in' type='checkbox'><label for='data-92817d44-ea32-46f3-bcca-0477f3d19593' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'><dt><span>grid_mapping :</span></dt><dd>polar_stereographic</dd><dt><span>long_name :</span></dt><dd>Reference Evapotranspiration</dd><dt><span>units :</span></dt><dd>mm</dd></dl></div><div class='xr-var-data'><table>\n", + " <tr>\n", + " <td>\n", + " <table style=\"border-collapse: collapse;\">\n", + " <thead>\n", + " <tr>\n", + " <td> </td>\n", + " <th> Array </th>\n", + " <th> Chunk </th>\n", + " </tr>\n", + " </thead>\n", + " <tbody>\n", + " \n", + " <tr>\n", + " <th> Bytes </th>\n", + " <td> 5.71 GiB </td>\n", + " <td> 6.55 MiB </td>\n", + " </tr>\n", + " \n", + " <tr>\n", + " <th> Shape </th>\n", + " <td> (22326, 262, 262) </td>\n", + " <td> (100, 131, 131) </td>\n", + " </tr>\n", + " <tr>\n", + " <th> Dask graph </th>\n", + " <td colspan=\"2\"> 896 chunks in 2 graph layers </td>\n", + " </tr>\n", + " <tr>\n", + " <th> Data type </th>\n", + " <td colspan=\"2\"> float32 numpy.ndarray </td>\n", + " </tr>\n", + " </tbody>\n", + " </table>\n", + " </td>\n", + " <td>\n", + " <svg width=\"156\" height=\"146\" style=\"stroke:rgb(0,0,0);stroke-width:1\" >\n", + "\n", + " <!-- Horizontal lines -->\n", + " <line x1=\"10\" y1=\"0\" x2=\"80\" y2=\"70\" style=\"stroke-width:2\" />\n", + " <line x1=\"10\" y1=\"13\" x2=\"80\" y2=\"83\" />\n", + " <line x1=\"10\" y1=\"26\" x2=\"80\" y2=\"96\" style=\"stroke-width:2\" />\n", + "\n", + " <!-- Vertical lines -->\n", + " <line x1=\"10\" y1=\"0\" x2=\"10\" y2=\"26\" style=\"stroke-width:2\" />\n", + " <line x1=\"13\" y1=\"3\" x2=\"13\" y2=\"29\" />\n", + " <line x1=\"17\" y1=\"7\" x2=\"17\" y2=\"33\" />\n", + " <line x1=\"21\" y1=\"11\" x2=\"21\" y2=\"37\" />\n", + " <line x1=\"24\" y1=\"14\" x2=\"24\" y2=\"41\" />\n", + " <line x1=\"28\" y1=\"18\" x2=\"28\" y2=\"44\" />\n", + " <line x1=\"32\" y1=\"22\" x2=\"32\" y2=\"48\" />\n", + " <line x1=\"35\" y1=\"25\" x2=\"35\" y2=\"52\" />\n", + " <line x1=\"39\" y1=\"29\" x2=\"39\" y2=\"55\" />\n", + " <line x1=\"43\" y1=\"33\" x2=\"43\" y2=\"59\" />\n", + " <line x1=\"46\" y1=\"36\" x2=\"46\" y2=\"63\" />\n", + " <line x1=\"50\" y1=\"40\" x2=\"50\" y2=\"66\" />\n", + " <line x1=\"54\" y1=\"44\" x2=\"54\" y2=\"70\" />\n", + " <line x1=\"58\" y1=\"48\" x2=\"58\" y2=\"74\" />\n", + " <line x1=\"62\" y1=\"52\" x2=\"62\" y2=\"78\" />\n", + " <line x1=\"65\" y1=\"55\" x2=\"65\" y2=\"81\" />\n", + " <line x1=\"69\" y1=\"59\" x2=\"69\" y2=\"85\" />\n", + " <line x1=\"73\" y1=\"63\" x2=\"73\" y2=\"89\" />\n", + " <line x1=\"77\" y1=\"67\" x2=\"77\" y2=\"93\" />\n", + " <line x1=\"80\" y1=\"70\" x2=\"80\" y2=\"96\" style=\"stroke-width:2\" />\n", + "\n", + " <!-- Colored Rectangle -->\n", + " <polygon points=\"10.0,0.0 80.58823529411765,70.58823529411765 80.58823529411765,96.78328473700768 10.0,26.195049442890028\" style=\"fill:#8B4903A0;stroke-width:0\"/>\n", + "\n", + " <!-- Horizontal lines -->\n", + " <line x1=\"10\" y1=\"0\" x2=\"36\" y2=\"0\" style=\"stroke-width:2\" />\n", + " <line x1=\"13\" y1=\"3\" x2=\"39\" y2=\"3\" />\n", + " <line x1=\"17\" y1=\"7\" x2=\"43\" y2=\"7\" />\n", + " <line x1=\"21\" y1=\"11\" x2=\"47\" y2=\"11\" />\n", + " <line x1=\"24\" y1=\"14\" x2=\"51\" y2=\"14\" />\n", + " <line x1=\"28\" y1=\"18\" x2=\"54\" y2=\"18\" />\n", + " <line x1=\"32\" y1=\"22\" x2=\"58\" y2=\"22\" />\n", + " <line x1=\"35\" y1=\"25\" x2=\"62\" y2=\"25\" />\n", + " <line x1=\"39\" y1=\"29\" x2=\"65\" y2=\"29\" />\n", + " <line x1=\"43\" y1=\"33\" x2=\"69\" y2=\"33\" />\n", + " <line x1=\"46\" y1=\"36\" x2=\"73\" y2=\"36\" />\n", + " <line x1=\"50\" y1=\"40\" x2=\"76\" y2=\"40\" />\n", + " <line x1=\"54\" y1=\"44\" x2=\"80\" y2=\"44\" />\n", + " <line x1=\"58\" y1=\"48\" x2=\"84\" y2=\"48\" />\n", + " <line x1=\"62\" y1=\"52\" x2=\"88\" y2=\"52\" />\n", + " <line x1=\"65\" y1=\"55\" x2=\"91\" y2=\"55\" />\n", + " <line x1=\"69\" y1=\"59\" x2=\"95\" y2=\"59\" />\n", + " <line x1=\"73\" y1=\"63\" x2=\"99\" y2=\"63\" />\n", + " <line x1=\"77\" y1=\"67\" x2=\"103\" y2=\"67\" />\n", + " <line x1=\"80\" y1=\"70\" x2=\"106\" y2=\"70\" style=\"stroke-width:2\" />\n", + "\n", + " <!-- Vertical lines -->\n", + " <line x1=\"10\" y1=\"0\" x2=\"80\" y2=\"70\" style=\"stroke-width:2\" />\n", + " <line x1=\"23\" y1=\"0\" x2=\"93\" y2=\"70\" />\n", + " <line x1=\"36\" y1=\"0\" x2=\"106\" y2=\"70\" style=\"stroke-width:2\" />\n", + "\n", + " <!-- Colored Rectangle -->\n", + " <polygon points=\"10.0,0.0 36.195049442890024,0.0 106.78328473700768,70.58823529411765 80.58823529411765,70.58823529411765\" style=\"fill:#8B4903A0;stroke-width:0\"/>\n", + "\n", + " <!-- Horizontal lines -->\n", + " <line x1=\"80\" y1=\"70\" x2=\"106\" y2=\"70\" style=\"stroke-width:2\" />\n", + " <line x1=\"80\" y1=\"83\" x2=\"106\" y2=\"83\" />\n", + " <line x1=\"80\" y1=\"96\" x2=\"106\" y2=\"96\" style=\"stroke-width:2\" />\n", + "\n", + " <!-- Vertical lines -->\n", + " <line x1=\"80\" y1=\"70\" x2=\"80\" y2=\"96\" style=\"stroke-width:2\" />\n", + " <line x1=\"93\" y1=\"70\" x2=\"93\" y2=\"96\" />\n", + " <line x1=\"106\" y1=\"70\" x2=\"106\" y2=\"96\" style=\"stroke-width:2\" />\n", + "\n", + " <!-- Colored Rectangle -->\n", + " <polygon points=\"80.58823529411765,70.58823529411765 106.78328473700768,70.58823529411765 106.78328473700768,96.78328473700768 80.58823529411765,96.78328473700768\" style=\"fill:#ECB172A0;stroke-width:0\"/>\n", + "\n", + " <!-- Text -->\n", + " <text x=\"93.685760\" y=\"116.783285\" font-size=\"1.0rem\" font-weight=\"100\" text-anchor=\"middle\" >262</text>\n", + " <text x=\"126.783285\" y=\"83.685760\" font-size=\"1.0rem\" font-weight=\"100\" text-anchor=\"middle\" transform=\"rotate(-90,126.783285,83.685760)\">262</text>\n", + " <text x=\"35.294118\" y=\"81.489167\" font-size=\"1.0rem\" font-weight=\"100\" text-anchor=\"middle\" transform=\"rotate(45,35.294118,81.489167)\">22326</text>\n", + "</svg>\n", + " </td>\n", + " </tr>\n", + "</table></div></li><li class='xr-var-item'><div class='xr-var-name'><span>polar_stereographic</span></div><div class='xr-var-dims'>()</div><div class='xr-var-dtype'>|S64</div><div class='xr-var-preview xr-preview'>...</div><input id='attrs-6eb0b3f3-4c33-46f9-9401-ef7e63d54cc6' class='xr-var-attrs-in' type='checkbox' ><label for='attrs-6eb0b3f3-4c33-46f9-9401-ef7e63d54cc6' title='Show/Hide attributes'><svg class='icon xr-icon-file-text2'><use xlink:href='#icon-file-text2'></use></svg></label><input id='data-c595b9f0-bef4-41b7-9592-21e8d27faaf8' class='xr-var-data-in' type='checkbox'><label for='data-c595b9f0-bef4-41b7-9592-21e8d27faaf8' title='Show/Hide data repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-var-attrs'><dl class='xr-attrs'><dt><span>GeoTransform :</span></dt><dd>-2620000 20000 0 -183582.2906 0 -20000 </dd><dt><span>false_easting :</span></dt><dd>0.0</dd><dt><span>false_northing :</span></dt><dd>0.0</dd><dt><span>grid_mapping_name :</span></dt><dd>polar_stereographic</dd><dt><span>inverse_flattening :</span></dt><dd>298.257223563</dd><dt><span>latitude_of_projection_origin :</span></dt><dd>90.0</dd><dt><span>long_name :</span></dt><dd>CRS definition</dd><dt><span>longitude_of_prime_meridian :</span></dt><dd>0.0</dd><dt><span>semi_major_axis :</span></dt><dd>6378137.0</dd><dt><span>spatial_ref :</span></dt><dd>PROJCS["unnamed",GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]],PROJECTION["Polar_Stereographic"],PARAMETER["latitude_of_origin",64],PARAMETER["central_meridian",-152],PARAMETER["scale_factor",1],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["Meter",1]]</dd><dt><span>standard_parallel :</span></dt><dd>64.0</dd><dt><span>straight_vertical_longitude_from_pole :</span></dt><dd>-152.0</dd></dl></div><div class='xr-var-data'><pre>[1 values with dtype=|S64]</pre></div></li></ul></div></li><li class='xr-section-item'><input id='section-c930f405-ba61-47c9-930f-eccc24a70a8f' class='xr-section-summary-in' type='checkbox' ><label for='section-c930f405-ba61-47c9-930f-eccc24a70a8f' class='xr-section-summary' >Indexes: <span>(3)</span></label><div class='xr-section-inline-details'></div><div class='xr-section-details'><ul class='xr-var-list'><li class='xr-var-item'><div class='xr-index-name'><div>time</div></div><div class='xr-index-preview'>PandasIndex</div><div></div><input id='index-5814c000-c316-4a4a-8c95-29c8ca9188a6' class='xr-index-data-in' type='checkbox'/><label for='index-5814c000-c316-4a4a-8c95-29c8ca9188a6' title='Show/Hide index repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-index-data'><pre>PandasIndex(DatetimeIndex(['1979-04-01', '1979-04-02', '1979-04-03', '1979-04-04',\n", + " '1979-04-05', '1979-04-06', '1979-04-07', '1979-04-08',\n", + " '1979-04-09', '1979-04-10',\n", + " ...\n", + " '2100-09-21', '2100-09-22', '2100-09-23', '2100-09-24',\n", + " '2100-09-25', '2100-09-26', '2100-09-27', '2100-09-28',\n", + " '2100-09-29', '2100-09-30'],\n", + " dtype='datetime64[ns]', name='time', length=22326, freq=None))</pre></div></li><li class='xr-var-item'><div class='xr-index-name'><div>x</div></div><div class='xr-index-preview'>PandasIndex</div><div></div><input id='index-2bfe6a78-4f7d-40fa-a5d4-7396c1fcc04b' class='xr-index-data-in' type='checkbox'/><label for='index-2bfe6a78-4f7d-40fa-a5d4-7396c1fcc04b' title='Show/Hide index repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-index-data'><pre>PandasIndex(Float64Index([-2610000.0, -2590000.0, -2570000.0, -2550000.0, -2530000.0,\n", + " -2510000.0, -2490000.0, -2470000.0, -2450000.0, -2430000.0,\n", + " ...\n", + " 2430000.0, 2450000.0, 2470000.0, 2490000.0, 2510000.0,\n", + " 2530000.0, 2550000.0, 2570000.0, 2590000.0, 2610000.0],\n", + " dtype='float64', name='x', length=262))</pre></div></li><li class='xr-var-item'><div class='xr-index-name'><div>y</div></div><div class='xr-index-preview'>PandasIndex</div><div></div><input id='index-88948772-247f-4dfb-b6e2-6551967a85fe' class='xr-index-data-in' type='checkbox'/><label for='index-88948772-247f-4dfb-b6e2-6551967a85fe' title='Show/Hide index repr'><svg class='icon xr-icon-database'><use xlink:href='#icon-database'></use></svg></label><div class='xr-index-data'><pre>PandasIndex(Float64Index([ -5413582.2906, -5393582.2906, -5373582.2906,\n", + " -5353582.2906, -5333582.2906, -5313582.2906,\n", + " -5293582.2906, -5273582.2906, -5253582.2906,\n", + " -5233582.2906,\n", + " ...\n", + " -373582.29059999995, -353582.29059999995, -333582.29059999995,\n", + " -313582.29059999995, -293582.29059999995, -273582.29059999995,\n", + " -253582.29059999995, -233582.29059999995, -213582.29059999995,\n", + " -193582.29059999995],\n", + " dtype='float64', name='y', length=262))</pre></div></li></ul></div></li><li class='xr-section-item'><input id='section-d4beab0b-2f1f-4996-9e49-315e6876de0b' class='xr-section-summary-in' type='checkbox' ><label for='section-d4beab0b-2f1f-4996-9e49-315e6876de0b' class='xr-section-summary' >Attributes: <span>(27)</span></label><div class='xr-section-inline-details'></div><div class='xr-section-details'><dl class='xr-attrs'><dt><span>Conventions :</span></dt><dd>CF</dd><dt><span>DODS.strlen :</span></dt><dd>0</dd><dt><span>Metadata_Conventions :</span></dt><dd>Unidata Dataset Discovery v1.0</dd><dt><span>NCO :</span></dt><dd>"4.5.4"</dd><dt><span>acknowledgment :</span></dt><dd>NULL</dd><dt><span>cdm_data_type :</span></dt><dd>grid</dd><dt><span>contact :</span></dt><dd>pbieniek at alaska.edu</dd><dt><span>creator_email :</span></dt><dd>pbieniek@alaska.edu</dd><dt><span>creator_name :</span></dt><dd>Peter Bieniek</dd><dt><span>date_issued :</span></dt><dd></dd><dt><span>geospatial_lat_max :</span></dt><dd>88.26</dd><dt><span>geospatial_lat_min :</span></dt><dd>37.23</dd><dt><span>geospatial_lon_max :</span></dt><dd>122.3</dd><dt><span>geospatial_lon_min :</span></dt><dd>-65.4</dd><dt><span>history :</span></dt><dd>Tue Aug 25 18:39:00 2020: ncks -4 --cnk_plc=nco --cnk_map=rew --fix_rec_dmn=time -L 1 ET0_1979_gfdl_hist.nc compressed/ET0_1979_gfdl_hist.nc</dd><dt><span>id :</span></dt><dd>cida.usgs.gov/gfdl_historical_simulation</dd><dt><span>license :</span></dt><dd>Freely available</dd><dt><span>naming_authority :</span></dt><dd>cida.usgs.gov</dd><dt><span>project :</span></dt><dd>Assessing Seasonal Wildfire Forecasting Methods in Alaska</dd><dt><span>publication :</span></dt><dd>Ziel, R.H.; Bieniek, P.A.; Bhatt, U.S.; Strader, H.; Rupp, T.S.; York, A. A Comparison of Fire Weather Indices with MODIS Fire Days for the Natural Regions of Alaska. Forests 2020, 11, 516.</dd><dt><span>publisher_email :</span></dt><dd>wwatkins@usgs.gov</dd><dt><span>publisher_name :</span></dt><dd>David Watkins</dd><dt><span>publisher_url :</span></dt><dd>https://water.usgs.gov/</dd><dt><span>source :</span></dt><dd>Dynamically Downscaled GFDL-CM3 Historical and RCP 8.5</dd><dt><span>time_coverage_end :</span></dt><dd></dd><dt><span>time_coverage_start :</span></dt><dd></dd><dt><span>title :</span></dt><dd>Gridded 20km Daily Reference Evapotranspiration for the State of Alaska from 1979 to 2017</dd></dl></div></li></ul></div></div>" + ], + "text/plain": [ + "<xarray.Dataset>\n", + "Dimensions: (time: 22326, y: 262, x: 262)\n", + "Coordinates:\n", + " lat (y, x) float32 dask.array<chunksize=(131, 131), meta=np.ndarray>\n", + " lon (y, x) float32 dask.array<chunksize=(131, 131), meta=np.ndarray>\n", + " * time (time) datetime64[ns] 1979-04-01 ... 2100-09-30\n", + " * x (x) float64 -2.61e+06 -2.59e+06 ... 2.59e+06 2.61e+06\n", + " * y (y) float64 -5.414e+06 -5.394e+06 ... -1.936e+05\n", + "Data variables:\n", + " et0 (time, y, x) float32 dask.array<chunksize=(100, 131, 131), meta=np.ndarray>\n", + " polar_stereographic |S64 ...\n", + "Attributes: (12/27)\n", + " Conventions: CF\n", + " DODS.strlen: 0\n", + " Metadata_Conventions: Unidata Dataset Discovery v1.0\n", + " NCO: \"4.5.4\"\n", + " acknowledgment: NULL\n", + " cdm_data_type: grid\n", + " ... ...\n", + " publisher_name: David Watkins\n", + " publisher_url: https://water.usgs.gov/\n", + " source: Dynamically Downscaled GFDL-CM3 Historical and RCP...\n", + " time_coverage_end: \n", + " time_coverage_start: \n", + " title: Gridded 20km Daily Reference Evapotranspiration fo..." + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "# open and view zarr dataset\n", "fs2 = fsspec.filesystem('s3', anon=True, endpoint_url='https://usgs.osn.mghpcc.org/')\n", @@ -178,12 +1498,26 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "id": "ab91268f-7200-4cb1-979a-c7d75531d2c0", "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "name of X dimension: x\n", + "\n", + "name of Y dimension: y\n", + "\n", + "name of T dimension: time\n", + "\n", + "Dimension dictionary: {'X': 'x', 'Y': 'y', 'T': 'time'}\n" + ] + } + ], "source": [ "dims_auto_extract = ['X', 'Y', 'T']\n", "def extract_dim(ds, d):\n", @@ -215,7 +1549,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "id": "8307fb3a-ca11-4c19-bcdc-c95ac7275b1c", "metadata": { "tags": [] @@ -236,7 +1570,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "id": "4eb4d027-4266-4a0b-8f16-bacfbef06242", "metadata": { "tags": [] @@ -261,7 +1595,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "id": "c7de2681-88c2-4597-857c-8f169c596f8b", "metadata": { "tags": [] @@ -295,12 +1629,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "id": "d46805e0-8e94-4ebe-aa01-d9a2d7051459", "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[-179.9994659423828, 37.233001708984375, 179.9990692138672, 88.26099395751953]\n" + ] + } + ], "source": [ "# pull out lat/lon bbox for data\n", "# coordinates must be from WGS 84 datum\n", @@ -326,12 +1668,21 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "id": "41a84995-867c-4152-8c57-85e3758bbb77", "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "min: 1979-04-01 00:00:00 \n", + "max: 2100-09-30 00:00:00\n" + ] + } + ], "source": [ "# pull out first and last timestamps\n", "temporal_extent_lower = pd.Timestamp(ds[dim_names_dict['T']].data.min())\n", @@ -343,7 +1694,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "id": "1b1e37c4-5348-46ad-abc9-e005b5d6c02b", "metadata": { "tags": [] @@ -363,12 +1714,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 14, "id": "7e96811b-95ae-406a-9728-55fc429d4e1f", "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "existing collection opened\n" + ] + } + ], "source": [ "if catalog.get_child(collection_id):\n", " collection = catalog.get_child(collection_id)\n", @@ -394,7 +1753,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 15, "id": "094832af-d22b-4359-b0f6-cf687acce5cc", "metadata": { "tags": [] @@ -412,7 +1771,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 16, "id": "0c298d07-f234-4a08-986d-87f4a39e9ae6", "metadata": { "tags": [] @@ -438,7 +1797,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 17, "id": "fc00946d-2880-491d-9b3b-3aeeb4414d6c", "metadata": { "tags": [] @@ -459,12 +1818,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 18, "id": "120a4914-3302-44a5-a282-0308ac84f040", "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['y', 'x', 'time']\n" + ] + } + ], "source": [ "# list out dataset dimensions\n", "# When writing data to Zarr, Xarray sets this attribute on all variables based on the variable dimensions. When reading a Zarr group, Xarray looks for this attribute on all arrays,\n", @@ -475,12 +1842,20 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 19, "id": "00a18a29-fb9a-4b56-8009-493122997b16", "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[-2610000.0, -5413582.2906, 2610000.0, -193582.29059999995]\n" + ] + } + ], "source": [ "# get x, y bounds for extent of those dimensions (required)\n", "xy_bounds = [ds[dim_names_dict['X']].data.min().astype(float).item(), ds[dim_names_dict['Y']].data.min().astype(float).item(), ds[dim_names_dict['X']].data.max().astype(float).item(), ds[dim_names_dict['Y']].data.max().astype(float).item()]\n", @@ -489,7 +1864,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 25, "id": "0f49d6d7-9e30-4144-909b-fa1238e6c77a", "metadata": { "tags": [] @@ -502,6 +1877,7 @@ " unique_steps = np.unique(diffs)\n", " # set step - if all steps are the same length\n", " # datacube spec specifies to use null for irregularly spaced steps\n", + " print(unique_steps)\n", " if len(unique_steps)==1:\n", " step = unique_steps[0].astype(float).item()\n", " else:\n", @@ -509,6 +1885,279 @@ " return(step)" ] }, + { + "cell_type": "code", + "execution_count": 37, + "id": "04b4124e-9e0d-4092-b535-5db305b2c2d8", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array(['2022-08-10T00:00:00.000000000', '2022-08-11T00:00:00.000000000',\n", + " '2022-08-12T00:00:00.000000000', '2022-08-13T00:00:00.000000000',\n", + " '2022-08-14T00:00:00.000000000', '2022-08-15T00:00:00.000000000',\n", + " '2022-08-16T00:00:00.000000000', '2022-08-17T00:00:00.000000000',\n", + " '2022-08-18T00:00:00.000000000', '2022-08-19T00:00:00.000000000',\n", + " '2022-08-20T00:00:00.000000000', '2022-08-21T00:00:00.000000000',\n", + " '2022-08-22T00:00:00.000000000', '2022-08-23T00:00:00.000000000',\n", + " '2022-08-24T00:00:00.000000000', '2022-08-25T00:00:00.000000000',\n", + " '2022-08-26T00:00:00.000000000', '2022-08-27T00:00:00.000000000',\n", + " '2022-08-28T00:00:00.000000000', '2022-08-29T00:00:00.000000000',\n", + " '2022-08-30T00:00:00.000000000', '2022-08-31T00:00:00.000000000',\n", + " '2022-09-01T00:00:00.000000000', '2022-09-02T00:00:00.000000000',\n", + " '2022-09-03T00:00:00.000000000', '2022-09-04T00:00:00.000000000',\n", + " '2022-09-05T00:00:00.000000000', '2022-09-06T00:00:00.000000000',\n", + " '2022-09-07T00:00:00.000000000', '2022-09-08T00:00:00.000000000',\n", + " '2022-09-09T00:00:00.000000000', '2022-09-10T00:00:00.000000000',\n", + " '2022-09-11T00:00:00.000000000', '2022-09-12T00:00:00.000000000',\n", + " '2022-09-13T00:00:00.000000000', '2022-09-14T00:00:00.000000000',\n", + " '2022-09-15T00:00:00.000000000', '2022-09-16T00:00:00.000000000',\n", + " '2022-09-17T00:00:00.000000000', '2022-09-18T00:00:00.000000000',\n", + " '2022-09-19T00:00:00.000000000', '2022-09-20T00:00:00.000000000',\n", + " '2022-09-21T00:00:00.000000000', '2022-09-22T00:00:00.000000000',\n", + " '2022-09-23T00:00:00.000000000', '2022-09-24T00:00:00.000000000',\n", + " '2022-09-25T00:00:00.000000000', '2022-09-26T00:00:00.000000000',\n", + " '2022-09-27T00:00:00.000000000', '2022-09-28T00:00:00.000000000',\n", + " '2022-09-29T00:00:00.000000000', '2022-09-30T00:00:00.000000000',\n", + " '2023-04-01T00:00:00.000000000', '2023-04-02T00:00:00.000000000',\n", + " '2023-04-03T00:00:00.000000000', '2023-04-04T00:00:00.000000000',\n", + " '2023-04-05T00:00:00.000000000', '2023-04-06T00:00:00.000000000',\n", + " '2023-04-07T00:00:00.000000000', '2023-04-08T00:00:00.000000000',\n", + " '2023-04-09T00:00:00.000000000', '2023-04-10T00:00:00.000000000',\n", + " '2023-04-11T00:00:00.000000000', '2023-04-12T00:00:00.000000000',\n", + " '2023-04-13T00:00:00.000000000', '2023-04-14T00:00:00.000000000',\n", + " '2023-04-15T00:00:00.000000000', '2023-04-16T00:00:00.000000000',\n", + " '2023-04-17T00:00:00.000000000', '2023-04-18T00:00:00.000000000',\n", + " '2023-04-19T00:00:00.000000000', '2023-04-20T00:00:00.000000000',\n", + " '2023-04-21T00:00:00.000000000', '2023-04-22T00:00:00.000000000',\n", + " '2023-04-23T00:00:00.000000000', '2023-04-24T00:00:00.000000000',\n", + " '2023-04-25T00:00:00.000000000', '2023-04-26T00:00:00.000000000',\n", + " '2023-04-27T00:00:00.000000000', '2023-04-28T00:00:00.000000000',\n", + " '2023-04-29T00:00:00.000000000', '2023-04-30T00:00:00.000000000',\n", + " '2023-05-01T00:00:00.000000000', '2023-05-02T00:00:00.000000000',\n", + " '2023-05-03T00:00:00.000000000', '2023-05-04T00:00:00.000000000',\n", + " '2023-05-05T00:00:00.000000000', '2023-05-06T00:00:00.000000000',\n", + " '2023-05-07T00:00:00.000000000', '2023-05-08T00:00:00.000000000',\n", + " '2023-05-09T00:00:00.000000000', '2023-05-10T00:00:00.000000000',\n", + " '2023-05-11T00:00:00.000000000', '2023-05-12T00:00:00.000000000',\n", + " '2023-05-13T00:00:00.000000000', '2023-05-14T00:00:00.000000000',\n", + " '2023-05-15T00:00:00.000000000', '2023-05-16T00:00:00.000000000',\n", + " '2023-05-17T00:00:00.000000000', '2023-05-18T00:00:00.000000000',\n", + " '2023-05-19T00:00:00.000000000', '2023-05-20T00:00:00.000000000',\n", + " '2023-05-21T00:00:00.000000000', '2023-05-22T00:00:00.000000000',\n", + " '2023-05-23T00:00:00.000000000', '2023-05-24T00:00:00.000000000',\n", + " '2023-05-25T00:00:00.000000000', '2023-05-26T00:00:00.000000000',\n", + " '2023-05-27T00:00:00.000000000', '2023-05-28T00:00:00.000000000',\n", + " '2023-05-29T00:00:00.000000000', '2023-05-30T00:00:00.000000000',\n", + " '2023-05-31T00:00:00.000000000', '2023-06-01T00:00:00.000000000',\n", + " '2023-06-02T00:00:00.000000000', '2023-06-03T00:00:00.000000000',\n", + " '2023-06-04T00:00:00.000000000', '2023-06-05T00:00:00.000000000',\n", + " '2023-06-06T00:00:00.000000000', '2023-06-07T00:00:00.000000000',\n", + " '2023-06-08T00:00:00.000000000', '2023-06-09T00:00:00.000000000',\n", + " '2023-06-10T00:00:00.000000000', '2023-06-11T00:00:00.000000000',\n", + " '2023-06-12T00:00:00.000000000', '2023-06-13T00:00:00.000000000',\n", + " '2023-06-14T00:00:00.000000000', '2023-06-15T00:00:00.000000000',\n", + " '2023-06-16T00:00:00.000000000', '2023-06-17T00:00:00.000000000',\n", + " '2023-06-18T00:00:00.000000000', '2023-06-19T00:00:00.000000000',\n", + " '2023-06-20T00:00:00.000000000', '2023-06-21T00:00:00.000000000',\n", + " '2023-06-22T00:00:00.000000000', '2023-06-23T00:00:00.000000000',\n", + " '2023-06-24T00:00:00.000000000', '2023-06-25T00:00:00.000000000',\n", + " '2023-06-26T00:00:00.000000000', '2023-06-27T00:00:00.000000000',\n", + " '2023-06-28T00:00:00.000000000', '2023-06-29T00:00:00.000000000',\n", + " '2023-06-30T00:00:00.000000000', '2023-07-01T00:00:00.000000000',\n", + " '2023-07-02T00:00:00.000000000', '2023-07-03T00:00:00.000000000',\n", + " '2023-07-04T00:00:00.000000000', '2023-07-05T00:00:00.000000000',\n", + " '2023-07-06T00:00:00.000000000', '2023-07-07T00:00:00.000000000',\n", + " '2023-07-08T00:00:00.000000000', '2023-07-09T00:00:00.000000000',\n", + " '2023-07-10T00:00:00.000000000', '2023-07-11T00:00:00.000000000',\n", + " '2023-07-12T00:00:00.000000000', '2023-07-13T00:00:00.000000000',\n", + " '2023-07-14T00:00:00.000000000', '2023-07-15T00:00:00.000000000',\n", + " '2023-07-16T00:00:00.000000000', '2023-07-17T00:00:00.000000000',\n", + " '2023-07-18T00:00:00.000000000', '2023-07-19T00:00:00.000000000',\n", + " '2023-07-20T00:00:00.000000000', '2023-07-21T00:00:00.000000000',\n", + " '2023-07-22T00:00:00.000000000', '2023-07-23T00:00:00.000000000',\n", + " '2023-07-24T00:00:00.000000000', '2023-07-25T00:00:00.000000000',\n", + " '2023-07-26T00:00:00.000000000', '2023-07-27T00:00:00.000000000',\n", + " '2023-07-28T00:00:00.000000000', '2023-07-29T00:00:00.000000000',\n", + " '2023-07-30T00:00:00.000000000', '2023-07-31T00:00:00.000000000',\n", + " '2023-08-01T00:00:00.000000000', '2023-08-02T00:00:00.000000000',\n", + " '2023-08-03T00:00:00.000000000', '2023-08-04T00:00:00.000000000',\n", + " '2023-08-05T00:00:00.000000000', '2023-08-06T00:00:00.000000000',\n", + " '2023-08-07T00:00:00.000000000', '2023-08-08T00:00:00.000000000',\n", + " '2023-08-09T00:00:00.000000000', '2023-08-10T00:00:00.000000000',\n", + " '2023-08-11T00:00:00.000000000', '2023-08-12T00:00:00.000000000',\n", + " '2023-08-13T00:00:00.000000000', '2023-08-14T00:00:00.000000000',\n", + " '2023-08-15T00:00:00.000000000', '2023-08-16T00:00:00.000000000',\n", + " '2023-08-17T00:00:00.000000000', '2023-08-18T00:00:00.000000000',\n", + " '2023-08-19T00:00:00.000000000', '2023-08-20T00:00:00.000000000',\n", + " '2023-08-21T00:00:00.000000000', '2023-08-22T00:00:00.000000000',\n", + " '2023-08-23T00:00:00.000000000', '2023-08-24T00:00:00.000000000',\n", + " '2023-08-25T00:00:00.000000000', '2023-08-26T00:00:00.000000000',\n", + " '2023-08-27T00:00:00.000000000', '2023-08-28T00:00:00.000000000',\n", + " '2023-08-29T00:00:00.000000000', '2023-08-30T00:00:00.000000000',\n", + " '2023-08-31T00:00:00.000000000', '2023-09-01T00:00:00.000000000',\n", + " '2023-09-02T00:00:00.000000000', '2023-09-03T00:00:00.000000000',\n", + " '2023-09-04T00:00:00.000000000', '2023-09-05T00:00:00.000000000',\n", + " '2023-09-06T00:00:00.000000000', '2023-09-07T00:00:00.000000000',\n", + " '2023-09-08T00:00:00.000000000', '2023-09-09T00:00:00.000000000',\n", + " '2023-09-10T00:00:00.000000000', '2023-09-11T00:00:00.000000000',\n", + " '2023-09-12T00:00:00.000000000', '2023-09-13T00:00:00.000000000',\n", + " '2023-09-14T00:00:00.000000000', '2023-09-15T00:00:00.000000000',\n", + " '2023-09-16T00:00:00.000000000', '2023-09-17T00:00:00.000000000',\n", + " '2023-09-18T00:00:00.000000000', '2023-09-19T00:00:00.000000000',\n", + " '2023-09-20T00:00:00.000000000', '2023-09-21T00:00:00.000000000',\n", + " '2023-09-22T00:00:00.000000000', '2023-09-23T00:00:00.000000000',\n", + " '2023-09-24T00:00:00.000000000', '2023-09-25T00:00:00.000000000',\n", + " '2023-09-26T00:00:00.000000000', '2023-09-27T00:00:00.000000000',\n", + " '2023-09-28T00:00:00.000000000', '2023-09-29T00:00:00.000000000',\n", + " '2023-09-30T00:00:00.000000000', '2024-04-01T00:00:00.000000000',\n", + " '2024-04-02T00:00:00.000000000', '2024-04-03T00:00:00.000000000',\n", + " '2024-04-04T00:00:00.000000000', '2024-04-05T00:00:00.000000000',\n", + " '2024-04-06T00:00:00.000000000', '2024-04-07T00:00:00.000000000',\n", + " '2024-04-08T00:00:00.000000000', '2024-04-09T00:00:00.000000000',\n", + " '2024-04-10T00:00:00.000000000', '2024-04-11T00:00:00.000000000',\n", + " '2024-04-12T00:00:00.000000000', '2024-04-13T00:00:00.000000000',\n", + " '2024-04-14T00:00:00.000000000', '2024-04-15T00:00:00.000000000',\n", + " '2024-04-16T00:00:00.000000000', '2024-04-17T00:00:00.000000000',\n", + " '2024-04-18T00:00:00.000000000', '2024-04-19T00:00:00.000000000',\n", + " '2024-04-20T00:00:00.000000000', '2024-04-21T00:00:00.000000000',\n", + " '2024-04-22T00:00:00.000000000', '2024-04-23T00:00:00.000000000',\n", + " '2024-04-24T00:00:00.000000000', '2024-04-25T00:00:00.000000000',\n", + " '2024-04-26T00:00:00.000000000', '2024-04-27T00:00:00.000000000',\n", + " '2024-04-28T00:00:00.000000000', '2024-04-29T00:00:00.000000000',\n", + " '2024-04-30T00:00:00.000000000', '2024-05-01T00:00:00.000000000',\n", + " '2024-05-02T00:00:00.000000000', '2024-05-03T00:00:00.000000000',\n", + " '2024-05-04T00:00:00.000000000', '2024-05-05T00:00:00.000000000',\n", + " '2024-05-06T00:00:00.000000000', '2024-05-07T00:00:00.000000000',\n", + " '2024-05-08T00:00:00.000000000', '2024-05-09T00:00:00.000000000',\n", + " '2024-05-10T00:00:00.000000000', '2024-05-11T00:00:00.000000000',\n", + " '2024-05-12T00:00:00.000000000', '2024-05-13T00:00:00.000000000',\n", + " '2024-05-14T00:00:00.000000000', '2024-05-15T00:00:00.000000000',\n", + " '2024-05-16T00:00:00.000000000', '2024-05-17T00:00:00.000000000',\n", + " '2024-05-18T00:00:00.000000000', '2024-05-19T00:00:00.000000000',\n", + " '2024-05-20T00:00:00.000000000', '2024-05-21T00:00:00.000000000',\n", + " '2024-05-22T00:00:00.000000000', '2024-05-23T00:00:00.000000000',\n", + " '2024-05-24T00:00:00.000000000', '2024-05-25T00:00:00.000000000',\n", + " '2024-05-26T00:00:00.000000000', '2024-05-27T00:00:00.000000000',\n", + " '2024-05-28T00:00:00.000000000', '2024-05-29T00:00:00.000000000',\n", + " '2024-05-30T00:00:00.000000000', '2024-05-31T00:00:00.000000000',\n", + " '2024-06-01T00:00:00.000000000', '2024-06-02T00:00:00.000000000',\n", + " '2024-06-03T00:00:00.000000000', '2024-06-04T00:00:00.000000000',\n", + " '2024-06-05T00:00:00.000000000', '2024-06-06T00:00:00.000000000',\n", + " '2024-06-07T00:00:00.000000000', '2024-06-08T00:00:00.000000000',\n", + " '2024-06-09T00:00:00.000000000', '2024-06-10T00:00:00.000000000',\n", + " '2024-06-11T00:00:00.000000000', '2024-06-12T00:00:00.000000000',\n", + " '2024-06-13T00:00:00.000000000', '2024-06-14T00:00:00.000000000',\n", + " '2024-06-15T00:00:00.000000000', '2024-06-16T00:00:00.000000000',\n", + " '2024-06-17T00:00:00.000000000', '2024-06-18T00:00:00.000000000',\n", + " '2024-06-19T00:00:00.000000000', '2024-06-20T00:00:00.000000000',\n", + " '2024-06-21T00:00:00.000000000', '2024-06-22T00:00:00.000000000',\n", + " '2024-06-23T00:00:00.000000000', '2024-06-24T00:00:00.000000000',\n", + " '2024-06-25T00:00:00.000000000', '2024-06-26T00:00:00.000000000',\n", + " '2024-06-27T00:00:00.000000000', '2024-06-28T00:00:00.000000000',\n", + " '2024-06-29T00:00:00.000000000', '2024-06-30T00:00:00.000000000',\n", + " '2024-07-01T00:00:00.000000000', '2024-07-02T00:00:00.000000000',\n", + " '2024-07-03T00:00:00.000000000', '2024-07-04T00:00:00.000000000',\n", + " '2024-07-05T00:00:00.000000000', '2024-07-06T00:00:00.000000000',\n", + " '2024-07-07T00:00:00.000000000', '2024-07-08T00:00:00.000000000',\n", + " '2024-07-09T00:00:00.000000000', '2024-07-10T00:00:00.000000000',\n", + " '2024-07-11T00:00:00.000000000', '2024-07-12T00:00:00.000000000',\n", + " '2024-07-13T00:00:00.000000000', '2024-07-14T00:00:00.000000000',\n", + " '2024-07-15T00:00:00.000000000', '2024-07-16T00:00:00.000000000',\n", + " '2024-07-17T00:00:00.000000000', '2024-07-18T00:00:00.000000000',\n", + " '2024-07-19T00:00:00.000000000', '2024-07-20T00:00:00.000000000',\n", + " '2024-07-21T00:00:00.000000000', '2024-07-22T00:00:00.000000000',\n", + " '2024-07-23T00:00:00.000000000', '2024-07-24T00:00:00.000000000',\n", + " '2024-07-25T00:00:00.000000000', '2024-07-26T00:00:00.000000000',\n", + " '2024-07-27T00:00:00.000000000', '2024-07-28T00:00:00.000000000',\n", + " '2024-07-29T00:00:00.000000000', '2024-07-30T00:00:00.000000000',\n", + " '2024-07-31T00:00:00.000000000', '2024-08-01T00:00:00.000000000',\n", + " '2024-08-02T00:00:00.000000000', '2024-08-03T00:00:00.000000000',\n", + " '2024-08-04T00:00:00.000000000', '2024-08-05T00:00:00.000000000',\n", + " '2024-08-06T00:00:00.000000000', '2024-08-07T00:00:00.000000000',\n", + " '2024-08-08T00:00:00.000000000', '2024-08-09T00:00:00.000000000',\n", + " '2024-08-10T00:00:00.000000000', '2024-08-11T00:00:00.000000000',\n", + " '2024-08-12T00:00:00.000000000', '2024-08-13T00:00:00.000000000',\n", + " '2024-08-14T00:00:00.000000000', '2024-08-15T00:00:00.000000000',\n", + " '2024-08-16T00:00:00.000000000', '2024-08-17T00:00:00.000000000',\n", + " '2024-08-18T00:00:00.000000000', '2024-08-19T00:00:00.000000000',\n", + " '2024-08-20T00:00:00.000000000', '2024-08-21T00:00:00.000000000',\n", + " '2024-08-22T00:00:00.000000000', '2024-08-23T00:00:00.000000000',\n", + " '2024-08-24T00:00:00.000000000', '2024-08-25T00:00:00.000000000',\n", + " '2024-08-26T00:00:00.000000000', '2024-08-27T00:00:00.000000000',\n", + " '2024-08-28T00:00:00.000000000', '2024-08-29T00:00:00.000000000',\n", + " '2024-08-30T00:00:00.000000000', '2024-08-31T00:00:00.000000000',\n", + " '2024-09-01T00:00:00.000000000', '2024-09-02T00:00:00.000000000',\n", + " '2024-09-03T00:00:00.000000000', '2024-09-04T00:00:00.000000000',\n", + " '2024-09-05T00:00:00.000000000', '2024-09-06T00:00:00.000000000',\n", + " '2024-09-07T00:00:00.000000000', '2024-09-08T00:00:00.000000000',\n", + " '2024-09-09T00:00:00.000000000', '2024-09-10T00:00:00.000000000',\n", + " '2024-09-11T00:00:00.000000000', '2024-09-12T00:00:00.000000000',\n", + " '2024-09-13T00:00:00.000000000', '2024-09-14T00:00:00.000000000',\n", + " '2024-09-15T00:00:00.000000000', '2024-09-16T00:00:00.000000000',\n", + " '2024-09-17T00:00:00.000000000', '2024-09-18T00:00:00.000000000',\n", + " '2024-09-19T00:00:00.000000000', '2024-09-20T00:00:00.000000000',\n", + " '2024-09-21T00:00:00.000000000', '2024-09-22T00:00:00.000000000',\n", + " '2024-09-23T00:00:00.000000000', '2024-09-24T00:00:00.000000000',\n", + " '2024-09-25T00:00:00.000000000', '2024-09-26T00:00:00.000000000',\n", + " '2024-09-27T00:00:00.000000000', '2024-09-28T00:00:00.000000000',\n", + " '2024-09-29T00:00:00.000000000', '2024-09-30T00:00:00.000000000',\n", + " '2025-04-01T00:00:00.000000000', '2025-04-02T00:00:00.000000000',\n", + " '2025-04-03T00:00:00.000000000', '2025-04-04T00:00:00.000000000',\n", + " '2025-04-05T00:00:00.000000000', '2025-04-06T00:00:00.000000000',\n", + " '2025-04-07T00:00:00.000000000', '2025-04-08T00:00:00.000000000',\n", + " '2025-04-09T00:00:00.000000000', '2025-04-10T00:00:00.000000000',\n", + " '2025-04-11T00:00:00.000000000', '2025-04-12T00:00:00.000000000',\n", + " '2025-04-13T00:00:00.000000000', '2025-04-14T00:00:00.000000000',\n", + " '2025-04-15T00:00:00.000000000', '2025-04-16T00:00:00.000000000',\n", + " '2025-04-17T00:00:00.000000000', '2025-04-18T00:00:00.000000000',\n", + " '2025-04-19T00:00:00.000000000', '2025-04-20T00:00:00.000000000',\n", + " '2025-04-21T00:00:00.000000000', '2025-04-22T00:00:00.000000000',\n", + " '2025-04-23T00:00:00.000000000', '2025-04-24T00:00:00.000000000',\n", + " '2025-04-25T00:00:00.000000000', '2025-04-26T00:00:00.000000000',\n", + " '2025-04-27T00:00:00.000000000', '2025-04-28T00:00:00.000000000',\n", + " '2025-04-29T00:00:00.000000000', '2025-04-30T00:00:00.000000000',\n", + " '2025-05-01T00:00:00.000000000', '2025-05-02T00:00:00.000000000',\n", + " '2025-05-03T00:00:00.000000000', '2025-05-04T00:00:00.000000000',\n", + " '2025-05-05T00:00:00.000000000', '2025-05-06T00:00:00.000000000',\n", + " '2025-05-07T00:00:00.000000000', '2025-05-08T00:00:00.000000000',\n", + " '2025-05-09T00:00:00.000000000', '2025-05-10T00:00:00.000000000',\n", + " '2025-05-11T00:00:00.000000000', '2025-05-12T00:00:00.000000000',\n", + " '2025-05-13T00:00:00.000000000', '2025-05-14T00:00:00.000000000',\n", + " '2025-05-15T00:00:00.000000000', '2025-05-16T00:00:00.000000000',\n", + " '2025-05-17T00:00:00.000000000', '2025-05-18T00:00:00.000000000',\n", + " '2025-05-19T00:00:00.000000000', '2025-05-20T00:00:00.000000000',\n", + " '2025-05-21T00:00:00.000000000', '2025-05-22T00:00:00.000000000',\n", + " '2025-05-23T00:00:00.000000000', '2025-05-24T00:00:00.000000000',\n", + " '2025-05-25T00:00:00.000000000', '2025-05-26T00:00:00.000000000',\n", + " '2025-05-27T00:00:00.000000000', '2025-05-28T00:00:00.000000000',\n", + " '2025-05-29T00:00:00.000000000', '2025-05-30T00:00:00.000000000',\n", + " '2025-05-31T00:00:00.000000000', '2025-06-01T00:00:00.000000000',\n", + " '2025-06-02T00:00:00.000000000', '2025-06-03T00:00:00.000000000',\n", + " '2025-06-04T00:00:00.000000000', '2025-06-05T00:00:00.000000000',\n", + " '2025-06-06T00:00:00.000000000', '2025-06-07T00:00:00.000000000',\n", + " '2025-06-08T00:00:00.000000000', '2025-06-09T00:00:00.000000000',\n", + " '2025-06-10T00:00:00.000000000', '2025-06-11T00:00:00.000000000',\n", + " '2025-06-12T00:00:00.000000000', '2025-06-13T00:00:00.000000000',\n", + " '2025-06-14T00:00:00.000000000', '2025-06-15T00:00:00.000000000',\n", + " '2025-06-16T00:00:00.000000000', '2025-06-17T00:00:00.000000000',\n", + " '2025-06-18T00:00:00.000000000', '2025-06-19T00:00:00.000000000',\n", + " '2025-06-20T00:00:00.000000000', '2025-06-21T00:00:00.000000000'],\n", + " dtype='datetime64[ns]')" + ] + }, + "execution_count": 37, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ds.time.values[8000:8500]" + ] + }, { "cell_type": "code", "execution_count": null, diff --git a/workflows/archive/cprep_create_collection_from_zarr.ipynb b/workflows/archive/cprep_create_collection_from_zarr.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..2b0d9d855041911fa4f20e36a27d464ba70ccdfa --- /dev/null +++ b/workflows/archive/cprep_create_collection_from_zarr.ipynb @@ -0,0 +1,1231 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "6c10e07b-1e60-4926-af1d-fa75dc78e5d4", + "metadata": { + "tags": [] + }, + "source": [ + "# CONUS404 Daily Zarr -> Collection Exploratory Workflow\n", + "This is a workflow for transforming the CONUS404 daily zarr dataset into a [STAC collection](https://github.com/radiantearth/stac-spec/blob/master/collection-spec/collection-spec.md). We use the [datacube extension](https://github.com/stac-extensions/datacube) to define the spatial and temporal dimensions of the zarr store, as well as the variables it contains.\n", + "\n", + "To simplify this workflow so that it can scale to many datasets, a few simplifying suggestions and assumptions are made:\n", + "1. For USGS data, we can use the CC0-1.0 license. For all other data we can use Unlicense. Ref: https://spdx.org/licenses/\n", + "2. I am assuming all coordinates are from the WGS84 datum if not specified." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "201e0945-de55-45ff-b095-c2af009a4e62", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "import pystac\n", + "from pystac.extensions.datacube import CollectionDatacubeExtension, AssetDatacubeExtension, AdditionalDimension, DatacubeExtension\n", + "import xarray as xr\n", + "import cf_xarray\n", + "import os\n", + "import fsspec\n", + "import cf_xarray\n", + "import hvplot.xarray\n", + "import pandas as pd\n", + "import json\n", + "import numpy as np\n", + "import metpy\n", + "import cartopy.crs as ccrs\n", + "import cfunits\n", + "import json" + ] + }, + { + "cell_type": "markdown", + "id": "9e9cff62-0e60-4e59-8994-aece90c2bbc6", + "metadata": {}, + "source": [ + "## Explore list of files to incorporate" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0bfe4a5b-72da-4f0a-93f8-5c899cc2602b", + "metadata": {}, + "outputs": [], + "source": [ + "# get list of zarr stores to create collections for - we will run through one\n", + "# as an example, then iterate through every item in the list\n", + "fs = fsspec.filesystem('s3', requester_pays=True)\n", + "s3_path_list = fs.ls('s3://nhgf-development/workspace/DataConversion/gdp/cprep')\n", + "zarr_name_list = [fp.split('/')[-1] for fp in s3_path_list]\n", + "print(f'NHGF S3 Endpoint\\n')\n", + "print(f'zarr stores found: {len(zarr_name_list)}\\n')\n", + "print(f'example file path: {s3_path_list[0]}\\n')\n", + "print(f'example file name: {zarr_name_list[0]}')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "eee2188c-1e17-4d94-ad37-cb791f701852", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "fs2 = fsspec.filesystem('s3', anon=True, endpoint_url='https://usgs.osn.mghpcc.org/')\n", + "osn_path_list = fs2.ls('s3://mdmf/gdp/cprep')\n", + "zarr_list = [fp.split('/')[-1] for fp in fs2.ls('s3://mdmf/gdp/cprep')]\n", + "print(f'OSN Pod Endpoint\\n')\n", + "print(f'zarr stores found: {len(zarr_list)}\\n')\n", + "print(f'example file path: {s3_path_list[0]}\\n')\n", + "print(f'example file name: {zarr_list[0]}')" + ] + }, + { + "cell_type": "markdown", + "id": "d412ee91-7d5b-494f-9c57-61ee69f5261b", + "metadata": {}, + "source": [ + "## Test an example with one zarr from the list of 297" + ] + }, + { + "cell_type": "markdown", + "id": "20b00e88-5a13-46b3-9787-d9ac2d4e7bd6", + "metadata": {}, + "source": [ + "## Open up NHGF STAC Catalog" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "adf6c59d-58cd-48b1-a5fd-3bb205a3ef56", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# define folder location where your STAC catalog json file is\n", + "catalog_path = os.path.join('..', '..', 'catalog')\n", + "# open catalog\n", + "catalog = pystac.Catalog.from_file(os.path.join(catalog_path, 'catalog.json'))" + ] + }, + { + "cell_type": "markdown", + "id": "996e60ba-13e4-453a-8534-e62ce747f0fa", + "metadata": {}, + "source": [ + "## Collection Metadata Input" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "482d204d-b5b6-40e5-ac42-55b459be1097", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# name for STAC collection\n", + "collection_id = os.path.splitext(zarr_list[100])[0]\n", + "# description of STAC collection\n", + "collection_description = collection_id\n", + "# license for dataset\n", + "collection_license = 'CC0-1.0'" + ] + }, + { + "cell_type": "markdown", + "id": "116b5837-8e85-4ae7-964a-803533ded714", + "metadata": {}, + "source": [ + "## Asset Metadata Input" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "dd6fa323-132a-4794-8c80-576933f547a0", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# url to zarr store that you want to create a collection for\n", + "zarr_url = f's3://mdmf/gdp/cprep/{collection_id}.zarr/'\n", + "\n", + "# define keyword arguments needed for opening the dataset with xarray\n", + "# ref: https://github.com/stac-extensions/xarray-assets\n", + "xarray_opendataset_kwargs = {\"xarray:open_kwargs\":{\"chunks\":{},\"engine\":\"zarr\",\"consolidated\":True},\n", + " \"xarray:storage_options\": {\"anon\": True, \"client_kwargs\": {\"endpoint_url\":\"https://usgs.osn.mghpcc.org/\"}}}\n", + "# description for zarr url asset attached to collection (zarr_url)\n", + "asset_description = \"Open Storage Network Pod S3 API access to collection zarr group\"\n", + "# roles to tag zarr url asset with\n", + "asset_roles = [\"data\",\"zarr\",\"s3\"]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e1441cd4-e94c-4902-af46-8f1af470eb6b", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# url to zarr store that you want to create a collection for\n", + "zarr_url2 = f's3://nhgf-development/workspace/DataConversion/gdp/cprep/{collection_id}.zarr/'\n", + "\n", + "# define keyword arguments needed for opening the dataset with xarray\n", + "# ref: https://github.com/stac-extensions/xarray-assets\n", + "xarray_opendataset_kwargs2 = {\"xarray:open_kwargs\":{\"chunks\":{},\"engine\":\"zarr\",\"consolidated\":True},\n", + " \"xarray:storage_options\":{\"requester_pays\":True}}\n", + "# description for zarr url asset attached to collection (zarr_url)\n", + "asset_description2 = \"S3 access to collection zarr group\"\n", + "# roles to tag zarr url asset with\n", + "asset_roles2 = [\"data\",\"zarr\",\"s3\"]" + ] + }, + { + "cell_type": "markdown", + "id": "b213b74f-ad17-4774-93b6-3b62be616b45", + "metadata": { + "tags": [] + }, + "source": [ + "## Data Exploration" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b5ee1874-d280-4158-8d56-ecab750b6000", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# open and view zarr dataset\n", + "fs2 = fsspec.filesystem('s3', anon=True, endpoint_url='https://usgs.osn.mghpcc.org/')\n", + "ds = xr.open_dataset(fs2.get_mapper(zarr_url), engine='zarr', \n", + " backend_kwargs={'consolidated':True}, chunks={})\n", + "ds" + ] + }, + { + "cell_type": "markdown", + "id": "0bc7e9b3-ad62-4b10-a18e-66b7ed2d35dc", + "metadata": {}, + "source": [ + "## Identify x, y, t dimensions of dataset\n", + "May require user input if dimensions cannot be auto-detected." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ab91268f-7200-4cb1-979a-c7d75531d2c0", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "dims_auto_extract = ['X', 'Y', 'T']\n", + "def extract_dim(ds, d):\n", + " try:\n", + " dim_list = ds.cf.axes[d]\n", + " assert len(dim_list)==1, f'There are too many {d} dimensions in this dataset.'\n", + " dim = dim_list[0]\n", + " except KeyError:\n", + " print(f\"Could not auto-extract {d} dimension name.\")\n", + " print(\"Look at the xarray output above showing the dataset dimensions.\")\n", + " dim = str(input(f\"What is the name of the {d} dimension of this dataset?\"))\n", + " assert dim in ds.dims, \"That is not a valid dimension name for this dataset\"\n", + " print(f\"name of {d} dimension: {dim}\\n\")\n", + " return dim\n", + "\n", + "dim_names_dict = {}\n", + "for d in dims_auto_extract:\n", + " dim_names_dict[d] = extract_dim(ds, d)\n", + "print(f\"Dimension dictionary: {dim_names_dict}\")" + ] + }, + { + "cell_type": "markdown", + "id": "667cb9e8-c4a5-4d26-8e30-be8c934adc37", + "metadata": {}, + "source": [ + "## Get crs info" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "172d9e6b-de88-4e3a-9184-706110a99659", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "ds = ds.metpy.parse_cf()\n", + "crs = ds[list(ds.keys())[0]].metpy.cartopy_crs" + ] + }, + { + "cell_type": "markdown", + "id": "8fbfecfb-9886-4d06-a34c-6471cb0a6053", + "metadata": {}, + "source": [ + "## Plot a map" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4eb4d027-4266-4a0b-8f16-bacfbef06242", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# # plot a map of a single variable\n", + "# var_to_plot = 'SNOW'\n", + "# da = ds[var_to_plot].sel(time='2014-03-01 00:00').load()\n", + "# da.hvplot.quadmesh(x='lon', y='lat', rasterize=True,\n", + "# geo=True, tiles='OSM', alpha=0.7, cmap='turbo')" + ] + }, + { + "cell_type": "markdown", + "id": "5e057a6c-06fb-4406-823b-e81c58e520e4", + "metadata": {}, + "source": [ + "## Plot a time series at a specific point\n", + "This can help you verify a variable's values" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c7de2681-88c2-4597-857c-8f169c596f8b", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# # enter lat, lon of point you want to plot time series for\n", + "# lat,lon = 39.978322,-105.2772194\n", + "# time_start = '2013-01-01 00:00'\n", + "# time_end = '2013-12-31 00:00'\n", + "# x, y = crs.transform_point(lon, lat, src_crs=ccrs.PlateCarree()) # PlateCaree = Lat,Lon\n", + "# da = ds[var_to_plot].sel(x=x, y=y, method='nearest').sel(time=slice(time_start,time_end)).load()\n", + "# da.hvplot(x=dim_names_dict['T'], grid=True)" + ] + }, + { + "cell_type": "markdown", + "id": "a8c3ed37-8564-400b-a7fb-25bd5e43d21c", + "metadata": {}, + "source": [ + "## Create Collection Extent" + ] + }, + { + "cell_type": "markdown", + "id": "69f0d837-68a5-4fed-9a14-5d75cfbb0da4", + "metadata": {}, + "source": [ + "### Spatial Extent" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d46805e0-8e94-4ebe-aa01-d9a2d7051459", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# pull out lat/lon bbox for data\n", + "# coordinates must be from WGS 84 datum\n", + "# left, bottom, right, top\n", + "# Note: I'm not sure why but I have some trouble getting the data type right here - \n", + "# I've included all the options I've had to run to get it to not be a regular float rather \n", + "# than a numpy float below - switch the commented line if you have this issue\n", + "#coord_bounds = [ds.lon.data.min().compute().astype(float), ds.lat.data.min().compute().astype(float), ds.lon.data.max().compute().astype(float), ds.lat.data.max().compute().astype(float)]\n", + "#coord_bounds = [ds.lon.data.min().compute().astype(float).tolist(), ds.lat.data.min().compute().astype(float).tolist(), ds.lon.data.max().compute().astype(float).tolist(), ds.lat.data.max().compute().astype(float).tolist()]\n", + "coord_bounds = [ds.lon.data.min().astype(float).item(), ds.lat.data.min().astype(float).item(), ds.lon.data.max().astype(float).item(), ds.lat.data.max().astype(float).item()]\n", + "print(coord_bounds)\n", + "# create a spatial extent object \n", + "spatial_extent = pystac.SpatialExtent(bboxes=[coord_bounds])" + ] + }, + { + "cell_type": "markdown", + "id": "a04c8fca-1d33-43ac-9e2b-62d7be2887f7", + "metadata": {}, + "source": [ + "### Temporal Extent" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "41a84995-867c-4152-8c57-85e3758bbb77", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# pull out first and last timestamps\n", + "# temporal_extent_lower = pd.Timestamp(ds[dim_names_dict['T']].data.min())\n", + "# temporal_extent_upper = pd.Timestamp(ds[dim_names_dict['T']].data.max())\n", + "temporal_extent_lower = ds.indexes[dim_names_dict['T']].to_datetimeindex().min()\n", + "temporal_extent_upper = ds.indexes[dim_names_dict['T']].to_datetimeindex().max()\n", + "print(f'min: {temporal_extent_lower} \\nmax: {temporal_extent_upper}')\n", + "# create a temporal extent object\n", + "temporal_extent = pystac.TemporalExtent(intervals=[[temporal_extent_lower, temporal_extent_upper]])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1b1e37c4-5348-46ad-abc9-e005b5d6c02b", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "collection_extent = pystac.Extent(spatial=spatial_extent, temporal=temporal_extent)" + ] + }, + { + "cell_type": "markdown", + "id": "cfb71202-03df-45b5-ac2f-0dc2ee1ab780", + "metadata": {}, + "source": [ + "## Create pystac collection" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7e96811b-95ae-406a-9728-55fc429d4e1f", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "if catalog.get_child(collection_id):\n", + " collection = catalog.get_child(collection_id)\n", + " print(\"existing collection opened\")\n", + " collection.extent=collection_extent\n", + " collection.description=collection_description\n", + " collection.license=collection_license\n", + "else:\n", + " collection = pystac.Collection(id=collection_id,\n", + " description=collection_description,\n", + " extent=collection_extent,\n", + " license=collection_license)\n", + " print(\"new collection created\")" + ] + }, + { + "cell_type": "markdown", + "id": "a21c76e8-cd57-4eb5-a33f-7c668a3b3205", + "metadata": {}, + "source": [ + "## Add zarr url asset to collection" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "094832af-d22b-4359-b0f6-cf687acce5cc", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "asset_id = \"zarr-s3-osn\"\n", + "asset = pystac.Asset(href=zarr_url,\n", + " description=asset_description,\n", + " media_type=\"application/vnd+zarr\",\n", + " roles=asset_roles,\n", + " extra_fields = xarray_opendataset_kwargs)\n", + "collection.add_asset(asset_id, asset)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0c298d07-f234-4a08-986d-87f4a39e9ae6", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "asset_id2 = \"zarr-s3\"\n", + "asset2 = pystac.Asset(href=zarr_url2,\n", + " description=asset_description2,\n", + " media_type=\"application/vnd+zarr\",\n", + " roles=asset_roles2,\n", + " extra_fields = xarray_opendataset_kwargs2)\n", + "collection.add_asset(asset_id2, asset2)" + ] + }, + { + "cell_type": "markdown", + "id": "f67cd5c9-db33-45c2-bc21-480cd67354f4", + "metadata": {}, + "source": [ + "## Add datacube extension to collection" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "fc00946d-2880-491d-9b3b-3aeeb4414d6c", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# instantiate extention on collection\n", + "dc = DatacubeExtension.ext(collection, add_if_missing=True)" + ] + }, + { + "cell_type": "markdown", + "id": "8bdd77a2-7587-485e-afb7-42af3a822241", + "metadata": {}, + "source": [ + "### Add cube dimensions (required field for extension)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "120a4914-3302-44a5-a282-0308ac84f040", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# list out dataset dimensions\n", + "# When writing data to Zarr, Xarray sets this attribute on all variables based on the variable dimensions. When reading a Zarr group, Xarray looks for this attribute on all arrays,\n", + "# raising an error if it can’t be found.\n", + "dims = list(ds.dims)\n", + "print(dims)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "00a18a29-fb9a-4b56-8009-493122997b16", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# get x, y bounds for extent of those dimensions (required)\n", + "xy_bounds = [ds[dim_names_dict['X']].data.min().astype(float).item(), ds[dim_names_dict['Y']].data.min().astype(float).item(), ds[dim_names_dict['X']].data.max().astype(float).item(), ds[dim_names_dict['Y']].data.max().astype(float).item()]\n", + "print(xy_bounds)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0f49d6d7-9e30-4144-909b-fa1238e6c77a", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "def get_step(dim_name):\n", + " dim_vals = ds[dim_name].values\n", + " diffs = [d2 - d1 for d1, d2 in zip(dim_vals, dim_vals[1:])]\n", + " unique_steps = np.unique(diffs)\n", + " # set step - if all steps are the same length\n", + " # datacube spec specifies to use null for irregularly spaced steps\n", + " if len(unique_steps)==1:\n", + " unique_steps = [np.array([unique_steps[0]], dtype=\"timedelta64[ms]\")[0] for step in unique_steps]\n", + " step = unique_steps[0].astype(float).item()\n", + " else:\n", + " step = None\n", + " return(step)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "a20d12bf-a511-4c5e-84d0-77e2ec551518", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "def get_long_name(ds, v):\n", + " # try to get long_name attribute from variable\n", + " try:\n", + " long_name = ds[v].attrs['long_name']\n", + " # otherwise, leave empty\n", + " except:\n", + " long_name = None\n", + " return long_name" + ] + }, + { + "cell_type": "markdown", + "id": "e7dc357c-91ec-49ae-83e5-400f791f9792", + "metadata": {}, + "source": [ + "#### user input needed - you will need to look at the crs information and create a cartopy crs object after identifying the projection type:\n", + "reference list of cartopy projections: https://scitools.org.uk/cartopy/docs/latest/reference/projections.html" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "ea452f62-5644-49b6-8a4e-7dc4f649fd1a", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# print ot crs information in dataset\n", + "print(crs)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1b1d05ff-8e43-44a7-8343-178b112c4ad6", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# the datacube extension can accept reference_system information as a numerical EPSG code, \n", + "# WKT2 (ISO 19162) string or PROJJSON object.\n", + "# we will use a projjson, as was done by Microsoft Planetary Computer here:\n", + "# https://planetarycomputer.microsoft.com/dataset/daymet-annual-na\n", + "# https://planetarycomputer.microsoft.com/api/stac/v1/collections/daymet-annual-na\n", + "projjson = crs.to_json()\n", + "print(projjson)" + ] + }, + { + "cell_type": "markdown", + "id": "00a5e041-081d-428d-ac2e-75d16de205e6", + "metadata": {}, + "source": [ + "#### user input needed - you will need to copy all of the dimensions from above into the dict and fill in the appropriate attributes(type, axis, extent):" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5a443497-67a9-4dce-a8e9-b08d31a88223", + "metadata": {}, + "outputs": [], + "source": [ + "# create a dictionary of datacube dimensions you would like to assign to this dataset\n", + "# dimension name should come from the coordinates printed above\n", + "# we do not recommend including redundant dimensions (do not include x,y if you have lon,lat)\n", + "# note that the extent of each dimension should be pulled from the dataset\n", + "dims_dict = {'time': pystac.extensions.datacube.Dimension({'type': 'temporal', 'description': get_long_name(ds, 'time'), 'extent': [temporal_extent_lower.strftime('%Y-%m-%dT%XZ'), temporal_extent_upper.strftime('%Y-%m-%dT%XZ')], 'step': pd.Timedelta(get_step('time')).isoformat()}),\n", + " 'lon': pystac.extensions.datacube.Dimension({'type': 'spatial', 'description': get_long_name(ds, 'lon'), 'axis': 'x', 'extent': [xy_bounds[0], xy_bounds[2]], 'step': get_step('lon'), 'reference_system': projjson}),\n", + " 'lat': pystac.extensions.datacube.Dimension({'type': 'spatial', 'axis': 'y', 'description': get_long_name(ds, 'lat'), 'extent': [xy_bounds[1], xy_bounds[3]], 'step': get_step('lat'), 'reference_system': projjson}),\n", + " 'bnds': pystac.extensions.datacube.Dimension({'type': 'bounds', 'description': get_long_name(ds, 'bnds'), 'extent': [ds.bnds.min().item(), ds.bnds.max().item()]}),\n", + " }" + ] + }, + { + "cell_type": "markdown", + "id": "0f277883-a3fd-425f-966a-ca2140d0ef2f", + "metadata": {}, + "source": [ + "### Add cube variables (optional field for extension)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "92510876-7853-4d24-8563-c69f9012aeb6", + "metadata": {}, + "outputs": [], + "source": [ + "# define functions to pull out datacube attributes and validate format\n", + "def get_unit(ds, v):\n", + " # check if unit is defined for variable\n", + " try:\n", + " unit = ds[v].attrs['units']\n", + " except:\n", + " unit = None\n", + " # check if unit comes from https://docs.unidata.ucar.edu/udunits/current/#Database\n", + " # datacube extension specifies: The unit of measurement for the data, preferably compliant to UDUNITS-2 units (singular).\n", + " # gdptools expects this format as well\n", + " try:\n", + " cfunits.Units(unit).isvalid\n", + " except:\n", + " print(\"Unit is not valid as a UD unit.\")\n", + " unit = str(input(\"Please enter a valid unit for {v} from here: https://docs.unidata.ucar.edu/udunits/current/#Database\"))\n", + " assert cfunits.Units(unit).isvalid\n", + " return unit\n", + "\n", + "def get_var_type(ds, v):\n", + " if v in ds.coords:\n", + " # type = auxiliary for a variable that contains coordinate data, but isn't a dimension in cube:dimensions.\n", + " # For example, the values of the datacube might be provided in the projected coordinate reference system, \n", + " # but the datacube could have a variable lon with dimensions (y, x), giving the longitude at each point.\n", + " var_type = 'auxiliary'\n", + " # type = data for a variable indicating some measured value, for example \"precipitation\", \"temperature\", etc.\n", + " else:\n", + " var_type = 'data'\n", + " return var_type" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e9272931-fc0b-4f2a-9546-283033e9cde8", + "metadata": {}, + "outputs": [], + "source": [ + "# pull list of vars from dataset\n", + "vars = list(ds.variables)\n", + "\n", + "# drop metpy_crs coordinate we have added\n", + "if 'metpy_crs' in ds.coords:\n", + " ds = ds.drop_vars('metpy_crs')\n", + "\n", + "# spec says that the keys of cube:dimensions and cube:variables should be unique together; a key like lat should not be both a dimension and a variable.\n", + "# we will drop all values in dims from vars\n", + "vars = [v for v in vars if v not in dims]\n", + "\n", + "# Microsoft Planetary Computer includes coordinates and crs as variables here:\n", + "# https://planetarycomputer.microsoft.com/dataset/daymet-annual-na\n", + "# https://planetarycomputer.microsoft.com/api/stac/v1/collections/daymet-annual-na\n", + "# we will keep those in the var list\n", + "\n", + "# create dictionary of dataset variables and associated dimensions\n", + "vars_dict={}\n", + "for v in vars:\n", + " unit = get_unit(ds, v)\n", + " var_type = get_var_type(ds, v)\n", + " long_name = get_long_name(ds, v)\n", + " vars_dict[v] = pystac.extensions.datacube.Variable({'dimensions':list(ds[v].dims), 'type': var_type, 'description': long_name, 'unit': unit})" + ] + }, + { + "cell_type": "markdown", + "id": "11ad5352-884c-4472-8864-4570a96f66e5", + "metadata": {}, + "source": [ + "### Finalize extension" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "10141fd4-91d6-491d-878b-02653720891d", + "metadata": {}, + "outputs": [], + "source": [ + "# add dimesions and variables to collection extension\n", + "dc.apply(dimensions=dims_dict, variables=vars_dict)" + ] + }, + { + "cell_type": "markdown", + "id": "615ca168-75fb-4135-9941-0ef5fe4fd1cb", + "metadata": {}, + "source": [ + "## Add STAC Collection to Catalog and Save" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e2120a55-3d04-4122-a93f-29afcdb8cb1b", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# # helper to find items of wrong type\n", + "# d = collection.to_dict()\n", + "# def find_paths(nested_dict, prepath=()):\n", + "# for k, v in nested_dict.items():\n", + "# try:\n", + "# path = prepath + (k,)\n", + "# if type(v) is np.float64: # found value\n", + "# yield path\n", + "# elif hasattr(v, 'items'): # v is a dict\n", + "# yield from find_paths(v, path) \n", + "# except:\n", + "# print(prepath)\n", + "\n", + "# print(*find_paths(d))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "4b75791b-6b2d-40be-b7c6-330a60888fb5", + "metadata": {}, + "outputs": [], + "source": [ + "if catalog.get_child(collection_id):\n", + " collection.normalize_and_save(root_href=os.path.join(catalog_path, collection_id), catalog_type=pystac.CatalogType.SELF_CONTAINED)\n", + "else:\n", + " catalog.add_child(collection)\n", + " catalog.normalize_and_save(root_href=catalog_path, catalog_type=pystac.CatalogType.SELF_CONTAINED)" + ] + }, + { + "cell_type": "markdown", + "id": "c734db5d-a9b4-42b4-88fb-50d84493f694", + "metadata": {}, + "source": [ + "## The big job\n", + "Now that we have tested the workflow, we will implement it in a big for loop for all 297 zarrs." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "929a90d4-2ae1-480a-aec3-348d19a667d8", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "markdown", + "id": "ac25d30a-0a27-4241-a631-522f6dcbe764", + "metadata": { + "tags": [] + }, + "source": [ + "## Supplemental - Calendar Exploration based on zarr conversion workflow\n", + "A special handling of the calendars was set up in the [zarr converstion workflow](https://code.usgs.gov/wma/nhgf/geo-data-portal/gdp_data_processing/-/blob/main/workflows/opendap/CIDA/CPREP/cprep_conversion.ipynb?ref_type=heads) for this dataset, so this was further explored to see if it was necessary." + ] + }, + { + "cell_type": "markdown", + "id": "3877e708-f600-48c2-b3e4-e267dd547c57", + "metadata": {}, + "source": [ + "### Types of calendars\n", + "There appear to be two types of calendars used in in this dataset's time variable. Let's check that first." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e314605d-5676-4add-935e-1ca59e4852d4", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "ds_example = []\n", + "calendar_list = []\n", + "calendar_count = {}\n", + "for f in zarr_list:\n", + " collection_id = os.path.splitext(f)[0]\n", + " zarr_url = f's3://mdmf/gdp/cprep/{collection_id}.zarr/'\n", + " ds = xr.open_dataset(fs2.get_mapper(zarr_url), engine='zarr', \n", + " backend_kwargs={'consolidated':True}, chunks={},\n", + " decode_times=False)\n", + " calendar = ds.time.calendar\n", + " try:\n", + " calendar_count[calendar] = calendar_count[calendar] + 1\n", + " except:\n", + " calendar_count[calendar] = 1\n", + " if calendar not in calendar_list:\n", + " ds_example.append(collection_id)\n", + " calendar_list.append(calendar)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0ff931d7-f0dd-4721-97ad-0b65b796db53", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "calendar_count" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "030a1cfd-f568-4cfe-b7d0-5fae88c1e819", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "calendar_list" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7493aa82-e707-4f10-bb22-125661c30c79", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "ds_example" + ] + }, + { + "cell_type": "markdown", + "id": "c17f24ff-7763-4400-80b3-3d815c2285fd", + "metadata": {}, + "source": [ + "### Julian calendar\n", + "#### What do we get for min/max times if we decode the times upon reading in the data (the xarray default)?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "03fdf554-c6ba-47a4-b8ce-8993d1cd00e9", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# Julian\n", + "zarr_url = f's3://mdmf/gdp/cprep/cprep_pr_day_I35prp1-DeltaSD-A32D01K00_rcp26_r1i1p1_I35Land_20060101-20991231.zarr/'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "708f2cf5-79ab-49af-8067-de31d0d13ee6", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# open and view zarr dataset\n", + "fs2 = fsspec.filesystem('s3', anon=True, endpoint_url='https://usgs.osn.mghpcc.org/')\n", + "ds = xr.open_dataset(fs2.get_mapper(zarr_url), engine='zarr', \n", + " backend_kwargs={'consolidated':True}, chunks={},\n", + " decode_times=True)\n", + "ds" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c6a94627-edb3-43f2-8b79-e45d5fad89cc", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "print('min time step:')\n", + "ds.indexes[dim_names_dict['T']].to_datetimeindex().min()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c87e35ad-6fe9-4057-83eb-c5e335a75446", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "print('max time step:')\n", + "ds.indexes[dim_names_dict['T']].to_datetimeindex().max()" + ] + }, + { + "cell_type": "markdown", + "id": "459848fa-b464-4254-a648-7205c032db01", + "metadata": {}, + "source": [ + "#### What do we get for min/max times if we do NOT decode the times (like was done in the zarr conversion workflow)?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "601db820-e332-42c2-a90b-24f527bb197b", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# open and view zarr dataset\n", + "fs2 = fsspec.filesystem('s3', anon=True, endpoint_url='https://usgs.osn.mghpcc.org/')\n", + "ds = xr.open_dataset(fs2.get_mapper(zarr_url), engine='zarr', \n", + " backend_kwargs={'consolidated':True}, chunks={},\n", + " decode_times=False)\n", + "ds" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5ec7044a-c744-4980-813b-fd15e5e06d7e", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "z = zarr_url\n", + "start_date = z.split('/')[5].split('_')[7].split('-')[0].split('.')[0]\n", + "end_date = z.split('/')[5].split('_')[7].split('-')[1].split('.')[0]\n", + "start_date = f'{start_date[0:4]}-{start_date[4:6]}-{start_date[6:8]}'\n", + "end_date = f'{end_date[0:4]}-{end_date[4:6]}-{end_date[6:8]}'\n", + "calendar = ds.time.calendar\n", + "if calendar == 'julian':\n", + " cftime_index = xr.cftime_range(start_date, end_date, freq='D', calendar='julian')\n", + " ds['time'] = cftime_index\n", + " \n", + "elif calendar == 'noleap':\n", + " cftime_index = xr.cftime_range(start_date, end_date, freq='D', calendar='noleap')\n", + " ds['time'] = cftime_index" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "950168e8-b2c2-4177-add0-efab5794db44", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "ds" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "faddefa3-cd71-43f9-ba6f-1e886a5a442f", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "print('min time step:')\n", + "pd.Timestamp((ds.indexes['time'].to_datetimeindex().min()))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "68b10114-3b44-4ed6-9c3f-7882e33b04f3", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "print('max time step:')\n", + "pd.Timestamp((ds.indexes['time'].to_datetimeindex().max()))" + ] + }, + { + "cell_type": "markdown", + "id": "61bf449c-bd99-427d-a7d1-1eed51d2da75", + "metadata": {}, + "source": [ + "### noleap\n", + "#### What do we get for min/max times if we decode the times upon reading in the data (the xarray default)?" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0a486983-7643-4f6e-b68f-3f6084074210", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# noleap\n", + "zarr_url = f's3://mdmf/gdp/cprep/cprep_pr_day_I35prp1-DeltaSD-A12D01K00_rcp26_r6i1p1_I35Land_20060101-20991231.zarr/'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "14f03b46-04fd-4a78-b5cf-bcc3331d7a30", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# open and view zarr dataset\n", + "fs2 = fsspec.filesystem('s3', anon=True, endpoint_url='https://usgs.osn.mghpcc.org/')\n", + "ds = xr.open_dataset(fs2.get_mapper(zarr_url), engine='zarr', \n", + " backend_kwargs={'consolidated':True}, chunks={},\n", + " decode_times=True)\n", + "ds" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "f225f473-adde-443e-b8c0-6d477639b40d", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "print('min time step:')\n", + "ds.indexes[dim_names_dict['T']].to_datetimeindex().min()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e20aaa0e-218c-4dfe-8cae-a2ca3854233d", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "print('max time step:')\n", + "ds.indexes[dim_names_dict['T']].to_datetimeindex().max()" + ] + }, + { + "cell_type": "markdown", + "id": "50a860f5-98b4-48b0-b872-63bc5dc271ae", + "metadata": {}, + "source": [ + "#### What do we get for min/max times if we do NOT decode the times (like was done in the zarr conversion workflow)?### What do we get for min/max times if we do NOT decode the times? - noleap" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "737458bc-cba5-4c93-83bf-963cbb635f24", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "# open and view zarr dataset\n", + "fs2 = fsspec.filesystem('s3', anon=True, endpoint_url='https://usgs.osn.mghpcc.org/')\n", + "ds = xr.open_dataset(fs2.get_mapper(zarr_url), engine='zarr', \n", + " backend_kwargs={'consolidated':True}, chunks={},\n", + " decode_times=False)\n", + "ds" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c1ae19f2-5713-4ca8-8299-a566c15b29ae", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "z = zarr_url\n", + "start_date = z.split('/')[5].split('_')[7].split('-')[0].split('.')[0]\n", + "end_date = z.split('/')[5].split('_')[7].split('-')[1].split('.')[0]\n", + "start_date = f'{start_date[0:4]}-{start_date[4:6]}-{start_date[6:8]}'\n", + "end_date = f'{end_date[0:4]}-{end_date[4:6]}-{end_date[6:8]}'\n", + "calendar = ds.time.calendar\n", + "if calendar == 'julian':\n", + " cftime_index = xr.cftime_range(start_date, end_date, freq='D', calendar='julian')\n", + " ds['time'] = cftime_index\n", + " \n", + "elif calendar == 'noleap':\n", + " cftime_index = xr.cftime_range(start_date, end_date, freq='D', calendar='noleap')\n", + " ds['time'] = cftime_index" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b7cc4b04-5b08-4bd0-bd49-6c9ba37f4df9", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "ds" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "df3038fa-a03b-41dc-a029-773a8fbf496d", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "print('min time step:')\n", + "ds.indexes[dim_names_dict['T']].to_datetimeindex().min()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e3bada84-0d24-42db-b345-6d657c40ba06", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "print('max time step:')\n", + "ds.indexes[dim_names_dict['T']].to_datetimeindex().min()" + ] + }, + { + "cell_type": "markdown", + "id": "fb491fae-4681-4b1a-aef6-95e4bbb764f1", + "metadata": {}, + "source": [ + "### Conclusion:\n", + "The workflow is overwriting the calendar values so that instead of being marked in the 12:00 hour, they are marked with the 00:00 hour. There doesn't seem to be different handling for Julian vs. noleap calendars. We will use the data's true data values and let xarray decode the times for us, rather than using this shifted timestamp." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "global-global-pangeo", + "language": "python", + "name": "conda-env-global-global-pangeo-py" + }, + "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.11.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +}