#grayscale");filter:gray;-webkit-filter:grayscale(100%);}.bk-root .bk-logo-small{width:20px;height:20px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAABx0RVh0U29mdHdhcmUAQWRvYmUgRmlyZXdvcmtzIENTNui8sowAAAOkSURBVDiNjZRtaJVlGMd/1/08zzln5zjP1LWcU9N0NkN8m2CYjpgQYQXqSs0I84OLIC0hkEKoPtiH3gmKoiJDU7QpLgoLjLIQCpEsNJ1vqUOdO7ppbuec5+V+rj4ctwzd8IIbbi6u+8f1539dt3A78eXC7QizUF7gyV1fD1Yqg4JWz84yffhm0qkFqBogB9rM8tZdtwVsPUhWhGcFJngGeWrPzHm5oaMmkfEg1usvLFyc8jLRqDOMru7AyC8saQr7GG7f5fvDeH7Ej8CM66nIF+8yngt6HWaKh7k49Soy9nXurCi1o3qUbS3zWfrYeQDTB/Qj6kX6Ybhw4B+bOYoLKCC9H3Nu/leUTZ1JdRWkkn2ldcCamzrcf47KKXdAJllSlxAOkRgyHsGC/zRday5Qld9DyoM4/q/rUoy/CXh3jzOu3bHUVZeU+DEn8FInkPBFlu3+nW3Nw0mk6vCDiWg8CeJaxEwuHS3+z5RgY+YBR6V1Z1nxSOfoaPa4LASWxxdNp+VWTk7+4vzaou8v8PN+xo+KY2xsw6une2frhw05CTYOmQvsEhjhWjn0bmXPjpE1+kplmmkP3suftwTubK9Vq22qKmrBhpY4jvd5afdRA3wGjFAgcnTK2s4hY0/GPNIb0nErGMCRxWOOX64Z8RAC4oCXdklmEvcL8o0BfkNK4lUg9HTl+oPlQxdNo3Mg4Nv175e/1LDGzZen30MEjRUtmXSfiTVu1kK8W4txyV6BMKlbgk3lMwYCiusNy9fVfvvwMxv8Ynl6vxoByANLTWplvuj/nF9m2+PDtt1eiHPBr1oIfhCChQMBw6Aw0UulqTKZdfVvfG7VcfIqLG9bcldL/+pdWTLxLUy8Qq38heUIjh4XlzZxzQm19lLFlr8vdQ97rjZVOLf8nclzckbcD4wxXMidpX30sFd37Fv/GtwwhzhxGVAprjbg0gCAEeIgwCZyTV2Z1REEW8O4py0wsjeloKoMr6iCY6dP92H6Vw/oTyICIthibxjm/DfN9lVz8IqtqKYLUXfoKVMVQVVJOElGjrnnUt9T9wbgp8AyYKaGlqingHZU/uG2NTZSVqwHQTWkx9hxjkpWDaCg6Ckj5qebgBVbT3V3NNXMSiWSDdGV3hrtzla7J+duwPOToIg42ChPQOQjspnSlp1V+Gjdged7+8UN5CRAV7a5EdFNwCjEaBR27b3W890TE7g24NAP/mMDXRWrGoFPQI9ls/MWO2dWFAar/xcOIImbbpA3zgAAAABJRU5ErkJggg==);}.bk-root .bk-logo-notebook{display:inline-block;vertical-align:middle;margin-right:5px;}.rendered_html .bk-root .bk-tooltip table,.rendered_html .bk-root .bk-tooltip tr,.rendered_html .bk-root .bk-tooltip th,.rendered_html .bk-root .bk-tooltip td{border:none;padding:1px;}.bk-root .bk-toolbar-hidden{visibility:hidden;opacity:0;transition:visibility 0.3s linear, opacity 0.3s linear;}.bk-root .bk-toolbar{display:flex;flex-wrap:nowrap;align-items:center;user-select:none;-ms-user-select:none;-moz-user-select:none;-webkit-user-select:none;}.bk-root .bk-toolbar .bk-logo{flex-shrink:0;}.bk-root .bk-toolbar.bk-above,.bk-root .bk-toolbar.bk-below{flex-direction:row;justify-content:flex-end;}.bk-root .bk-toolbar.bk-above .bk-logo,.bk-root .bk-toolbar.bk-below .bk-logo{order:1;margin-left:5px;margin-right:0px;}.bk-root .bk-toolbar.bk-left,.bk-root .bk-toolbar.bk-right{flex-direction:column;justify-content:flex-start;}.bk-root .bk-toolbar.bk-left .bk-logo,.bk-root .bk-toolbar.bk-right .bk-logo{order:0;margin-bottom:5px;margin-top:0px;}.bk-root .bk-toolbar-button{width:30px;height:30px;cursor:pointer;background-size:60% 60%;background-origin:border-box;background-color:transparent;background-repeat:no-repeat;background-position:center center;}.bk-root .bk-toolbar-button:hover,.bk-root .bk-tool-overflow:hover{background-color:rgba(192, 192, 192, 0.15);}.bk-root .bk-toolbar-button:focus,.bk-root .bk-tool-overflow:focus,.bk-root .bk-toolbar-button:focus-visible,.bk-root .bk-tool-overflow:focus-visible{outline:1px dotted #26aae1;outline-offset:-1px;}.bk-root .bk-toolbar-button::-moz-focus-inner,.bk-root .bk-tool-overflow::-moz-focus-inner{border:0;}.bk-root .bk-above .bk-toolbar-button{border-bottom:2px solid transparent;}.bk-root .bk-above .bk-toolbar-button.bk-active{border-bottom-color:#26aae1;}.bk-root .bk-below .bk-toolbar-button{border-top:2px solid transparent;}.bk-root .bk-below .bk-toolbar-button.bk-active{border-top-color:#26aae1;}.bk-root .bk-right .bk-toolbar-button{border-left:2px solid transparent;}.bk-root .bk-right .bk-toolbar-button.bk-active{border-left-color:#26aae1;}.bk-root .bk-left .bk-toolbar-button{border-right:2px solid transparent;}.bk-root .bk-left .bk-toolbar-button.bk-active{border-right-color:#26aae1;}.bk-root .bk-divider{content:" ";display:inline-block;background-color:lightgray;}.bk-root .bk-above .bk-divider,.bk-root .bk-below .bk-divider{height:10px;width:1px;}.bk-root .bk-left .bk-divider,.bk-root .bk-right .bk-divider{height:1px;width:10px;}.bk-root .bk-tool-overflow{color:gray;display:flex;align-items:center;}.bk-root .bk-above .bk-tool-overflow,.bk-root .bk-below .bk-tool-overflow,.bk-root .bk-horizontal .bk-tool-overflow{width:15px;height:30px;flex-direction:row;}.bk-root .bk-left .bk-tool-overflow,.bk-root .bk-right .bk-tool-overflow,.bk-root .bk-vertical .bk-tool-overflow{width:30px;height:15px;flex-direction:column;}.bk-root .bk-tool-icon-copy-to-clipboard{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH5AUSDBoBvcHQeQAAAG9JREFUWMNjXLhsJcNAAiaGAQYwB/xHwh/Q+ITEkfHQCwEWND4jmeb8H/JpgBwfI6cNBhLSEkqaGXRpgFRAcZoZsmlg1AGjDhh1wKgDRh0w6gCaVcf/R2wIkNqw+D9s0wADvUNiyIYA47BJAwPuAAAj/Cjd0TCN6wAAAABJRU5ErkJggg==");}.bk-root .bk-tool-icon-replace-mode{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH5AUFFxokK3gniQAAAHpJREFUWMNjXLhsJcNAAiaGAQajDhhwB7DgEP+PxmeksvjgDwFcLmYkUh2hkBj8IcBIZXsYh1w2/I8v3sgAOM0bLYhGc8GgrwuICgldfQO88pcvXvg/aOuCUQeM5oLRuoCFCJcTbOMh5XOiW0JDNhdQS3y0IBp1ABwAAF8KGrhC1Eg6AAAAAElFTkSuQmCC");}.bk-root .bk-tool-icon-append-mode{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH5AUFFxkZWD04WwAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAAAoUlEQVRYw+1WQQ6AIAwrhO8Y/bIXEz9jIMSDr8ETCUEPQzA4pMeFLKNbu4l5WR0CDOMEALBGIzMuQIBEZQjPgP9JLjwTfBjY9sO9lZsFA9IafZng3BlIyVefgd8XQFZBAWe8jfNxwsDhir6rzoCiPiy1K+J8/FRQemv2XfAdFcQ9znU4Viqg9ta1qYJ+D1BnAIBrkgGVOrXNqUA9rbyZm/AEzFh4jEeY/soAAAAASUVORK5CYII=");}.bk-root .bk-tool-icon-intersect-mode{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH5AUFFxkrkOpp2wAAAPhJREFUWMPtV1EKwjAMTUavI3oawR/vtn5srJdREfzwMvHHQlcT2mpdMzFfWxiP5r2+JMN+mAiCOB72CABgR1cln4oOGocJnuMTSxWk8jMm7OggYkYXA9gPE3uyd8NXHONJ+eYMdE/NqCJmEZ5ZqlJJ4sUksKN7cYSaPoCZFWR1QI+Xm1fBACU63Cw22x0AAJxudwrffVwvZ+JmQdAHZkw0d4EpAMCw8k87pMdbnwtizQumJYv3nwV6XOA1qbUT/oQLUJgFRbsiNwFVucBIlyR3p0tdMp+XmFjfLKi1LatyAXtCRjPWBdL3Ke3VuACJKFfDr/xFN2fgAR/Go0qaLlmEAAAAAElFTkSuQmCC");}.bk-root .bk-tool-icon-subtract-mode{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH5AUFFxgsF5XNOQAAAB1pVFh0Q29tbWVudAAAAAAAQ3JlYXRlZCB3aXRoIEdJTVBkLmUHAAABFUlEQVRYw9VWUQqDMAxNpWfxQxD1MoP97G7zQ5mH2RTZYLtM9lWoMbXtxLXNX4OG9r28l4hrd0PQoqxqAACYpxH25C/nkwCHyCBwSPoS09k1T5Fo+4EiExcC4v584xGFmyIXHBLRISAVZyZufUPVa4rcrwmPDgr93ylo+2GliLRUYHK6th/o/6r7nfLpqaCsagEA8Hh9FmcNKeRmgeYDC+SCq0B6FFi8/BcV6BdR9cL3gCv3ijPKOacsn3rBEcjmaVxpfGcg4wHxzgJJnc6241Hn23DERFRAu1bNcWa3Q0uXi62XR6sCaWoSejbtdLYmU3kTEunNgj0bUbQqYG/IcMaqwPS9jftoVCAQ0ZVDJwf0zQdH4AsyW6fpQu4YegAAAABJRU5ErkJggg==");}.bk-root .bk-tool-icon-clear-selection{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH5AUGEhcuan3d3wAAAoRJREFUWMPtlzFP3EAQhd+b3TNSzg0N5TWXLkJQUUaKhIQ4fgP/g5ArrriE/I3opEgRrZtIVJR0FJQ010SioUmEZHtnUpwN9gWHGA5BJCy58MraffvmfZ41v3z9hqe8BE98vQh4cgG+Ydzmnrng8efvQJNi/uN7dznx/B3ggtfhf4ehNdUttRzBDIm/2VTiiWCG1HK0nc+3UWtq8BQIiEEakEQOADBIA4QCQmBqoHBhFNR27ikQSmGdYCdTqCpEHMDZmEKRWUBEv1gBDg5SzRJnpopILWICgWuRYflLamuzxB2BmtYqSRIka5VWU8QduXO+1hRc5YZu5GAwmP2ZJzND0IBu5HCV2+NQcAhAVRsnC2IbPzPdSjzd6to6VtfWkXi6YLaVWr7xoAwkfpb8MnC3SH7rKSMBe4M0jA/OTicFIbtCGRIyNbURhcf3ErCd6YwA1m0HgAxhw1NGQnlXBHG4kylVlSJuH0RfIP2CkL2I/qS1gIAAQiBl1QwFggIHtyxgrxK5PgyfC0JWKoT0HLh8LwoietB4TYKaIl7yeNURxB05UtMxDOcVQlZIrlRKdK6m47gjR/fuBRQihyLArtNeJD50Izcx2Eczu7iFkIug4VM3cpOr3MKDekFED0fWUHv9Zq0kpLnridjhY3XDg7NTN0jDrhO3X7O9Wg7wwyANu4mnayNg3gmbu0tCNoUyBNGv2l4rB9EXynA7082FOxAQLhU6rQVO9T2AvWowFToNCJcPORGxIRcnpjZSKATSU9NxvOQnAPArDSaQoUKnNI4iufkGtD4P3EHIcWZhz4HLceSOyrR3Izf5memPAL2cX3yhAkonysZVaWLBkd9dw1Ivv2a/AYPkK+ty1U1DAAAAAElFTkSuQmCC");}.bk-root .bk-tool-icon-box-select{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gEMEg0kduFrowAAAIdJREFUWMPtVtEKwCAI9KL//4e9DPZ3+wP3KgOjNZouFYI4C8q7s7DtB1lGIeMoRMRinCLXg/ML3EcFqpjjloOyZxRntxpwQ8HsgHYARKFAtSFrCg3TCdMFCE1BuuALEXJLjC4qENsFVXCESZw38/kWLOkC/K4PcOc/Hj03WkoDT3EaWW9egQul6CUbq90JTwAAAABJRU5ErkJggg==");}.bk-root .bk-tool-icon-box-zoom{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gEMEg82t254aQAAAkBJREFUWMPN11+E1FEUB/DPTFn2qaeIpcSwr5NlUyJiKWVXWUqvlUh/iE3RY9mUekkPPURtLKNRrFJEeuphGfUUaVliiX1aVjGs6aG7+XX9ZnZ+d2fTl2vmnHvPPfeee/79Sk+may2/UQq/q7Qu+bAJoxjHIKqB/wlfUMcMVqI9bLZ+DGIKwzlzQ2GcxCx2xwvKOUKlaHTiX8bHNspjDONHkOmJBW5jIof/FvPh/06MZOb6cRc7cGn1AKUE5cdzlM/gAr5F/O24H3xkFRfxAbVygvK+cIsspjGWo1zgjeFpxL+BvnLw7laBA4xjIFJwrgu52DoVjKdY4HBEX8dSF3JLYe1fe6UcYCii3xWQjdfuSTnAtoheKCC7GNED5Zx4L4qt61jbTLHA94geKSC7P7ZeShQ0Inoi1IJuEOeORooFXkV0FZNdZs5qvFfKAeqYy7nZ6yg//HG0MBfffh71lFrQDCW2EvEP4mt4okZUDftz9rmGZkotmMxJRtlisy+MTniAWrty3AlXw0hFM2TD89l+oNsoOJXjbIs4EpqNtTCLXbiZ0g+M4mFObj8U3vsNjoZCVcmk60ZwthpepLZkB/AsivWfOJZxtpUQHfWib7KWDwzjeegBZJSdKFiE2qJTFFTwElsi/unQ/awXrU4WGMD7nOJxBY/1EO2iYConq93CHT1GOwucjdqnRyFz+VcHmMNefMY9nNkA3SWUOoXhQviSWQ4huLIRFlirFixnQq/XaKXUgg2xQNGv4V7x/RcW+AXPB3h7H1PaiQAAAABJRU5ErkJggg==");}.bk-root .bk-tool-icon-zoom-in{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gEMEgsUBmL8iQAAA2JJREFUWMO9l12IlFUYx3//MzPrLpSjkm5oN4FFIWVEl66IQlFYwtLOzozsjHdGRSCRF0sfBEXRVV0FQuQiLm5CZNBFgRRaRLVFhbJ2EdiN5gbK7toObTPn6eYdPTvNzPvOBz5Xh/ec5/n/n89zXtEHmZqeSXSuXBz/3zfdKvBWJHQrwZuRcP0El+QkbQXeBX6WZEgm6TtJk5lM5o4Lc+cV6qpf4Ga20Tm338zeATItVK9Ker6yvPzp4NDQ3+XieGsCU9MzTYumGbhz7m4ze9/MHgvBgItACrgfGAj2jgAvAYs3wlEujjc13kii8YyZrXXOfWhmo9GnFUlvOOemarVapVqtkslksmb2KjARqL62ecuWN9NxbRInzrldAXhV0uFSIfdew7G/gNLU9MwS8CwSmE3Oz88fcXG5blfpqVRq0Ix8VIAAX0XgrVL7HDCHGcCaWrV60LUBN8Dae58aQIxEqcA592I9M610JL0cpG/U9TIHJNKY3RV5z0R+7Nd4HZ0P1g/2RMBuegLAsRMnb4vT8d5vqKfMzOgtAlADrkmqGywmiMBTwfr3dC9j1Xv/r6Tvg/5/5ejxE6cO7M9faVbQZrYNOFSPmqQvVo9FKexvi5uWX58943aM7DwAfBDY+FbSCxP5sdkGx55GeguzrUEXPaSo2pFkAbiSZQCAzZJOmdkjwd6SpB/M7KykQTPbA2wDhoIzRzcNDx9MJwGNIXdJ0mEzmwbujL7dbma7gd03A7lKfnTOvf74nl0r6bonTUbujRSUCrm2d4L3/kvn3JPe+8+BDW2i9o+kT7z3kxP5sYsA6W47oE64TsR7P9tQL4vA2mh9WdIscKxUyJ0M7aR7acOGzikD65EQLEjaa2ZXzMwDFeB6qZBbbLTRE4EGeSaozNOZgYFf8qP7lmIvs354n0qlHpB0T7B9Ogl4IgJJrmjv/SiQjbrkD+BMUkfSbYATPdckrTOzkciWAXOlQu5cYgLdPEIapud9wMOR9zVJH3ViKx333mtHMJvNuoWFhZ3A+ojMcja77njXBEKwJJfTcqUyCIQ34Mf7nnh0paMnXacFuGoC1mr3AtuDfLzd8Zuyl+rfuGn4HLAD+Az4qZQf+61TAj0Noj8vX6oC35SL43u7teG6rf5+iXppwW7/JUL5D03qaFRvvUe+AAAAAElFTkSuQmCC");}.bk-root .bk-tool-icon-zoom-out{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gEMEgsHgty9VwAAA0FJREFUWMO9l09oXFUUxn/fmXlpItppi22k7UJBRSlVkCytSAuKUloIdjKT0El3FXVXdVFKRVAQV7qQohsNwdA0UFvBhYtqUVyIVlRaogtFQVq7qSTVjA3z3nHzBq/jvPmTN/Ss7rv3nvN99/y794kByMzcfE/7picn/jenmwWeRUI3E7wdCRskuCSTdDfwBvCtJEdySV9KOhpF0e0/LF5SqKtBgbv7ZjObcvfXgShD9Zqk5+orKx8Oj4z8NT05kU1gZm6+bdK0Azezu9z9hLs/HoIBvwAF4H5gKFh7B3gBWFY3460kWve4+3oze9fdx9OpVUmvmNlMHMf1RqNBFEUldz8OHAxUX9q6bduryut+Sfvc/Wz62ZD0fK1afjND9y3gGSRwv1GMojstTxUUCoVhdyopEYDzKXjWwZ4FFnEHWBc3Goet00m7lZlZYQixKw0FZnakGZksHUnHgvCN5/KARBH37enpOVg58H13HV0Kxg/kIuD/ngSA2ZMLt3bTSZJkUzNk7k4+D0AM/CGpaXCyBw/sC8Y/qZd2GpZiuL9YLN4Sx/HpoP5/c/exQ1OVq+1yyt13SLoArEsJnMjlgfOffvK3u58Kprab2QezJxfG2iTzUzI70wRPG9jbmpmb95SNB9mpzp7/j2yVdNbdx4K565K+cvfPJQ27+x5gBzAS7Hlvy+jo4WIvoC3kWpcvS3rR3eeAO9K529x9N7C7zX6AC2b28hN7Hl1Vt44niVq13LUjmtlYkiQfA5s6eO+GpDNJkhw9NFX5ueNt2ARodyF1IHIN2JiOl4H16fiKpK+B2Vq1vBAqFAf4IJkGNiIhWJK0192vunsC1IE/a9XycquNXARa5OnApeeioaHvKuP7r3dTGsiLqFAo7JR0T7B8rhfwXARa2us4UEqr5Ffgs151i/08oTNKdIO770ptObBYq5Yv5ibQq/sl3Qc8lJ4+lnSqH1vFfp9koZRKJVtaWnqkWXqSVkqlDe+vmUDWpZMlK/X6MBDegKf3P/nYaj8ErN9fqZBYEsf3Ag8G8Xit33BaniTcvGX0IvAw8BHwTa1y4Md+CeRqRL9fudwAvpienNi7Vhu21uwflOT+L+i1X2TJP57iUvUFtHWsAAAAAElFTkSuQmCC");}.bk-root .bk-tool-icon-help{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAABltpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIgogICAgICAgICAgICB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIKICAgICAgICAgICAgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiCiAgICAgICAgICAgIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIKICAgICAgICAgICAgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIj4KICAgICAgICAgPHRpZmY6UmVzb2x1dGlvblVuaXQ+MjwvdGlmZjpSZXNvbHV0aW9uVW5pdD4KICAgICAgICAgPHRpZmY6Q29tcHJlc3Npb24+NTwvdGlmZjpDb21wcmVzc2lvbj4KICAgICAgICAgPHRpZmY6WFJlc29sdXRpb24+NzI8L3RpZmY6WFJlc29sdXRpb24+CiAgICAgICAgIDx0aWZmOk9yaWVudGF0aW9uPjE8L3RpZmY6T3JpZW50YXRpb24+CiAgICAgICAgIDx0aWZmOllSZXNvbHV0aW9uPjcyPC90aWZmOllSZXNvbHV0aW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFlEaW1lbnNpb24+MzI8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+MzI8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogICAgICAgICA8ZXhpZjpDb2xvclNwYWNlPjE8L2V4aWY6Q29sb3JTcGFjZT4KICAgICAgICAgPHhtcE1NOkluc3RhbmNlSUQ+eG1wLmlpZDpBODVDNDBDMzIwQjMxMUU0ODREQUYzNzM5QTM2MjBCRTwveG1wTU06SW5zdGFuY2VJRD4KICAgICAgICAgPHhtcE1NOkRvY3VtZW50SUQ+eG1wLmRpZDpBODVDNDBDNDIwQjMxMUU0ODREQUYzNzM5QTM2MjBCRTwveG1wTU06RG9jdW1lbnRJRD4KICAgICAgICAgPHhtcE1NOkRlcml2ZWRGcm9tIHJkZjpwYXJzZVR5cGU9IlJlc291cmNlIj4KICAgICAgICAgICAgPHN0UmVmOmluc3RhbmNlSUQ+eG1wLmlpZDpBODVDNDBDMTIwQjMxMUU0ODREQUYzNzM5QTM2MjBCRTwvc3RSZWY6aW5zdGFuY2VJRD4KICAgICAgICAgICAgPHN0UmVmOmRvY3VtZW50SUQ+eG1wLmRpZDpBODVDNDBDMjIwQjMxMUU0ODREQUYzNzM5QTM2MjBCRTwvc3RSZWY6ZG9jdW1lbnRJRD4KICAgICAgICAgPC94bXBNTTpEZXJpdmVkRnJvbT4KICAgICAgICAgPGRjOnN1YmplY3Q+CiAgICAgICAgICAgIDxyZGY6U2VxLz4KICAgICAgICAgPC9kYzpzdWJqZWN0PgogICAgICAgICA8eG1wOk1vZGlmeURhdGU+MjAxNjoxMToyOCAxMToxMTo4MjwveG1wOk1vZGlmeURhdGU+CiAgICAgICAgIDx4bXA6Q3JlYXRvclRvb2w+UGl4ZWxtYXRvciAzLjY8L3htcDpDcmVhdG9yVG9vbD4KICAgICAgPC9yZGY6RGVzY3JpcHRpb24+CiAgIDwvcmRmOlJERj4KPC94OnhtcG1ldGE+Cphjt2AAAAT7SURBVFgJxRdbaFxFdGb2bhui227BWrsVKYgf2kJUbP9EUPuzEB803WTXJjH61Q/7Ya1+CMYKEVTsh4J/EpvY7BoabUiNiA8s1p+4KIhpoUUEselHqyS76TbZ3HuP58ydc3d2u4+IkQxczpz3mZkzZ86VYpXjvenpjZsLhUcliE4AuUuASAgptmt1EFdwPiclzIIUUwubNn17OJlcXo1p2UpodHRiux9xB1Eug1+slbzhFxGOKc851tu7/0oznYYBDA8Pt0U2tL8KQryIq2tvZqQhD0QJHRz3yqWhgYGBpXpydQMwqz6NCnurleCSADkJEfgKfOePqL80R/wV1ZaQyr1LenKfkPCkEPKeaj0xg7vxVL3duCmA0Vyuw/fl52hgBxsBED+h4Cv9z3R/zbRm8MTJTx7HQN7GQB6w5C4L4SX7M5lfLBpurjXMyvNIShiyi0l1pL8n9b7EDGPR8fHxzSsQ6XDB3618/xqo6Pk25V5MpVJllgHM1BO58RdQ612kOYZ+GXdij70TYQB05mpj+1kU5G2fB+l3PZtOf8NGx6ambnMXb3yAxg8wjSEG6OKKR9oicBQD+ZvpH2Wzj0lQpxCPG9qMv1x6hHNCsSAlHM7ZOa682vlI9tRDbvHGbD3nZAPpDoD/3JIrLpAs26UFkC3EMUA99hpfGtEBfJjNJnS2Gwnadnvl+Xw+iuc3DAJuNyIaSCHpilVldyDjjUxj3WDZIAhxhHHyRcdNuA7AAfUaXzVKODpzFiZ4/uLvh5G+m2no+C/pyIf7MqlEJB7bpqR6nXkEUfbeawuLaZsW2ISfNQ2vtaktQlGFQyIVGT0o2+2EC4iQNGwjBIN9qdQ5Qg4mk4X4rW3vCClLtowE2FOFUxKDfNmiZci3ovKKRFPh4FK9q4Zbdr+lKKJiA13TcHR2dmLBgdmQ0GAS2MZaEowY+XbAk09IvgtYZGp16SyvFhaHcIUh645t8T9DBCcnz5zZ4hZLu3DzK2QlL1QQa0Y+pHiJKPSuOGj3PmZTheM5w2TwqBxnvBZOTk7G5gvXJ5Aelms8wnJURL+olSWcfEhf6gDoUXPMq6ZlqbzWU2pE+3hi4s6F68tfIj9cBMlikr7Z0/P0b/X0yIcUXsDCF1WhtL4OROHaXk+xlkbV0Cu732Nmhc4peaWSg73pA8dq5RkvO37ldUTfXCKZv2q45MkhvG87WQEzpCCUSvV1d9GONBy3lMvgKSwrZig8gjAietWY0QriylO2jIo4yVbOSb7KB/qmI9BPKjHpSSXYauRyn92Nq9/Kcrj13x3s3v8D481glQ/0raiNYgX9njPSBOImbrHZePl+tfFmc9sH+Xaoh8NjOKSVdDMhjjYzQLy+dFceH5+IJQf9VYXX4tROg4ZFU8m31M3mfPEqUoJqCGJfvWpo2xnNfdrhC28n06SCeSzNZxlvBINGRXCtKS7EY1uV6V7HWAm38y1cXaXsMcOCvr9ySPj+af7A1U2HJXHzVNvUXVLIGyPf+jV0pf8GHoN+TLAyPkidTCi2RpPApmnR0Bd1zGRaB/B8Oj2HSw7LLbVR1MmskW8RdEWVXSJf3JbpAMgRtc4IZoxTh9qotQjCasm46M0YX9pV1VmbpvRH5OwwgdRtSg2vKaAz/1dNKVtb17Y8DCL4HVufHxMOYl1/zTgIgiYvBnFKfaNp3YjTdPz3n9Na8//X7/k/O1tdwopcZlcAAAAASUVORK5CYII=");}.bk-root .bk-tool-icon-hover{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gEMEg4oVHp0SwAAAQJJREFUWMPtlsENgzAMRb8RQ5VJItFDOgaZAMaAA0iZpN3KPZSoEEHSQBCViI/G8pfNt/KAFFcPshPdoAGgZkYVVYjQAFCyFLN8tlAbXRwAxp61nc9XCkGERpZCxRDvBl0zoxp7K98GAACxxH29srNNmPsK2l7zHoHHXZDr+/9vwDfB3kgeSB5IHkgeOH0DmesJjSXi6pUvkYt5u9teVy6aWREDM0D0BRvmGRV5N6DsQkMzI64FidtI5t3AOKWaFhuioY8dlYf9TO1PREUh/9HVeAqzIThHgWZ6MuNmC1jiL1mK4pAzlKUojEmNsxcmL0J60tazWjLZFpClPbd9BMJfL95145YajN5RHQAAAABJRU5ErkJggg==");}.bk-root .bk-tool-icon-crosshair{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAADEUlEQVRYR81XXVIaQRCeHqug8CXmBNETaE4gniDwIgpVspxAbxC9ATkBkCpQ8gKeQDiB5AQxNyAvUlrldr7eHxyGXZi1rMJ5opbp7m++7un+htSGF204vsoMoNXrlzSpfWa1oxQfhAegCZGaEtPorHo8znIoJwCt6+td8uk7ApUQCIHTF4BNAWzImq8ap6cP68CsBdDp9i9ZqXM7ML79g/EnCWD+jgMKENKqWT+tXK0CkQqgNRjs0OxpQIqKhoMxaG6/6JeRnK7T6yO2UvVqhYSlLX+ryORfgKn9ORDFIy7ky41yGcwsr0QAQfDH5zucOswx819fs4egI9OFCcD8DjBF7VNbEX0JzdWEt3NHSSASAcCxBDqMgt/623kvyTgNgNjJIfTjk4D4FqaJR1715MjmYAmA5Bx3AwUXQL+t105KaTlcBSC26XRvhjEIoLiq1yqXpr8FAGG16/ug4IT27fxBWu7EiQuAiImJpEMKE6nYM30uAIDDttSUOPfJP7JzbjPhAiBIh9QE67vIvoOi9WJfCwDavf40ulpjbCqmUf+W753ezURuh7Dg1SqflwAEHU6pgfyBq9Y4qx0LG++2fnZ/eUzcstmdM2AWH+jfc+liWdBJfSENf8Lifi3GVwC9mybOfi5dzatWVrbbLIHNva8p5h/16gkaFiLGGxbufkoE6XguwePiXLF3XmMfCUCUAqtKXU7sumd1CowOuJEi3Pg1FBpjitIGhyvVSfvmjci6ZR+rFQfDiPVE2jFYeICQ+PoewwjC5h7CZld6DBdyu6nDSKgzOyIMhmhK5TTqXYbRorZYM46TmpKAAOrGWwSJJekSB1yqJNOzp1Gs7YJ0EDeySDIMtJbQHh6Kf/uFfNFZkolJICRmz0P8DKWZuIG2g1hpok+Mk0Qphs0h9lzMtWRoNvYLuVImUWrmPJDlBKeRBDfATGOpHkhw670QSHWGLLckmF1PTsMlYqMJpyUbiO0weiMMceqLVTcotnMCYAYJJbcuQrVgZFP0NOOJYpr62pf3AmrHfWUG4O7abefGAfwH7EXSMJafOlYAAAAASUVORK5CYII=");}.bk-root .bk-tool-icon-lasso-select{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gEMEgwlGP1qdAAABMBJREFUWMO9V1uIVVUY/r61z57ZMx4DnbzgkbQXL5iCJphlWdpIGY4jpFBkEiU9ZNaDRRcITcIwMwgxoQtU2IMXdAZfMjFvpERXYiSbysyBEXFmyuHMnLP32uvrwT2xnY5nxvHQ93Jg7fWv71/r//7L4a59TRgqJk+Z6v3a+sv0OI5nk5wu6VaSVZImAThHsgjgrKTvM5nMUWvtmf5n8HodCIKgOgzDhc65pSTrJQWDsSNpJX1ljHnDOfdT37oZLLHv+8OMMasKhcIJ59xHAJYMlhwAJGUAzJfUTHLFuFzOG5QDU6dNMyQfs9Yedc5tBpAD4IYYNQGoBrDtQnt7/b0LFrJsCHzfn2itfQfAnZLiazytA3AaQAuAiwDaEgeNpGkkswAWSBqRONB38b88z5uTKePt6iiKXkk8jq+iJC5LOmiMaTLGHLPWhmWeHr7vV0dRtATAapAzIVmSo51zyzIlbm2stesFPA6pKk0r6Ryg93y/ek8YFvPOOTg3cDSiKCoC2OP7/rEoirYm4rUkF12lAWNM1lr7lqQn0+QA8gI2jBg5cj6Aj8OwmB+KAKIoukhyp6SRJAUgl0ndPLDWPi9pJQCbuviXvu+/GIZhW1dnJ24UJFuTjCCA2ADA8sYGWmsXS3qmL94kDYAtkh4Nw7ANlQJ5U6INT1KrAYC9zQdykl7nFSj5fXp5Y8NWVBhy7mUAjqShMYdMXV2dJ2klyRwAJ8lIeuGWCRMP7N7frEqSG2OmAFhKshNAp5wrmO7u7jEAngPQm1S2z2pqapr+OPt7XEly0oxwzq2RdFmSD2AMgKKJouhhAL4kA+Cs53l7e3t7uytJHgRBreTWkXwkKVJnJD0B4GAGwIJE9R6AFufc6UqSZ7PZbD6ff5dkA4CQZEHSqwAOISmXtwGIE+F1SeqqIP8d+Xz+C0mLJYWSAODteXffczjdDQNJ0BWMCoLg5gqIbRTJNwHsljQhUb0luWPM2LE7Thw/9m/5NCT/TByxAOYWi8X6/gdWV1dnfN8fNRBxJpMZTXKdc+6IpFVJWAEgkvSJpA0X2tvtVTaSjgOYBCAEEADYSHK87/sfhmEYA9gShuEDkgzJHyWtB/B1irQ2juP7ADxkrX0wOUOpzmdpzEY590HJ7Ni1r2kSyZOSiv2+hSRjSTXp/QAukzySNJOJkmalyNIl10hqMcasdc61XDNcQRD8BnITgNp+36r6kfcNFMMlLQGwTNLMEuQGQBfJl2bdPru+HDkAZAqFQux53jZHEsC6aw0eg2gylNRBcqcx5v04ji999+03AwsWAOI4Lsy9a94WkisAnE5a5WCJYwCfA1g7LJudI2lTHMeXBm1faiQzxkyRtF3S5CTupeAB+KG2tnZFT0/P30NO2VKLzrmfAbwGMipjG5Oc0dPTc0Md05SZ5U4Q2FxChErtEYD7jTGNQ3UgM8Asv90Yc9I5LSKRlXSI5CxJa0jWSALJjKRnAewfkniT+vwf7N7fXHK9rq7O7+jo+BTA/NRrdBpjnnLOnUrvXd7YMPQXSBunneno6IhIHgYwW1JtkgmBpBkATlVMAwOk3nFJ+VSoqgCMr6gIy2FcLtdKspAedyQN/98caDt/3kpyabUmf8WvG/8A1vODTBVE/0MAAAAASUVORK5CYII=");}.bk-root .bk-tool-icon-pan{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gEMEg4lKssI9gAAAOtJREFUWMPVll0KwyAMgNPgoc0JzDX2Mtgp3csKErSamGabIEUo/T6bHz0ezxdsjPJ5kvUDaROem7VJAp3gufkbtwtI+JYEOsHNEugIN0mgM1wtsVoF1MnyKtZHZBW4DVxoMh6jaAW0MTfnBAbALyUwCD6UwEB4VyJN4FXx4aqUAACgFLjzrsRP9AECAP4Cm88QtJeJrGivdeNdPpko+j1H7XzUB+6WYHmo4eDk4wj41XFMEfBZGXpK0F/eB+QhVcXslVo7i6eANjF5NYSojCN7wi05MJNgbfKiMaPZA75TBVKCrWWbnGrb3DPePZ9Bcbe/QecAAAAASUVORK5CYII=");}.bk-root .bk-tool-icon-xpan{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gEMEg4X4hxZdgAAAMpJREFUWMPtlsEKwjAMhr/pwOOedINJe/PobWXCfAIvgo/nA4heOiilZQqN2yE5lpD/I38SWt3uD9aMHSuHAiiAAmwaYCqoM/0KMABtQYDW11wEaHyiEei28bWb8LGOkk5C4iEEgE11YBQWDyHGuAMD0CeS30IQPfACbC3o+Vd2bOIOWMCtoO1mC+ap3CfmoCokFs/SZd6E0ILjnzrhvFbyEJ2FIZzXyB6iZ3AkjITn8WOdSbbAoaD4NSW+tIZdQYBOPyQKoAAKkIsPv0se4A/1UC0AAAAASUVORK5CYII=");}.bk-root .bk-tool-icon-ypan{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gEMEg4anK0lywAAAMVJREFUWMPtlzEKwzAMRX/S7rlpIMXeOnaLaME36FLo8XqCdNFghGljyc4kgQi2Q/SUj0F/eL7eMMTKz6j9wNlYPGRrFcSoLH4XxQPvdQeYuPOlcLbw2dRTgqvoXEaolWM0aP4LYm0NkHYWzyFSSwlmzjw2sR6OvAXNwgEcwAEcwAEcwAEcoGYk20SiMCHlmVoCzACoojEqjHBmCeJOCOo1lgPA7Q8E8TvdjMmHuzsV3NFD4w+1t+Ai/gTx3qHuOFqdMQB8ASMwJX0IEHOeAAAAAElFTkSuQmCC");}.bk-root .bk-tool-icon-range{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAABCJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOmV4aWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vZXhpZi8xLjAvIgogICAgICAgICAgICB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iCiAgICAgICAgICAgIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyI+CiAgICAgICAgIDx0aWZmOlJlc29sdXRpb25Vbml0PjI8L3RpZmY6UmVzb2x1dGlvblVuaXQ+CiAgICAgICAgIDx0aWZmOkNvbXByZXNzaW9uPjU8L3RpZmY6Q29tcHJlc3Npb24+CiAgICAgICAgIDx0aWZmOlhSZXNvbHV0aW9uPjcyPC90aWZmOlhSZXNvbHV0aW9uPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICAgICA8dGlmZjpZUmVzb2x1dGlvbj43MjwvdGlmZjpZUmVzb2x1dGlvbj4KICAgICAgICAgPGV4aWY6UGl4ZWxYRGltZW5zaW9uPjMyPC9leGlmOlBpeGVsWERpbWVuc2lvbj4KICAgICAgICAgPGV4aWY6Q29sb3JTcGFjZT4xPC9leGlmOkNvbG9yU3BhY2U+CiAgICAgICAgIDxleGlmOlBpeGVsWURpbWVuc2lvbj4zMjwvZXhpZjpQaXhlbFlEaW1lbnNpb24+CiAgICAgICAgIDxkYzpzdWJqZWN0PgogICAgICAgICAgICA8cmRmOkJhZy8+CiAgICAgICAgIDwvZGM6c3ViamVjdD4KICAgICAgICAgPHhtcDpNb2RpZnlEYXRlPjIwMTgtMDQtMjhUMTQ6MDQ6NDk8L3htcDpNb2RpZnlEYXRlPgogICAgICAgICA8eG1wOkNyZWF0b3JUb29sPlBpeGVsbWF0b3IgMy43PC94bXA6Q3JlYXRvclRvb2w+CiAgICAgIDwvcmRmOkRlc2NyaXB0aW9uPgogICA8L3JkZjpSREY+CjwveDp4bXBtZXRhPgrsrWBhAAAD60lEQVRYCcVWv2scRxSemZ097SHbSeWkcYwwclDhzr1Q5T6QE1LghP6BGNIYJGRWNlaZItiFK1mr+JAu4HQu0kjpU8sgF3ITAsaFg0hOvt2Zyfvmdsa7a610Unx44Zgf773vvfneezPHNzrbhn3CT3xC3wPXYOC8LDzqdi8YY/gwh4BeknS/2th6dr2kf94AOp3OFyWgMyziOPbMDxV9FTtJnl1ut795Xd0/YQ0/vtYQwMT1KXWCfr2IjOWwtNehwN4xL9ykTrm6Pzl58yLn3J+mKh9mXbT3uRjGEDph+O8/TjfP5dBp7Ha7AX7O3o5nZeD/0E/OGyXntDgzA0X6qmCnrVutVlrUWV9f/3xo+pwhGDhvEPHOjoxnZjJggXmMHzBQ7NGNp9vxk61fr0HR7e/u7pZzCGHlc7qwBYYTT7tJYSx1AQzppyFPft5apta9w7SKcn0b7P7+/jCsDQ5mbc0dCmIJGDN0ehdcjsmkm6A6KUeKFOTE11PLxrC7Ukqh3ylL2fT0NAP9q6ur6rRCJJYsbKB0JsbCKMuy+xREePDyxQPCz+Crlw062QcA5wBOOt1l6vIl2WiI9F1fN6Q+BBqit6hEC4Hk08GQJMn4myjSP7RavVxgdaVUh/3U6HCMsPr9pYnJKRziHtWQ+un58+hGs6nsjQSjpuTyKGN3CX+FBwHXSiEVgjP+O8X6N12kIePES+GzTKAkGbNp8yJsGUMVzz8jPKReiyAQRimy5/cjye5RpF8utFp/+nwmT7d/NMzcFkS7yjJNGDaPURQxIQThEQy0SyF4l5WJYYhBa816vZ6dU7A6CAhbZVow/pDe0O9hVOoCi13r4BgBAvJHqMSQL2vE/iH6IAXEwgrRVUmBoRRwnwJQT98xEeVeSUyB4dJ5nwJBKdCFFGRmUCcu7rwIYypCTblaChuNBhWODrman5ub+4v0rMNBt8z6Ezh7GksJQpCbm79cMQE7QBFm/X6f0rjWnv8WRYg/QdbUpwDAEBy8vPyA8rNGzg3a8MiElwiM7dAtRqNoNptjGPM1laVxP9umWEMGLOKhKUOJDtBwDmzsw9fC/CzHr9SGuCTi2LbbKvVtmqXpCjMihBFa79Wrt5fGx9PDzc3fmu32Lf8qFliwU9emKhBSp+kRKn/hu9k1COEDbFdt/BoKWOAkuEbdVYyoIXv8+I/QK9dMHEb1Knb7MHOv8LFFOsjzCVHWOD7Ltn+MXCRF4729vWMDK+p8rLkvwjLg4N4v741m5YuwCI9CvHp1Ha8gFdBoPnQAkGsYYGxxcfEI7QQlFCTGUXwjAz4tWF+EpymOWu7fglE7qsOvrYE6g4+9/x/vhRbMdLOCFgAAAABJRU5ErkJggg==");}.bk-root .bk-tool-icon-polygon-select{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gEMEjc1OfiVKAAAAe1JREFUWMPt1r9rU1EUB/DPK0XbqphFHETo4OCiFhwF0V1KHbRSROLqon+AUMVRRFBwEbRFMBiV+mMW/wIxi5OD1kERRVKRJHUwLvfBTZrU5OWBGXLgQu7Jfe98z/ec7z0vKa88b2q1BDtRHdAPBaylm1NzsxsOjPnPNt6WSWprbft+/c3I3zOAjhT1Y4+fvcjEQJIXnVECSa+AhqIHqlHH5lWCZoe+Gk4GRgDG86j9SAUdlDBSQaZhlOkuHyoVdJmsw98D1S5fM4NYM1LCpqM+Lwa240oLgmZzpVZvzKT75VLZcqksSZKWlQeAy/iORVwIvh31xvotvK7VG3Px4aWHj3Jl4C2uYSvq+Bn8v6LLbaVWb9zsBiKLCvbiNG7gLm7jAYqbPHMJMziZ9lsKoh8GtqCEVVzHftwJn+TFHp4/hg8BSCYVfMOZoPEv2NZGdy9WCGUr9toDR3E2/H4V6nwRe/BmgN65H1ZhvMuB3XiKIyFoGefwO6ysVkUlrNUNsyAK/jli533Q+Y8cJFvAeXyMS1CI/jiMr/gUtD2LQwMGr4R3p7bY3oQHQ5b38CT4D2AXXg6YcQXHpyYnlqKsi5iOAVSwL9zd7zJ09r+Cpwq72omFMazjT9Dnibym0dTkRDUKrrgwH7MwXVyYB38BstaGDfLUTsgAAAAASUVORK5CYII=");}.bk-root .bk-tool-icon-redo{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gEMEg4itK+dVQAAAaFJREFUWMPt1L1rFFEUBfDfJDaBBSslIFjbaSFp1FJQFMVCHkzhKIqdUYOCoBgErVz8rCwiTDMwBCIKipDWyip/gxAIWAmBgBC0eYFh2Gx2l9lFcA5M8e59782Zc84dWrT435Hs1siLchqn43MS0zgW22vYxjesYjVLw3YjBPKinMUTBOwf8J5fKLGYpWFjJAJ5Uc7gIW6jM6Kim3iNZ1katgYmEL/6I+YasvY7Lg6iRpIX5VF8wuEe/XV8wGf8jN6LWTiAc7iEQ7ucPZ+lYW0vAtfwvlbfwCKW9gpXDOv1mJvZHiSO91MiyYsyiQSuxtpXXM7SsDmM5nlRdrCMMz3sOJWl4Xevc/vwBzdwAl+yNNwZxfRI+GxelK9ikHcwh8d4NNR/YFRES1ZwoTYdR7I0rNf3TzVNIGbmSvR/Bx08mIgCFSVu4l2ltIWD9WxNGR+W8KOynqnZ0rwCeVG+wa0hjrxtWoF5dAfc28V8Mib/n+Nev5dnabg/zgw87aNEN/bHOwVRiRe4Wym9zNKwMKkpgIWKEt24njxiJlq0aPFv4i9ZWXMSPPhE/QAAAABJRU5ErkJggg==");}.bk-root .bk-tool-icon-reset{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gEMEg4gWqH8eQAABLdJREFUWMPtlktsVGUUx3/nfvfOlLQaY2IiRRMQIRpI0PjamJhoVASDvNpCpYw1vJQYSVwZwIVQF6wwRHmkAUof9ElrI6VqDAXcID4TF0IiYQMkSlTokNCZ+b7jove2t+NMH7rQBWd3v+989/zP+Z8X3Jb/WGQySvUNTQBJESkNguAVYIWqzhaRhwBU9WcR+QXoymazn6jqzUQiMQSQzWZRVdal1vwzAI2tHQBPOuc2AbWTdOyQ53n7nHNfRwee51GzqoIQMCLDpr3x/tLQ0oZzrk5Vj0/BOEBt+KYuOlBVGlrahr0Wob27t3gEjnZ2AyQzmUwHsDgP6J/AYRE553neDwDOuUdU9QngNeCumK4TkRMhZUORcYC1qysLA6iuSQHIwkWLD6lqapQsuSmwTVV3h99I7EcAR462A2xR2Ilq6ehTaejvO1774kuLNALR33eclsaGsQDe3fYegHl43vyNwEeqGl1963mm2jl7YZRTQ82qlWP4HM6ZToC5ztkW4LHQoALru7s6Di5dvlIj/e6ujrEAWoZDn8hmMjXATMACGaAVuBjXTVVXFc/AxhaA+4zvn1DV+eHxVWPMAmvtb5GeMWZyZVhI2rt7qVy2pOh9U1snwIPW2vMi4oWJuBPYHkVAVScPoKmtkzVVK6cEMsyJraHhiCqJqJUwj/JRz7TW1iSSyR2rVyylqa0Ta+24Ic8vXaAEmDFc/l5Z2A/80OibuVyuz/f9ElUdHCmvw82t5HK5h6y1PYhsz2YyGw43t2KtBZHIGwB6+j4rCkBVUdV7gXrggnPuu8h4eP+xMeZS2D0rJYZ6AdAMzAt1b4nI26p6IFZOY8pugijcKSIHVLUK0LyST4vnrVfnWr3mjmP4QTATaERkXkypRFX3isjmuHdRJEK6Ckqquopp06bdKCkp2Sgi7XnGLcg7gzeutwNIiPYc8HixqIrIOlU9ONVIhHPEd851icgSVXUiskVV94gIqoonIt0i8gfQCfwae38e6BWRXuBZz5jZ8VbaOE4EIqlZVUEQBLlkMplS1QER2RwkEnsSyaREDUzyeNsvIhvCMqkH1kdIJ2o+k8iJB1LVVRfjZ6nqqlEAIbdVQGto8Lrv+/dbawcjAL7vc+6bs+zetetfLSHxniIFGofGGsU2oC7eOCbDfZ7nQawBOSAX74SF9oEPImOq+r7nmVmxb5raukZa8UReGmNmhbMkAwwBH467EYVZe49z7kdgenj8k7V2oTHm8kgdWcvrNdVFjR8cHkYzjDH9wLjDaEwEzpwa4MypgWvAjtjxfGNMj4jMiT+M+kFsZI/Q6Pv+HGNMT8w4wI7TAyevxXVPD5z8+zD64tRXAMHVK1eaVLUyVvuDqroV2BOnJF4ZIedviUidqt4Re9s+vbx8zZXLl7PR2+nl5Tz/zNOFp2FzxzGAklw22wUsLLaSKXwf8vhosZUM6PeDYEUum70VHfpBwKsVyyfeikOP6oBNwN1TrLbfgX3A1kKLzKeff8nLLzw38T5wZDgxn1LnNk5lLRfP26/OnR2hwfNYW2Atn9RCsrf+EECyrKysDFimqhXhyjY3VLkAXBKRDqA7nU6nS0tLhyIj6XSaN9bVclv+l/IXAmkwvZc+jNUAAAAASUVORK5CYII=");}.bk-root .bk-tool-icon-save{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gEMEg4UexUIzAAAAIRJREFUWMNjXLhs5X+GAQRMDAMMWJDYjGhyf7CoIQf8x2H+f0KGM9M7BBio5FNcITo408CoA0YdQM1cwEhtB/ylgqMkCJmFLwrOQguj/xTg50hmkeyARAYGhlNUCIXjDAwM0eREwTUGBgbz0Ww46oBRB4w6YNQBow4YdcCIahP+H5EhAAAH2R8hH3Rg0QAAAABJRU5ErkJggg==");}.bk-root .bk-tool-icon-tap-select{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2hpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYxIDY0LjE0MDk0OSwgMjAxMC8xMi8wNy0xMDo1NzowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo3NzIwRUFGMDYyMjE2ODExOTdBNUNBNjVEQTY5OTRDRSIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpCOTJBQzE0RDQ0RDUxMUU0QTE0ODk2NTE1M0M0MkZENCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpCOTJBQzE0QzQ0RDUxMUU0QTE0ODk2NTE1M0M0MkZENCIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1LjEgTWFjaW50b3NoIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6OTQ0QzIwMUM1RjIxNjgxMUE3QkFFMzhGRjc2NTI3MjgiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NzcyMEVBRjA2MjIxNjgxMTk3QTVDQTY1REE2OTk0Q0UiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6eYZ88AAADLklEQVR42rSXf2TUYRzHv7tuGcfE6Vwb5zLSSjEj7Y9KWqfEmFZJP+yPMdKKmUrrn0iUfjhWlLFi6YfNrF+StBoTo39iYkTGco4xxxG59P7k/T2PT8/37nu3bx9ezvPj+zyf5/PreS78bGLS8SmrwE6yje3NHJsDBTALpknBz6JhH3NiYAB0gHqPOVv52wJ6QQ48BzdAttTioRJjdeA8mAHHS2xuk3p+M8M16ipVQE49Ds6CiFO9RLjGONf05QLx6wPQaBlbBlPgJVgkP0ETiIJ2sB/E1XfimjfgBOOlKDUqCGOcqBcQnw6BYW5YTo4wbvQhMmCfGRemC2rBiGXzWUb+kM/NRZ6CHWBM9ce5R61NgX6ayhSJ5EPlItlDRNkz4JbFHf06BkSzHjXxM+gDv1S/mPUo2AXWgt9UUHL/IVhS8yUV1/EbV3o4N+NaoE9Fu/i827K5pNYHnqAVJECShWmAaddpscYFFXwR7vnXBRGlnUN/L6kqKJlxnRUuDbaDBiL+vst5d4gpcpBrqk/2jIgCKVUolhntplzivHmwh4stGOPfwBWwl/2dpp8p7xjQZqFLiQJtauKkivYm+kzccpK57yXfOUe+P23JqAnVbhMFmlXntCWnxbT31am9ZJ4BJifsUmNTqt0cYhA5ypympPg7VkEKunPbVb8cIG+0kyHLJZNR7fUMooUKFHAPkfQo58VLK+RzwRDd4FdWG9mjpaAXzqkJa1R7kQttqEABWXMjOOxxVRfnhRm5URX1prk/0pQHwNcKlchZ+jdpC+hFdVqO0my9Hj5dkYgCn1Rfh/KdlNDHrJhPqlDih+IfBd6qwpOgEqYMsorJ2HtWxtagLJDn/W3KRfPOZhoeBJfZPgVeGKeKrkQBh5dLXl25Ny3pc4/1fkTdbvFqFQgbxWeYD0hXulhQ0pYiM1jG547fcbMQpVnHTZEn9W3ljsCzwHxCdVteNHIZvQa7/7cC7nV6zHIfyFP9EXjFa7YxKAVqPP4bxhhoLWW+z9JyCb6M/MREg59/RlmmXbmneIybB+YC/ay+yrffqEddDzwGvKxxDmzhc0tc80XVgblqFfgjwAAPubcGjAOl1wAAAABJRU5ErkJggg==");}.bk-root .bk-tool-icon-undo{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gEMEg4em8Dh0gAAAatJREFUWMPt1rFrFFEQBvDfGhACASshkL/ALpWVrSAKEQV5sIULWlgZNSgIFkGIVQ412gkBt1lYLERREFJqJRaW1oHAoZUQsDqwecWy7N3tbe6C4H2wxc682Zn3zTfvLXPM8b8j6RqYF+UCzsfnHBawGt3fMcAX7GEvS8NgKgXkRbmMxwg41TLsN0psZmnodyogL8pFPMIdLHUk7hA7eJKl4U/rAuKu3+HslFr/FZezNPSTFslX8QErDe4DvMVH/Iq9F7VwGpdwZUjsPtaSFjv/1vCBPjaxO0xcNbHejLpZrrlvJCMCT+JzA+2fcC1Lw+GE4l3CG1yIptfjCtiKoqtiJ0vD3aM0Py/K57iIMxgkQxat4EdN7e9xdRzlk+LEEPvDWvIDXJ928sYxjL36icWK+VaWhlezOIqbGFirJd/H7szugrwoX+D2BDEvszSsT5OBdfRaru/F9dPXQF6U27g/KnmWhgctxqyzBrZGMNGL/rHI0nDkKXiKexXTsywNGx0OnFbFNk3BRoWJXnw//j+ivCi32/S8CxPVNiWOAdUiJtXITIqYY45/Cn8B2D97FYW2H+IAAAAASUVORK5CYII=");}.bk-root .bk-tool-icon-wheel-pan{background-image:url("data:image/png;base64,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");}.bk-root .bk-tool-icon-wheel-zoom{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gEMEgskILvMJQAABTtJREFUWMPdl1+MXVUVxn/fPvf2zrSFmUKnoBCUdjRoVaIxEpO2JhilMYBCtBQS2hejpg1Uo2NUrIFAoyGmtiE+GHwQGtvQJhqDmKYRBv+URFsFDNCSptH60DJTO3dKnX/33rM/H7rvsDu9M20fDMaVnGTvtb69z7fWXmvtc/TEzqd4OyXwNsv/FwFJQVI/sA14SZKRLOlPkr5TrVYXHz70quYkEEK4TtI2YAgYkrQthHDdhV5uuw+43/ZrwCbgRttgY/tjtrc0m83X3/f+D6ydnJhYcB4BSZcBA7aP2d4ELAGW2N5k+xgwkDB0IH19CGGH7R8B1aQeAf4KvAw0ku4K2zu7uru3ApdPEyiKohd4TNKjtjt5h6RHgccSNrddbvuHtm9Jqoak7xVF8WFgdavV+pSk5cCObNmXgK++85prCj3z28HKqZMnH7D9YAY4BvwujT8BvCuL1INX9vVt+dfwcCvNb7f9q2RuSfrGvWu/sL2Nf3LX7pzvj4ENSGBPVarVd4fRkZFltjdmoMGiKO4IIWwIIWwoiuIOYDDzeOPoyMiyFLkum7WJCMDztrcrTTrIRuAQZ6NcK1utL4dWq/VZoC8BhqvV6l1lWb4YYxyLMY6VZflitVq9CxhOmL60hhCKeYiV7WMKIXw9jT1HpXw3c+bOAKzOjJubzebJrKQCQLPZPClpc7bP6rMYKtjXth2OMf7tIkr11Wz8oQDc1Fb09vY+kQw1YAuwJY2nbUluAnCWpKkaFl6IQIzxivaR2SYA89sJVK/Xp2x32R6w/a30DNjuqtfrU0ArYecDCEqgLqm94T0dEm9mBG7PxkdDlkBnkhebgIezNQ8nHcCZPL9ijE1Jf/bZZoPtzbavmqNZLbf9tSxq+yoduuJ+SZ+zXSZyBXCqU+d8fvC5yRUrV+0G2j3g2hDCLyXd/+Su3QdnvP/zCuH72LWsgf2k0oHlH2c2odlkxcpVEdgr6aDtjyb8x20/J+mA7T9I6rL9SWA5dne2/GdXLl58qNJh398An85yTMA+4DOz8Dgu6Zu2dwJXJ91ltm8Gbp7Fgb+EEB4aHhpq5CEtACqVyr3AC0AlPS8k3TSmQ2YPhhBuS/1/LpmS9JTtNTHGfwBU2uUALARotVqniqJYH2Pck85pfavVaufAwnQvnHc0McaDKVptebN94QAnJB0EdtjekydyZXqjs/0ZgLIs/w6sy8bnYGYJ63pgERKC05JutT1kOwITwL9tvzlzUQUYB+Zjs2DBgu6xsbGJZHstByZbezregcBXeCsEz1bnzXt5anLyzLq71zDLxTRdVgemdx0fv2e2w5thO5DbiqL4oKT3ZKpnpyYnz+SY2ZpTAPZmJfdIrVZbNBNUq9UW2X4kU+2dcf53Aj1pj2PA7y/6m1DS00A9za9uNBq7iqJYBuoGdRdFsazRaOzKSqye1rTbaa/tlbYrqXQP2X4FIA9/J1l39xrC0v7+w5IeB8XkwS1lWe6TGJAYKMty31tfO4qSHl/a3384I3CDpI+kzC4lnRfrue6GytEjR8oQwlY73gC0L4qlth/q0M1/LYWtR48cKQF6enrC6dOnVwGLEpnxnp7en4+O1i/tszzGOCTpPmB7ahb57QUwBWyXdF+McWg6MScmuoA8OX8xOlpvXGz422XYTsB/SnpA0h7bX5R0WzI9HUL4qe2XbI+dk3xl+V7gxoztD5jRI+YK/zkEEokx2/uB/RdzIfUtueqVN04cXwF8G3iHY3z9Urw/j8ClyhsnjrcS2Vv/J/8NLxT+/zqBTkcxU/cfEkyEAu3kmjAAAAAASUVORK5CYII=");}.bk-root .bk-tool-icon-box-edit{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gEMEg4QfHjM1QAAAGRJREFUWMNjXLhsJcNAAiaGAQYsDAwM/+lsJ+OgCwGsLqMB+D8o08CoA0YdMOqAUQewDFQdMBoFIyoN/B/U7YFRB7DQIc7xyo9GwbBMA4xDqhxgISH1klXbDYk0QOseEeOgDgEAIS0JQleje6IAAAAASUVORK5CYII=");}.bk-root .bk-tool-icon-freehand-draw{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAADTElEQVRYCeWWTWwMYRjH/88721X1lZJIGxJxcEE4OOiBgzjXWh8TJKR76kWacOBGxdEJIdk4VChZI/phidRBHMRRIr7DSUiaSCRFRM3u88gz+o7Z6bBTdjmYZPf9eJ55fv/5zzvvDPC/H9QsA66Olo9Ga+/MdR+Ljm2/KQIULsz9FqItGdOfJKLhApLgVkiSCGODjWit7QpKWy+TNrFeXvzKVUT8NiTVaIgDcbiCFJ7GiT8WkARXAdYBK0Lbhi/CenArRNskuM7/tgNp4ArQ42dwjf3WY5gWTqC7O/NbNn2Xkfw/YwdSw/We14HP2IEZwX+y9cZ9SH0LmgFP7UCz4KkENBNeV0Cz4b8U8DfgKiDxMWwUXETqLvJpCQpXZfawbzS7t9v5pL19cHBwfja7YA0y/lyCM0+E5hv5+piZXwKYcF23as+37bTXsQVqgkL0p/34fHR7DcBtbetFsBmGDwMOJCggYG55yw7dMlk6DuC1Bdu2RsCU9TYWQq2IoGbsreZ5NzvEqfSBsIsIy8OTbcdgiRHeh4o8AFAEwDakbY2AaCCpH7V9aGhoUUUy3UyVbkPYFuYLDlUZH8XBpwxkK0Dbgxg5HcVi0ent7a0RULMIozaHBSMfF9b2SzdutFcFB2FkwMIJOG6qfteXOa1nHZ48tyefuwyfT9s6wtzZ3t7eZse2DR2I228TtHXzuWCx9g8MtK5cuHCZTH4tiHEOa4xFngvTyS8f35d6enomiCi4/foEXBkZaQuukChL4FYA2Whd7YcC4gEdW3CpdL3LtGAVCVYJywEyTpAuJKeMOKXZs/Bw947C50KhUFOG4cwz35cjWNBlHGeD53n3xsfHP/T19U1qciggar8Fa4I3PHobIotBWBtc2hSiChyZxVzM53Pv7FVH6Tp3uVy+g0r1ImD2GjIrQGYIxjnfuXTZGICS5k/bBwJoubwEFX4TLah9EXomJGMA3za+f9913Yl4TnzsDQ+vE6YTZOjHh4ngibstt1pzQwd04F0bPStEBpXqRoBeQ/AKghfBnOEKgS+Q7z91Xfdz/HGKg8Ox7z8iYD9z6wqTkZFgnvhMGP9VZ2or1XVkPM9z0mytSfVsHa1RLBZbLoyNzUnK+ydz3wC6I9x+lwbngwAAAABJRU5ErkJggg==");}.bk-root .bk-tool-icon-poly-draw{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gEMEjglo9eZgwAAAc5JREFUWMPt1zFrU1EUB/DfS4OmVTGDIChCP4BgnQXRxVHqIJUupp9AB8VBQcRBQUXIB9DWQoMRiXZzcnQSA34A7aAuHSJKkgo2LvfBrU3aJnlYkBy4vHcP557zP/9z3r33JdXa647N0kHSZd5Nn0rSxc8G3cXp85sMcnZZ8vge3osZ+l3vB8CWFA0iL14t79h210swAjACMAIwAjACkB90D/8/GchI9ve4nPwTBh5E9ws7OepzGWb9EddSn51Op9ZstadSg4VK1UKlKkmSDSMLALewiuNh/hVJq71Wxttmqz0dG88vPc+MgWP4grvYG3SLOBrZFFFrttqPe4HIDxh4GSei+98iSlusuYopXEAjBtEPA3tQwUpwluAbDm4TPJUz+BTW9l2Ce6G7L0X/Bw8D3T/7SKKIDzHg7QCcxjvcQAEtXAnrrg/RP0/DKPbqgcN4iVOR7gcO4dcQgRuoh7HSqwlP4n20m63jJu5n8MkWMYfP3UowhzdR8FU8w9iQwevBdyq3/27CMRzAE5yLuvsRLg+ZcR1nJ8YL81HWJUzGAPaFZwe/Q5MdyYDyNHgjzO90YyGHtVDncuiJchaHw8R4oREFV5qdiVmYLM3OgD9k5209/atmIAAAAABJRU5ErkJggg==");}.bk-root .bk-tool-icon-point-draw{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gEMEiERGWPELgAAA4RJREFUWMO1lr1uG1cQhb9ztdRSP7AF1QxgwKlcuZSqRC9gWUUUINWqTh5AnaFOnVPEteQmRuhCURqWsSqqc9IolREXdEvQBElxtdw7KURSFEVKu4w8wAKLxdw9Z+bMnRmZGXfZ29//II8th4WwGVNyIoQLYB5vxA9Caq04iUd9A+7ZlsNC2I7TdSd2hZXMJKlnTqp9jtl/GBaqoyQ0noFKpUIzBicYYc+DEFpxkglc4oVJa5gvDn8v1xV2irG3FM4NSVwjUKlUaMcpJhCGmSEJQ6QGD8M5WnHCd8+f3QCXpPLx8WNwv0j6Bm9FMK7FJ3WBE+R/2t7c/GBmFvSBrzRTCsyTDjXrxUgEMtpxynJYmJoBJ4VAybwVARgvL7Oik0okCodnKpVKX7P0leiVMb0VvbJT+upznK4vh0GIeQwwQStJkHQD3MwsCALTJRG7Qrdrj5m/djgYaIa0hlkRdJk26XEgC9txurccBtVW3IudBImmZuACUP+ZlIDBt9FKcubYNTcAH/X0RYM1E7utJPlqe+uZzPxUcEkiSS4sTT95n15Mud0xWC0o2PAWOCdK3KYZlFxfM+tHOcnMzNr1es18ug+cgsVjP4yBU/Ppfrter1m/+l0+zYygML1xRVHU7TSb1cSzBzoBzszsH+AMdJJ49jrNZjWKou6wBnwOzcyndBpNbuueURR1Dw8Pq35p9cc5p/Dy9Dypt7jXrtdGwQECS9NPhr6Gq6txUzNigE6zydLK6lTw12/KT4FGFEUfJX2YJNONq5tVs4ODA7sD/DnwJ/BoADZuE3tHFs12dna6d4C/BI6AlbyzI8ii2TTw12/KK33gb2cdXsNZoAntbZC2SeO4c9592k/5eNQbiwvFd1kJuFGwLJr1wSPg/SwpvyFBHufOeXcFeAlE97U/uCxOY+P3b+Bn4B3Q+L8EdJfD4a+/AbC4UBzPxiPg3wlHZquB28Cn2IuR9x3gr3uV4DbwfvSDOvi4uFA8BDZmIRHkjHpS9Ht9iRqd8+5G3g05mAGcQbsdiX5QJ428G7Kygo8XYdb1/K4NWVmjzkNge2sz84bs+ELmpDDLtqWsNZBXgvmw8CTtpWVMT7x5YWBjLARnwZfKQNYN2U2LPvrh+5nBt7c2M2/It9bArCTKR8eZN+SJ13AScPnoODeRdqNenH+wul5w2gUr2WUjMFAt8bZ/0axX/wNnv4H8vTFb1QAAAABJRU5ErkJggg==");}.bk-root .bk-tool-icon-poly-edit{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4gELFi46qJmxxAAABV9JREFUWMOdl19vFFUYxn9n9u9sCyylUIzWUoMQBAWCMdEEIt6xIRQSLIEKtvHe6AcA4yeQb7CAUNJy0daLeomJN8SEULAC2kBBapBKoLvbmdl/c14vdmY7u91tF95kknPOnHmf95znPc97Ro2OTeBbdjFDT3c32ZxVHUOE9kSMB0/m6ExuoJn1H+ur6Y+OTfD50SMN5168OgrAlyf7CfuD+z7+iDs3p8hkLUQ0iFQ/yFl5Nm/qonfHVva+s32Zw9GxCYILsZ08tpNfBhbs+1YN4OH9+7huGdECSBVfqUosbsllfmauBqiR+cCNwOr7AEo8pPHJnymXykhg5fUWjoQpl0vVvhZhbSzGoUOHqgBlt6B6uruj2Zy1E9jo0fhfeyL2x4Mnc8VErK0KUEOB64JSyptfG4RSytsJjUJVxw2lsFy3urL9nx1Qd25ObctkrVMi+jQivd7U2ZyV/3Hzpq7h3h1b/7p9Y0o8v8rwAbTWrGpSocN/FGDlbAI0Rl23PCBan0Ok158H9Ipwzi25A/Mzc9Gl/BYx/E4kYqC1NKRARNAaDCNUM27Z+Zr+ouXs0q4+LSLBHPYCFkTkC6uU39kwCdsS7WRKmaYUiAhdnZ3MPX2K4+QjQI+C94A93rMzm8ltMwyDeDzWjMZeEb2pYQDdW3vITU2jtUZ5QThOPgm8C7wP7J15OPsBsB3oWpGnVWisCeDS1VHj4vBI92+/3tgB7Ab2AruAXiDBK5oIOkhtkEYRNRuJhObrd8Dl9ewf4D5wG7hVLpen29vb5wzD+BrkbBMaL3d1dk5nsrnlFDTTFWAWmAZueWD3gCemGde2k2fw1Al1YXhEvjozoO49eczdqekrWmsc2zlrmvEKOGoW1GUjFLqSk2KpJrCLwyMCPAP+BO54QL8DM6YZX/ClsP9YnwKkXnIBP4jdIpJRpdJTCYdMwwi98KU0Hjc/dDILNyUcwTCWdOSMJ0TRmBktGRhLugu0xyLk7CIqVNm+0bGJptl1YXikD0grpY4Rjc4a8Fbgdab/6OGbAJeCUuyJnnHmZH9pbSyGuBXV8NUwlUpR1EWyixmSyTWEwqGlJ2Swbo2JXbAAfgDGgGQA9I1A9t1tlq0AxrXxn0ilUpw4fhQqYkH/sT41OTnJJwf2s6FjI5mshdYa7bqVR2uezr9MJmJt14FvGrh/O9D+e6UkM/xyCuCqEKCYnJyUTKFQrZDHjxzGshwWLQcRsOz8Hi85P23id0ug/XilAMLBmm4tPGdoaKjSH5+oAGrhwvBI9SjZTn4QSK9yenoD7dlrExPoJlXW8G8ytpNHxRKk02lGxsdRKFwXLNvx5yY94HQLGhGk4LFCYQSqaE0AwWM1eOoEbR0dKBSW7bC4mKuffxs4D/wCLKwQQPAUzIkslfp6cVomROWSolh0GjldAM4nzDi2k9/i5UAzC9aKfwNJ3zgJg9YEvN6+C7SHgKm69+sD7RfNnKTTaZRPQfAut4oFV//IS7gkcB34VlVo8kGzphlfB+DU+TfNGBpZtRastvrvARJmfMF28ge9sc2B9/PNnCilMIDwK6y8/ow/Ai4kvILTljAXvDvEvrqKSUs60KolzPjBxspavQD2tKqCAGF/Ba+xE/Wbilu54wZV8NEKF5fXzQHl/bh4hUsE0WAXSlDMYcQSrQXgCmsTseXHsJkNnjqBFGwKJaHsKlxtUHYVhbLCzr1kaOA4bcn1y1Swmb+iLpJKpVrfgdpfsiVVCYcgluwgnU7jEgJ4s5UkLFtWYyHyEg0/N1q1tmQH+YXnAMFr97Nmv3p+0QsHQRsF8qpBOE5+rb9Nkaj50tVQKjqh4OU3GNL/1/So3vuUgbAAAAAASUVORK5CYII=");}.bk-root .bk-tool-icon-line-edit{background-image:url("data:image/png;base64,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");}.bk-root .bk-menu-icon{width:28px;height:28px;background-size:60%;background-color:transparent;background-repeat:no-repeat;background-position:center center;}.bk-root .bk-context-menu{position:absolute;display:inline-flex;flex-wrap:nowrap;user-select:none;-ms-user-select:none;-moz-user-select:none;-webkit-user-select:none;width:auto;height:auto;z-index:100;cursor:pointer;font-size:12px;background-color:#fff;border:1px solid #ccc;border-radius:4px;box-shadow:0 6px 12px rgba(0, 0, 0, 0.175);}.bk-root .bk-context-menu.bk-horizontal{flex-direction:row;}.bk-root .bk-context-menu.bk-vertical{flex-direction:column;}.bk-root .bk-context-menu > .bk-divider{cursor:default;overflow:hidden;background-color:#e5e5e5;}.bk-root .bk-context-menu.bk-horizontal > .bk-divider{width:1px;margin:5px 0;}.bk-root .bk-context-menu.bk-vertical > .bk-divider{height:1px;margin:0 5px;}.bk-root .bk-context-menu > :not(.bk-divider){border:1px solid transparent;}.bk-root .bk-context-menu > :not(.bk-divider).bk-active{border-color:#26aae1;}.bk-root .bk-context-menu > :not(.bk-divider):hover{background-color:#f9f9f9;}.bk-root .bk-context-menu > :not(.bk-divider):focus,.bk-root .bk-context-menu > :not(.bk-divider):focus-visible{outline:1px dotted #26aae1;outline-offset:-1px;}.bk-root .bk-context-menu > :not(.bk-divider)::-moz-focus-inner{border:0;}.bk-root .bk-context-menu.bk-horizontal > :not(.bk-divider):first-child{border-top-left-radius:4px;border-bottom-left-radius:4px;}.bk-root .bk-context-menu.bk-horizontal > :not(.bk-divider):last-child{border-top-right-radius:4px;border-bottom-right-radius:4px;}.bk-root .bk-context-menu.bk-vertical > :not(.bk-divider):first-child{border-top-left-radius:4px;border-top-right-radius:4px;}.bk-root .bk-context-menu.bk-vertical > :not(.bk-divider):last-child{border-bottom-left-radius:4px;border-bottom-right-radius:4px;}.bk-root .bk-menu{position:absolute;left:0;width:100%;z-index:100;cursor:pointer;font-size:12px;background-color:#fff;border:1px solid #ccc;border-radius:4px;box-shadow:0 6px 12px rgba(0, 0, 0, 0.175);}.bk-root .bk-menu.bk-above{bottom:100%;}.bk-root .bk-menu.bk-below{top:100%;}.bk-root .bk-menu > .bk-divider{height:1px;margin:7.5px 0;overflow:hidden;background-color:#e5e5e5;}.bk-root .bk-menu > :not(.bk-divider){padding:6px 12px;}.bk-root .bk-menu > :not(.bk-divider):hover,.bk-root .bk-menu > :not(.bk-divider).bk-active{background-color:#e6e6e6;}.bk-root .bk-caret{display:inline-block;vertical-align:middle;width:0;height:0;margin:0 5px;}.bk-root .bk-caret.bk-down{border-top:4px solid;}.bk-root .bk-caret.bk-up{border-bottom:4px solid;}.bk-root .bk-caret.bk-down,.bk-root .bk-caret.bk-up{border-right:4px solid transparent;border-left:4px solid transparent;}.bk-root .bk-caret.bk-left{border-right:4px solid;}.bk-root .bk-caret.bk-right{border-left:4px solid;}.bk-root .bk-caret.bk-left,.bk-root .bk-caret.bk-right{border-top:4px solid transparent;border-bottom:4px solid transparent;}.bk-root{}.bk-root .bk-tooltip{font-weight:300;font-size:12px;position:absolute;padding:5px;border:1px solid #e5e5e5;color:#2f2f2f;background-color:white;pointer-events:none;opacity:0.95;z-index:100;}.bk-root .bk-tooltip > div:not(:first-child){margin-top:5px;border-top:#e5e5e5 1px dashed;}.bk-root .bk-tooltip.bk-left.bk-tooltip-arrow::before{position:absolute;margin:-7px 0 0 0;top:50%;width:0;height:0;border-style:solid;border-width:7px 0 7px 0;border-color:transparent;content:" ";display:block;left:-10px;border-right-width:10px;border-right-color:#909599;}.bk-root .bk-tooltip.bk-left::before{left:-10px;border-right-width:10px;border-right-color:#909599;}.bk-root .bk-tooltip.bk-right.bk-tooltip-arrow::after{position:absolute;margin:-7px 0 0 0;top:50%;width:0;height:0;border-style:solid;border-width:7px 0 7px 0;border-color:transparent;content:" ";display:block;right:-10px;border-left-width:10px;border-left-color:#909599;}.bk-root .bk-tooltip.bk-right::after{right:-10px;border-left-width:10px;border-left-color:#909599;}.bk-root .bk-tooltip.bk-above::before{position:absolute;margin:0 0 0 -7px;left:50%;width:0;height:0;border-style:solid;border-width:0 7px 0 7px;border-color:transparent;content:" ";display:block;top:-10px;border-bottom-width:10px;border-bottom-color:#909599;}.bk-root .bk-tooltip.bk-below::after{position:absolute;margin:0 0 0 -7px;left:50%;width:0;height:0;border-style:solid;border-width:0 7px 0 7px;border-color:transparent;content:" ";display:block;bottom:-10px;border-top-width:10px;border-top-color:#909599;}.bk-root .bk-tooltip-row-label{text-align:right;color:#26aae1;}.bk-root .bk-tooltip-row-value{color:default;}.bk-root .bk-tooltip-color-block{width:12px;height:12px;margin-left:5px;margin-right:5px;outline:#dddddd solid 1px;display:inline-block;}.bk-root .bk-clearfix:before,.bk-root .bk-clearfix:after{content:"";display:table;}.bk-root .bk-clearfix:after{clear:both;}.bk-root{}.bk-root .noUi-target,.bk-root .noUi-target *{-webkit-touch-callout:none;-webkit-tap-highlight-color:rgba(0, 0, 0, 0);-webkit-user-select:none;-ms-touch-action:none;touch-action:none;-ms-user-select:none;-moz-user-select:none;user-select:none;-moz-box-sizing:border-box;box-sizing:border-box;}.bk-root .noUi-target{position:relative;}.bk-root .noUi-base,.bk-root .noUi-connects{width:100%;height:100%;position:relative;z-index:1;}.bk-root .noUi-connects{overflow:hidden;z-index:0;}.bk-root .noUi-connect,.bk-root .noUi-origin{will-change:transform;position:absolute;z-index:1;top:0;right:0;-ms-transform-origin:0 0;-webkit-transform-origin:0 0;-webkit-transform-style:preserve-3d;transform-origin:0 0;transform-style:flat;}.bk-root .noUi-connect{height:100%;width:100%;}.bk-root .noUi-origin{height:10%;width:10%;}.bk-root .noUi-txt-dir-rtl.noUi-horizontal .noUi-origin{left:0;right:auto;}.bk-root .noUi-vertical .noUi-origin{width:0;}.bk-root .noUi-horizontal .noUi-origin{height:0;}.bk-root .noUi-handle{-webkit-backface-visibility:hidden;backface-visibility:hidden;position:absolute;}.bk-root .noUi-touch-area{height:100%;width:100%;}.bk-root .noUi-state-tap .noUi-connect,.bk-root .noUi-state-tap .noUi-origin{-webkit-transition:transform 0.3s;transition:transform 0.3s;}.bk-root .noUi-state-drag *{cursor:inherit !important;}.bk-root .noUi-horizontal{height:18px;}.bk-root .noUi-horizontal .noUi-handle{width:34px;height:28px;right:-17px;top:-6px;}.bk-root .noUi-vertical{width:18px;}.bk-root .noUi-vertical .noUi-handle{width:28px;height:34px;right:-6px;top:-17px;}.bk-root .noUi-txt-dir-rtl.noUi-horizontal .noUi-handle{left:-17px;right:auto;}.bk-root .noUi-target{background:#FAFAFA;border-radius:4px;border:1px solid #D3D3D3;box-shadow:inset 0 1px 1px #F0F0F0, 0 3px 6px -5px #BBB;}.bk-root .noUi-connects{border-radius:3px;}.bk-root .noUi-connect{background:#3FB8AF;}.bk-root .noUi-draggable{cursor:ew-resize;}.bk-root .noUi-vertical .noUi-draggable{cursor:ns-resize;}.bk-root .noUi-handle{border:1px solid #D9D9D9;border-radius:3px;background:#FFF;cursor:default;box-shadow:inset 0 0 1px #FFF, inset 0 1px 7px #EBEBEB, 0 3px 6px -3px #BBB;}.bk-root .noUi-active{box-shadow:inset 0 0 1px #FFF, inset 0 1px 7px #DDD, 0 3px 6px -3px #BBB;}.bk-root .noUi-handle:before,.bk-root .noUi-handle:after{content:"";display:block;position:absolute;height:14px;width:1px;background:#E8E7E6;left:14px;top:6px;}.bk-root .noUi-handle:after{left:17px;}.bk-root .noUi-vertical .noUi-handle:before,.bk-root .noUi-vertical .noUi-handle:after{width:14px;height:1px;left:6px;top:14px;}.bk-root .noUi-vertical .noUi-handle:after{top:17px;}.bk-root [disabled] .noUi-connect{background:#B8B8B8;}.bk-root [disabled].noUi-target,.bk-root [disabled].noUi-handle,.bk-root [disabled] .noUi-handle{cursor:not-allowed;}.bk-root .noUi-pips,.bk-root .noUi-pips *{-moz-box-sizing:border-box;box-sizing:border-box;}.bk-root .noUi-pips{position:absolute;color:#999;}.bk-root .noUi-value{position:absolute;white-space:nowrap;text-align:center;}.bk-root .noUi-value-sub{color:#ccc;font-size:10px;}.bk-root .noUi-marker{position:absolute;background:#CCC;}.bk-root .noUi-marker-sub{background:#AAA;}.bk-root .noUi-marker-large{background:#AAA;}.bk-root .noUi-pips-horizontal{padding:10px 0;height:80px;top:100%;left:0;width:100%;}.bk-root .noUi-value-horizontal{-webkit-transform:translate(-50%, 50%);transform:translate(-50%, 50%);}.bk-root .noUi-rtl .noUi-value-horizontal{-webkit-transform:translate(50%, 50%);transform:translate(50%, 50%);}.bk-root .noUi-marker-horizontal.noUi-marker{margin-left:-1px;width:2px;height:5px;}.bk-root .noUi-marker-horizontal.noUi-marker-sub{height:10px;}.bk-root .noUi-marker-horizontal.noUi-marker-large{height:15px;}.bk-root .noUi-pips-vertical{padding:0 10px;height:100%;top:0;left:100%;}.bk-root .noUi-value-vertical{-webkit-transform:translate(0, -50%);transform:translate(0, -50%);padding-left:25px;}.bk-root .noUi-rtl .noUi-value-vertical{-webkit-transform:translate(0, 50%);transform:translate(0, 50%);}.bk-root .noUi-marker-vertical.noUi-marker{width:5px;height:2px;margin-top:-1px;}.bk-root .noUi-marker-vertical.noUi-marker-sub{width:10px;}.bk-root .noUi-marker-vertical.noUi-marker-large{width:15px;}.bk-root .noUi-tooltip{display:block;position:absolute;border:1px solid #D9D9D9;border-radius:3px;background:#fff;color:#000;padding:5px;text-align:center;white-space:nowrap;}.bk-root .noUi-horizontal .noUi-tooltip{-webkit-transform:translate(-50%, 0);transform:translate(-50%, 0);left:50%;bottom:120%;}.bk-root .noUi-vertical .noUi-tooltip{-webkit-transform:translate(0, -50%);transform:translate(0, -50%);top:50%;right:120%;}.bk-root .noUi-horizontal .noUi-origin > .noUi-tooltip{-webkit-transform:translate(50%, 0);transform:translate(50%, 0);left:auto;bottom:10px;}.bk-root .noUi-vertical .noUi-origin > .noUi-tooltip{-webkit-transform:translate(0, -18px);transform:translate(0, -18px);top:auto;right:28px;}.bk-root .noUi-handle{cursor:grab;cursor:-webkit-grab;}.bk-root .noUi-handle.noUi-active{cursor:grabbing;cursor:-webkit-grabbing;}.bk-root .noUi-handle:after,.bk-root .noUi-handle:before{display:none;}.bk-root .noUi-tooltip{display:none;white-space:nowrap;}.bk-root .noUi-handle:hover .noUi-tooltip{display:block;}.bk-root .noUi-horizontal{width:100%;height:10px;}.bk-root .noUi-vertical{width:10px;height:100%;}.bk-root .noUi-horizontal .noUi-handle{width:14px;height:18px;right:-7px;top:-5px;}.bk-root .noUi-vertical .noUi-handle{width:18px;height:14px;right:-5px;top:-7px;}.bk-root .noUi-target.noUi-horizontal{margin:5px 0px;}.bk-root .noUi-target.noUi-vertical{margin:0px 5px;}.bk-root .bk-slider-title{white-space:nowrap;}.bk-root .bk-slider-value{font-weight:600;}
PO.DAAC ECCO SSH – EarthData Cloud Cookbook
Many of NASA’s current and legacy data collections are archive in netCDF4 format. By itself, netCDF4 are not cloud optimized and reading these files can take as long from a personal/local work environment as it takes to read the data from a working environment deployed in the cloud. Using Kerchunk
, we can treat these files as cloud optimized assets by creating metadata json file describing existing netCDF4 files, their chunks, and where to access them. The json reference files can be read in using Zarr
and Xarray
for efficient reads and fast processing.
Requirements
1. AWS instance running in us-west-2
NASA Earthdata Cloud data in S3 can be directly accessed via temporary credentials; this access is limited to requests made within the US West (Oregon) (code: us-west-2) AWS region.
2. Earthdata Login
An Earthdata Login account is required to access data, as well as discover restricted data, from the NASA Earthdata system. Thus, to access NASA data, you need Earthdata Login. Please visit https://urs.earthdata.nasa.gov to register and manage your Earthdata Login account. This account is free to create and only takes a moment to set up.
3. netrc File
You will need a netrc file containing your NASA Earthdata Login credentials in order to execute the notebooks. A netrc file can be created manually within text editor and saved to your home directory. For additional information see: Authentication for NASA Earthdata .
Import required packages
import requests
import xarray as xr
import ujson
import s3fs
import fsspec
from tqdm import tqdm
from glob import glob
import os
import pathlib
import hvplot.xarray
from kerchunk.hdf import SingleHdf5ToZarr
from kerchunk.combine import MultiZarrToZarr
# The xarray produced from the reference file throws a SerializationWarning for each variable. Will need to explore why
import warnings
warnings.simplefilter("ignore" )
Create Dask client to process the output json file in parallel
Generating the Kerchunk
reference file can take some time depending on the internal structure of the data. Dask
allows us to execute the reference file generation process in parallel, thus speeding up the overall process.
import dask
from dask.distributed import Client
client = Client(n_workers= 4 )
client
2022-05-11 15:27:29,674 - distributed.diskutils - INFO - Found stale lock file and directory '/home/jovyan/earthdata-cloud-cookbook/examples/PODAAC/dask-worker-space/worker-mezhdsy7', purging
/srv/conda/envs/notebook/lib/python3.9/contextlib.py:126: UserWarning: Creating scratch directories is taking a surprisingly long time. This is often due to running workers on a network file system. Consider specifying a local-directory to point workers to write scratch data to a local disk.
next(self.gen)
Client
Client-ddf55e52-d13e-11ec-818c-b6609e8b92a4
Cluster Info
LocalCluster
a24e60d3
Scheduler Info
Scheduler
Scheduler-8e045442-a409-4c3b-8c8c-a95470883931
Workers
Worker: 0
Comm: tcp://127.0.0.1:34235
Total threads: 1
Dashboard: http://127.0.0.1:42845/status
Memory: 3.80 GiB
Nanny: tcp://127.0.0.1:37927
Local directory: /home/jovyan/earthdata-cloud-cookbook/examples/PODAAC/dask-worker-space/worker-869qv5xb
Worker: 1
Comm: tcp://127.0.0.1:40997
Total threads: 1
Dashboard: http://127.0.0.1:41189/status
Memory: 3.80 GiB
Nanny: tcp://127.0.0.1:35257
Local directory: /home/jovyan/earthdata-cloud-cookbook/examples/PODAAC/dask-worker-space/worker-3mo0d80c
Worker: 2
Comm: tcp://127.0.0.1:46429
Total threads: 1
Dashboard: http://127.0.0.1:42211/status
Memory: 3.80 GiB
Nanny: tcp://127.0.0.1:34287
Local directory: /home/jovyan/earthdata-cloud-cookbook/examples/PODAAC/dask-worker-space/worker-o2fvmao4
Worker: 3
Comm: tcp://127.0.0.1:41615
Total threads: 1
Dashboard: http://127.0.0.1:41507/status
Memory: 3.80 GiB
Nanny: tcp://127.0.0.1:43053
Local directory: /home/jovyan/earthdata-cloud-cookbook/examples/PODAAC/dask-worker-space/worker-9u77hywd
Get temporary S3 credentials
Temporary S3 credentials need to be passed to AWS. Note, these credentials must be refreshed after 1 hour .
s3_cred_endpoint = {
'podaac' :'https://archive.podaac.earthdata.nasa.gov/s3credentials' ,
'lpdaac' :'https://data.lpdaac.earthdatacloud.nasa.gov/s3credentials' ,
'ornldaac' :'https://data.ornldaac.earthdata.nasa.gov/s3credentials' ,
'gesdisc' :'https://data.gesdisc.earthdata.nasa.gov/s3credentials'
}
def get_temp_creds():
temp_creds_url = s3_cred_endpoint['podaac' ]
return requests.get(temp_creds_url).json()
temp_creds_req = get_temp_creds()
Direct Access a single netCDF4 file
Pass temporary credentials to our filesystem object to access the S3 assets
fs = s3fs.S3FileSystem(
anon= False ,
key= temp_creds_req['accessKeyId' ],
secret= temp_creds_req['secretAccessKey' ],
token= temp_creds_req['sessionToken' ]
)
url = 's3://podaac-ops-cumulus-protected/ECCO_L4_SSH_05DEG_MONTHLY_V4R4/SEA_SURFACE_HEIGHT_mon_mean_2015-01_ECCO_V4r4_latlon_0p50deg.nc'
s3_file_obj = fs.open (url, mode= 'rb' )
Time how long it takes to directly access a cloud asset for comparisons later.
%% time
xr_ds = xr.open_dataset(s3_file_obj, chunks= 'auto' , engine= 'h5netcdf' )
xr_ds
CPU times: user 228 ms, sys: 8.51 ms, total: 237 ms
Wall time: 272 ms
<xarray.Dataset>
Dimensions: (time: 1, latitude: 360, longitude: 720, nv: 2)
Coordinates:
* time (time) datetime64[ns] 2015-01-16T12:00:00
* latitude (latitude) float32 -89.75 -89.25 -88.75 ... 89.25 89.75
* longitude (longitude) float32 -179.8 -179.2 -178.8 ... 179.2 179.8
time_bnds (time, nv) datetime64[ns] dask.array<chunksize=(1, 2), meta=np.ndarray>
latitude_bnds (latitude, nv) float32 dask.array<chunksize=(360, 2), meta=np.ndarray>
longitude_bnds (longitude, nv) float32 dask.array<chunksize=(720, 2), meta=np.ndarray>
Dimensions without coordinates: nv
Data variables:
SSH (time, latitude, longitude) float32 dask.array<chunksize=(1, 360, 720), meta=np.ndarray>
SSHIBC (time, latitude, longitude) float32 dask.array<chunksize=(1, 360, 720), meta=np.ndarray>
SSHNOIBC (time, latitude, longitude) float32 dask.array<chunksize=(1, 360, 720), meta=np.ndarray>
Attributes: (12/57)
acknowledgement: This research was carried out by the Jet Pr...
author: Ian Fenty and Ou Wang
cdm_data_type: Grid
comment: Fields provided on a regular lat-lon grid. ...
Conventions: CF-1.8, ACDD-1.3
coordinates_comment: Note: the global 'coordinates' attribute de...
... ...
time_coverage_duration: P1M
time_coverage_end: 2015-02-01T00:00:00
time_coverage_resolution: P1M
time_coverage_start: 2015-01-01T00:00:00
title: ECCO Sea Surface Height - Monthly Mean 0.5 ...
uuid: 088d03b8-4158-11eb-876b-0cc47a3f47f1 Dimensions: time : 1latitude : 360longitude : 720nv : 2
Coordinates: (6)
time
(time)
datetime64[ns]
2015-01-16T12:00:00
axis : T bounds : time_bnds coverage_content_type : coordinate long_name : center time of averaging period standard_name : time array(['2015-01-16T12:00:00.000000000'], dtype='datetime64[ns]') latitude
(latitude)
float32
-89.75 -89.25 ... 89.25 89.75
axis : Y bounds : latitude_bnds comment : uniform grid spacing from -89.75 to 89.75 by 0.5 coverage_content_type : coordinate long_name : latitude at grid cell center standard_name : latitude units : degrees_north array([-89.75, -89.25, -88.75, ..., 88.75, 89.25, 89.75], dtype=float32) longitude
(longitude)
float32
-179.8 -179.2 ... 179.2 179.8
axis : X bounds : longitude_bnds comment : uniform grid spacing from -179.75 to 179.75 by 0.5 coverage_content_type : coordinate long_name : longitude at grid cell center standard_name : longitude units : degrees_east array([-179.75, -179.25, -178.75, ..., 178.75, 179.25, 179.75],
dtype=float32) time_bnds
(time, nv)
datetime64[ns]
dask.array<chunksize=(1, 2), meta=np.ndarray>
comment : Start and end times of averaging period. coverage_content_type : coordinate long_name : time bounds of averaging period
Bytes
16 B
16 B
Shape
(1, 2)
(1, 2)
Count
2 Tasks
1 Chunks
Type
datetime64[ns]
numpy.ndarray
2 1
latitude_bnds
(latitude, nv)
float32
dask.array<chunksize=(360, 2), meta=np.ndarray>
coverage_content_type : coordinate long_name : latitude bounds grid cells
Bytes
2.81 kiB
2.81 kiB
Shape
(360, 2)
(360, 2)
Count
2 Tasks
1 Chunks
Type
float32
numpy.ndarray
2 360
longitude_bnds
(longitude, nv)
float32
dask.array<chunksize=(720, 2), meta=np.ndarray>
coverage_content_type : coordinate long_name : longitude bounds grid cells
Bytes
5.62 kiB
5.62 kiB
Shape
(720, 2)
(720, 2)
Count
2 Tasks
1 Chunks
Type
float32
numpy.ndarray
2 720
Data variables: (3)
SSH
(time, latitude, longitude)
float32
dask.array<chunksize=(1, 360, 720), meta=np.ndarray>
coverage_content_type : modelResult long_name : Dynamic sea surface height anomaly standard_name : sea_surface_height_above_geoid units : m comment : Dynamic sea surface height anomaly above the geoid, suitable for comparisons with altimetry sea surface height data products that apply the inverse barometer (IB) correction. Note: SSH is calculated by correcting model sea level anomaly ETAN for three effects: a) global mean steric sea level changes related to density changes in the Boussinesq volume-conserving model (Greatbatch correction, see sterGloH), b) the inverted barometer (IB) effect (see SSHIBC) and c) sea level displacement due to sea-ice and snow pressure loading (see sIceLoad). SSH can be compared with the similarly-named SSH variable in previous ECCO products that did not include atmospheric pressure loading (e.g., Version 4 Release 3). Use SSHNOIBC for comparisons with altimetry data products that do NOT apply the IB correction. valid_min : -1.8805772066116333 valid_max : 1.4207719564437866
Bytes
0.99 MiB
0.99 MiB
Shape
(1, 360, 720)
(1, 360, 720)
Count
2 Tasks
1 Chunks
Type
float32
numpy.ndarray
720 360 1
SSHIBC
(time, latitude, longitude)
float32
dask.array<chunksize=(1, 360, 720), meta=np.ndarray>
coverage_content_type : modelResult long_name : The inverted barometer (IB) correction to sea surface height due to atmospheric pressure loading units : m comment : Not an SSH itself, but a correction to model sea level anomaly (ETAN) required to account for the static part of sea surface displacement by atmosphere pressure loading: SSH = SSHNOIBC - SSHIBC. Note: Use SSH for model-data comparisons with altimetry data products that DO apply the IB correction and SSHNOIBC for comparisons with altimetry data products that do NOT apply the IB correction. valid_min : -0.30144819617271423 valid_max : 0.5245633721351624
Bytes
0.99 MiB
0.99 MiB
Shape
(1, 360, 720)
(1, 360, 720)
Count
2 Tasks
1 Chunks
Type
float32
numpy.ndarray
720 360 1
SSHNOIBC
(time, latitude, longitude)
float32
dask.array<chunksize=(1, 360, 720), meta=np.ndarray>
coverage_content_type : modelResult long_name : Sea surface height anomaly without the inverted barometer (IB) correction units : m comment : Sea surface height anomaly above the geoid without the inverse barometer (IB) correction, suitable for comparisons with altimetry sea surface height data products that do NOT apply the inverse barometer (IB) correction. Note: SSHNOIBC is calculated by correcting model sea level anomaly ETAN for two effects: a) global mean steric sea level changes related to density changes in the Boussinesq volume-conserving model (Greatbatch correction, see sterGloH), b) sea level displacement due to sea-ice and snow pressure loading (see sIceLoad). In ECCO Version 4 Release 4 the model is forced with atmospheric pressure loading. SSHNOIBC does not correct for the static part of the effect of atmosphere pressure loading on sea surface height (the so-called inverse barometer (IB) correction). Use SSH for comparisons with altimetry data products that DO apply the IB correction. valid_min : -1.6654272079467773 valid_max : 1.4550364017486572
Bytes
0.99 MiB
0.99 MiB
Shape
(1, 360, 720)
(1, 360, 720)
Count
2 Tasks
1 Chunks
Type
float32
numpy.ndarray
720 360 1
Attributes: (57)
acknowledgement : This research was carried out by the Jet Propulsion Laboratory, managed by the California Institute of Technology under a contract with the National Aeronautics and Space Administration. author : Ian Fenty and Ou Wang cdm_data_type : Grid comment : Fields provided on a regular lat-lon grid. They have been mapped to the regular lat-lon grid from the original ECCO lat-lon-cap 90 (llc90) native model grid. SSH (dynamic sea surface height) = SSHNOIBC (dynamic sea surface without the inverse barometer correction) - SSHIBC (inverse barometer correction). The inverted barometer correction accounts for variations in sea surface height due to atmospheric pressure variations. Conventions : CF-1.8, ACDD-1.3 coordinates_comment : Note: the global 'coordinates' attribute describes auxillary coordinates. creator_email : ecco-group@mit.edu creator_institution : NASA Jet Propulsion Laboratory (JPL) creator_name : ECCO Consortium creator_type : group creator_url : https://ecco-group.org date_created : 2020-12-18T09:39:51 date_issued : 2020-12-18T09:39:51 date_metadata_modified : 2021-03-15T22:07:49 date_modified : 2021-03-15T22:07:49 geospatial_bounds_crs : EPSG:4326 geospatial_lat_max : 90.0 geospatial_lat_min : -90.0 geospatial_lat_resolution : 0.5 geospatial_lat_units : degrees_north geospatial_lon_max : 180.0 geospatial_lon_min : -180.0 geospatial_lon_resolution : 0.5 geospatial_lon_units : degrees_east history : Inaugural release of an ECCO Central Estimate solution to PO.DAAC id : 10.5067/ECG5M-SSH44 institution : NASA Jet Propulsion Laboratory (JPL) instrument_vocabulary : GCMD instrument keywords keywords : EARTH SCIENCE > OCEANS > SEA SURFACE TOPOGRAPHY > SEA SURFACE HEIGHT, EARTH SCIENCE SERVICES > MODELS > EARTH SCIENCE REANALYSES/ASSIMILATION MODELS keywords_vocabulary : NASA Global Change Master Directory (GCMD) Science Keywords license : Public Domain metadata_link : https://cmr.earthdata.nasa.gov/search/collections.umm_json?ShortName=ECCO_L4_SSH_05DEG_MONTHLY_V4R4 naming_authority : gov.nasa.jpl platform : ERS-1/2, TOPEX/Poseidon, Geosat Follow-On (GFO), ENVISAT, Jason-1, Jason-2, CryoSat-2, SARAL/AltiKa, Jason-3, AVHRR, Aquarius, SSM/I, SSMIS, GRACE, DTU17MDT, Argo, WOCE, GO-SHIP, MEOP, Ice Tethered Profilers (ITP) platform_vocabulary : GCMD platform keywords processing_level : L4 product_name : SEA_SURFACE_HEIGHT_mon_mean_2015-01_ECCO_V4r4_latlon_0p50deg.nc product_time_coverage_end : 2018-01-01T00:00:00 product_time_coverage_start : 1992-01-01T12:00:00 product_version : Version 4, Release 4 program : NASA Physical Oceanography, Cryosphere, Modeling, Analysis, and Prediction (MAP) project : Estimating the Circulation and Climate of the Ocean (ECCO) publisher_email : podaac@podaac.jpl.nasa.gov publisher_institution : PO.DAAC publisher_name : Physical Oceanography Distributed Active Archive Center (PO.DAAC) publisher_type : institution publisher_url : https://podaac.jpl.nasa.gov references : ECCO Consortium, Fukumori, I., Wang, O., Fenty, I., Forget, G., Heimbach, P., & Ponte, R. M. 2020. Synopsis of the ECCO Central Production Global Ocean and Sea-Ice State Estimate (Version 4 Release 4). doi:10.5281/zenodo.3765928 source : The ECCO V4r4 state estimate was produced by fitting a free-running solution of the MITgcm (checkpoint 66g) to satellite and in situ observational data in a least squares sense using the adjoint method standard_name_vocabulary : NetCDF Climate and Forecast (CF) Metadata Convention summary : This dataset provides monthly-averaged dynamic sea surface height interpolated to a regular 0.5-degree grid from the ECCO Version 4 Release 4 (V4r4) ocean and sea-ice state estimate. Estimating the Circulation and Climate of the Ocean (ECCO) state estimates are dynamically and kinematically-consistent reconstructions of the three-dimensional, time-evolving ocean, sea-ice, and surface atmospheric states. ECCO V4r4 is a free-running solution of a global, nominally 1-degree configuration of the MIT general circulation model (MITgcm) that has been fit to observations in a least-squares sense. Observational data constraints used in V4r4 include sea surface height (SSH) from satellite altimeters [ERS-1/2, TOPEX/Poseidon, GFO, ENVISAT, Jason-1,2,3, CryoSat-2, and SARAL/AltiKa]; sea surface temperature (SST) from satellite radiometers [AVHRR], sea surface salinity (SSS) from the Aquarius satellite radiometer/scatterometer, ocean bottom pressure (OBP) from the GRACE satellite gravimeter; sea-ice concentration from satellite radiometers [SSM/I and SSMIS], and in-situ ocean temperature and salinity measured with conductivity-temperature-depth (CTD) sensors and expendable bathythermographs (XBTs) from several programs [e.g., WOCE, GO-SHIP, Argo, and others] and platforms [e.g., research vessels, gliders, moorings, ice-tethered profilers, and instrumented pinnipeds]. V4r4 covers the period 1992-01-01T12:00:00 to 2018-01-01T00:00:00. time_coverage_duration : P1M time_coverage_end : 2015-02-01T00:00:00 time_coverage_resolution : P1M time_coverage_start : 2015-01-01T00:00:00 title : ECCO Sea Surface Height - Monthly Mean 0.5 Degree (Version 4 Release 4) uuid : 088d03b8-4158-11eb-876b-0cc47a3f47f1
Specify a list of S3 URLs
Data Collection: ECCO_L4_SSH_05DEG_MONTHLY_V4R4
Time Range: 2015
urls = ['s3://podaac-ops-cumulus-protected/ECCO_L4_SSH_05DEG_MONTHLY_V4R4/SEA_SURFACE_HEIGHT_mon_mean_2014-12_ECCO_V4r4_latlon_0p50deg.nc' ,
's3://podaac-ops-cumulus-protected/ECCO_L4_SSH_05DEG_MONTHLY_V4R4/SEA_SURFACE_HEIGHT_mon_mean_2015-01_ECCO_V4r4_latlon_0p50deg.nc' ,
's3://podaac-ops-cumulus-protected/ECCO_L4_SSH_05DEG_MONTHLY_V4R4/SEA_SURFACE_HEIGHT_mon_mean_2015-02_ECCO_V4r4_latlon_0p50deg.nc' ,
's3://podaac-ops-cumulus-protected/ECCO_L4_SSH_05DEG_MONTHLY_V4R4/SEA_SURFACE_HEIGHT_mon_mean_2015-03_ECCO_V4r4_latlon_0p50deg.nc' ,
's3://podaac-ops-cumulus-protected/ECCO_L4_SSH_05DEG_MONTHLY_V4R4/SEA_SURFACE_HEIGHT_mon_mean_2015-04_ECCO_V4r4_latlon_0p50deg.nc' ,
's3://podaac-ops-cumulus-protected/ECCO_L4_SSH_05DEG_MONTHLY_V4R4/SEA_SURFACE_HEIGHT_mon_mean_2015-05_ECCO_V4r4_latlon_0p50deg.nc' ,
's3://podaac-ops-cumulus-protected/ECCO_L4_SSH_05DEG_MONTHLY_V4R4/SEA_SURFACE_HEIGHT_mon_mean_2015-06_ECCO_V4r4_latlon_0p50deg.nc' ,
's3://podaac-ops-cumulus-protected/ECCO_L4_SSH_05DEG_MONTHLY_V4R4/SEA_SURFACE_HEIGHT_mon_mean_2015-07_ECCO_V4r4_latlon_0p50deg.nc' ,
's3://podaac-ops-cumulus-protected/ECCO_L4_SSH_05DEG_MONTHLY_V4R4/SEA_SURFACE_HEIGHT_mon_mean_2015-08_ECCO_V4r4_latlon_0p50deg.nc' ,
's3://podaac-ops-cumulus-protected/ECCO_L4_SSH_05DEG_MONTHLY_V4R4/SEA_SURFACE_HEIGHT_mon_mean_2015-09_ECCO_V4r4_latlon_0p50deg.nc' ,
's3://podaac-ops-cumulus-protected/ECCO_L4_SSH_05DEG_MONTHLY_V4R4/SEA_SURFACE_HEIGHT_mon_mean_2015-10_ECCO_V4r4_latlon_0p50deg.nc' ,
's3://podaac-ops-cumulus-protected/ECCO_L4_SSH_05DEG_MONTHLY_V4R4/SEA_SURFACE_HEIGHT_mon_mean_2015-11_ECCO_V4r4_latlon_0p50deg.nc' ,
's3://podaac-ops-cumulus-protected/ECCO_L4_SSH_05DEG_MONTHLY_V4R4/SEA_SURFACE_HEIGHT_mon_mean_2015-12_ECCO_V4r4_latlon_0p50deg.nc' ]
Generate the Kerchunk
reference files.
Define a function to generate the Kerchunk
reference files. These files can take a little time to generate.
def gen_json(u):
so = dict (
mode= "rb" ,
anon= False ,
default_fill_cache= False ,
default_cache_type= "none"
)
with fs.open (u, ** so) as infile:
h5chunks = SingleHdf5ToZarr(infile, u, inline_threshold= 300 )
with open (f"jsons/ { u. split('/' )[- 1 ]} .json" , 'wb' ) as outf:
outf.write(ujson.dumps(h5chunks.translate()).encode())
Create output jsons directory if one does not exist.
pathlib.Path('./jsons/' ).mkdir(exist_ok= True )
Use the Dask Delayed function to create the Kerchunk
reference file for each URL from the list of URLs in parallel
%% time
reference_files = []
for url in urls:
ref = dask.delayed(gen_json)(url)
reference_files.append(ref)
reference_files_compute = dask.compute(* reference_files)
CPU times: user 195 ms, sys: 83.4 ms, total: 278 ms
Wall time: 1.38 s
fs_ref_list = fsspec.filesystem('file' )
reference_list = sorted ([x for x in fs_ref_list.ls('jsons' ) if '.json' in x])
reference_list
['/home/jovyan/earthdata-cloud-cookbook/examples/PODAAC/jsons/SEA_SURFACE_HEIGHT_mon_mean_2014-12_ECCO_V4r4_latlon_0p50deg.nc.json',
'/home/jovyan/earthdata-cloud-cookbook/examples/PODAAC/jsons/SEA_SURFACE_HEIGHT_mon_mean_2015-01_ECCO_V4r4_latlon_0p50deg.nc.json',
'/home/jovyan/earthdata-cloud-cookbook/examples/PODAAC/jsons/SEA_SURFACE_HEIGHT_mon_mean_2015-02_ECCO_V4r4_latlon_0p50deg.nc.json',
'/home/jovyan/earthdata-cloud-cookbook/examples/PODAAC/jsons/SEA_SURFACE_HEIGHT_mon_mean_2015-03_ECCO_V4r4_latlon_0p50deg.nc.json',
'/home/jovyan/earthdata-cloud-cookbook/examples/PODAAC/jsons/SEA_SURFACE_HEIGHT_mon_mean_2015-04_ECCO_V4r4_latlon_0p50deg.nc.json',
'/home/jovyan/earthdata-cloud-cookbook/examples/PODAAC/jsons/SEA_SURFACE_HEIGHT_mon_mean_2015-05_ECCO_V4r4_latlon_0p50deg.nc.json',
'/home/jovyan/earthdata-cloud-cookbook/examples/PODAAC/jsons/SEA_SURFACE_HEIGHT_mon_mean_2015-06_ECCO_V4r4_latlon_0p50deg.nc.json',
'/home/jovyan/earthdata-cloud-cookbook/examples/PODAAC/jsons/SEA_SURFACE_HEIGHT_mon_mean_2015-07_ECCO_V4r4_latlon_0p50deg.nc.json',
'/home/jovyan/earthdata-cloud-cookbook/examples/PODAAC/jsons/SEA_SURFACE_HEIGHT_mon_mean_2015-08_ECCO_V4r4_latlon_0p50deg.nc.json',
'/home/jovyan/earthdata-cloud-cookbook/examples/PODAAC/jsons/SEA_SURFACE_HEIGHT_mon_mean_2015-09_ECCO_V4r4_latlon_0p50deg.nc.json',
'/home/jovyan/earthdata-cloud-cookbook/examples/PODAAC/jsons/SEA_SURFACE_HEIGHT_mon_mean_2015-10_ECCO_V4r4_latlon_0p50deg.nc.json',
'/home/jovyan/earthdata-cloud-cookbook/examples/PODAAC/jsons/SEA_SURFACE_HEIGHT_mon_mean_2015-11_ECCO_V4r4_latlon_0p50deg.nc.json',
'/home/jovyan/earthdata-cloud-cookbook/examples/PODAAC/jsons/SEA_SURFACE_HEIGHT_mon_mean_2015-12_ECCO_V4r4_latlon_0p50deg.nc.json']
Read single netCDF4 using Kerchunk
reference file
Open the first reference file to read into an xarray dataset
with open (reference_list[0 ]) as j:
reference = ujson.load(j)
Set configurations options
s_opts = {'skip_instance_cache' :True } #json
r_opts = {'anon' :False ,
'key' :temp_creds_req['accessKeyId' ],
'secret' :temp_creds_req['secretAccessKey' ],
'token' :temp_creds_req['sessionToken' ]} #ncfiles
fs_single = fsspec.filesystem("reference" ,
fo= reference,
ref_storage_args= s_opts,
remote_protocol= 's3' ,
remote_options= r_opts)
Read in a single reference object. We get a lot of SerializationWarnings
which are ignored here using the warning
package.
NOTE, the fill value
, data range
, min value
, and max value
may not match the source file . Will need to look into this more.
%% time
m = fs_single.get_mapper("" )
ds_single = xr.open_dataset(m, engine= "zarr" , backend_kwargs= {'consolidated' :False }, chunks= {})
ds_single
CPU times: user 56.3 ms, sys: 26 ms, total: 82.2 ms
Wall time: 221 ms
<xarray.Dataset>
Dimensions: (time: 1, latitude: 360, longitude: 720, nv: 2)
Coordinates:
* latitude (latitude) float32 -89.75 -89.25 -88.75 ... 89.25 89.75
latitude_bnds (latitude, nv) float32 dask.array<chunksize=(360, 2), meta=np.ndarray>
* longitude (longitude) float32 -179.8 -179.2 -178.8 ... 179.2 179.8
longitude_bnds (longitude, nv) float32 dask.array<chunksize=(720, 2), meta=np.ndarray>
* time (time) datetime64[ns] 2014-12-16T12:00:00
time_bnds (time, nv) datetime64[ns] dask.array<chunksize=(1, 2), meta=np.ndarray>
Dimensions without coordinates: nv
Data variables:
SSH (time, latitude, longitude) float32 dask.array<chunksize=(1, 360, 720), meta=np.ndarray>
SSHIBC (time, latitude, longitude) float32 dask.array<chunksize=(1, 360, 720), meta=np.ndarray>
SSHNOIBC (time, latitude, longitude) float32 dask.array<chunksize=(1, 360, 720), meta=np.ndarray>
Attributes: (12/57)
Conventions: CF-1.8, ACDD-1.3
acknowledgement: This research was carried out by the Jet Pr...
author: Ian Fenty and Ou Wang
cdm_data_type: Grid
comment: Fields provided on a regular lat-lon grid. ...
coordinates_comment: Note: the global 'coordinates' attribute de...
... ...
time_coverage_duration: P1M
time_coverage_end: 2015-01-01T00:00:00
time_coverage_resolution: P1M
time_coverage_start: 2014-12-01T00:00:00
title: ECCO Sea Surface Height - Monthly Mean 0.5 ...
uuid: 08a2fc68-4158-11eb-b498-0cc47a3f6943 Dimensions: time : 1latitude : 360longitude : 720nv : 2
Coordinates: (6)
latitude
(latitude)
float32
-89.75 -89.25 ... 89.25 89.75
axis : Y bounds : latitude_bnds comment : uniform grid spacing from -89.75 to 89.75 by 0.5 coverage_content_type : coordinate long_name : latitude at grid cell center standard_name : latitude units : degrees_north array([-89.75, -89.25, -88.75, ..., 88.75, 89.25, 89.75], dtype=float32) latitude_bnds
(latitude, nv)
float32
dask.array<chunksize=(360, 2), meta=np.ndarray>
coverage_content_type : coordinate long_name : latitude bounds grid cells
Bytes
2.81 kiB
2.81 kiB
Shape
(360, 2)
(360, 2)
Count
2 Tasks
1 Chunks
Type
float32
numpy.ndarray
2 360
longitude
(longitude)
float32
-179.8 -179.2 ... 179.2 179.8
axis : X bounds : longitude_bnds comment : uniform grid spacing from -179.75 to 179.75 by 0.5 coverage_content_type : coordinate long_name : longitude at grid cell center standard_name : longitude units : degrees_east array([-179.75, -179.25, -178.75, ..., 178.75, 179.25, 179.75],
dtype=float32) longitude_bnds
(longitude, nv)
float32
dask.array<chunksize=(720, 2), meta=np.ndarray>
coverage_content_type : coordinate long_name : longitude bounds grid cells
Bytes
5.62 kiB
5.62 kiB
Shape
(720, 2)
(720, 2)
Count
2 Tasks
1 Chunks
Type
float32
numpy.ndarray
2 720
time
(time)
datetime64[ns]
2014-12-16T12:00:00
axis : T bounds : time_bnds coverage_content_type : coordinate long_name : center time of averaging period standard_name : time array(['2014-12-16T12:00:00.000000000'], dtype='datetime64[ns]') time_bnds
(time, nv)
datetime64[ns]
dask.array<chunksize=(1, 2), meta=np.ndarray>
comment : Start and end times of averaging period. coverage_content_type : coordinate long_name : time bounds of averaging period
Bytes
16 B
16 B
Shape
(1, 2)
(1, 2)
Count
2 Tasks
1 Chunks
Type
datetime64[ns]
numpy.ndarray
2 1
Data variables: (3)
SSH
(time, latitude, longitude)
float32
dask.array<chunksize=(1, 360, 720), meta=np.ndarray>
comment : Dynamic sea surface height anomaly above the geoid, suitable for comparisons with altimetry sea surface height data products that apply the inverse barometer (IB) correction. Note: SSH is calculated by correcting model sea level anomaly ETAN for three effects: a) global mean steric sea level changes related to density changes in the Boussinesq volume-conserving model (Greatbatch correction, see sterGloH), b) the inverted barometer (IB) effect (see SSHIBC) and c) sea level displacement due to sea-ice and snow pressure loading (see sIceLoad). SSH can be compared with the similarly-named SSH variable in previous ECCO products that did not include atmospheric pressure loading (e.g., Version 4 Release 3). Use SSHNOIBC for comparisons with altimetry data products that do NOT apply the IB correction. coverage_content_type : modelResult long_name : Dynamic sea surface height anomaly standard_name : sea_surface_height_above_geoid units : m valid_max : 1.4207719564437866 valid_min : -1.8805772066116333
Bytes
0.99 MiB
0.99 MiB
Shape
(1, 360, 720)
(1, 360, 720)
Count
2 Tasks
1 Chunks
Type
float32
numpy.ndarray
720 360 1
SSHIBC
(time, latitude, longitude)
float32
dask.array<chunksize=(1, 360, 720), meta=np.ndarray>
comment : Not an SSH itself, but a correction to model sea level anomaly (ETAN) required to account for the static part of sea surface displacement by atmosphere pressure loading: SSH = SSHNOIBC - SSHIBC. Note: Use SSH for model-data comparisons with altimetry data products that DO apply the IB correction and SSHNOIBC for comparisons with altimetry data products that do NOT apply the IB correction. coverage_content_type : modelResult long_name : The inverted barometer (IB) correction to sea surface height due to atmospheric pressure loading units : m valid_max : 0.5245633721351624 valid_min : -0.30144819617271423
Bytes
0.99 MiB
0.99 MiB
Shape
(1, 360, 720)
(1, 360, 720)
Count
2 Tasks
1 Chunks
Type
float32
numpy.ndarray
720 360 1
SSHNOIBC
(time, latitude, longitude)
float32
dask.array<chunksize=(1, 360, 720), meta=np.ndarray>
comment : Sea surface height anomaly above the geoid without the inverse barometer (IB) correction, suitable for comparisons with altimetry sea surface height data products that do NOT apply the inverse barometer (IB) correction. Note: SSHNOIBC is calculated by correcting model sea level anomaly ETAN for two effects: a) global mean steric sea level changes related to density changes in the Boussinesq volume-conserving model (Greatbatch correction, see sterGloH), b) sea level displacement due to sea-ice and snow pressure loading (see sIceLoad). In ECCO Version 4 Release 4 the model is forced with atmospheric pressure loading. SSHNOIBC does not correct for the static part of the effect of atmosphere pressure loading on sea surface height (the so-called inverse barometer (IB) correction). Use SSH for comparisons with altimetry data products that DO apply the IB correction. coverage_content_type : modelResult long_name : Sea surface height anomaly without the inverted barometer (IB) correction units : m valid_max : 1.4550364017486572 valid_min : -1.6654272079467773
Bytes
0.99 MiB
0.99 MiB
Shape
(1, 360, 720)
(1, 360, 720)
Count
2 Tasks
1 Chunks
Type
float32
numpy.ndarray
720 360 1
Attributes: (57)
Conventions : CF-1.8, ACDD-1.3 acknowledgement : This research was carried out by the Jet Propulsion Laboratory, managed by the California Institute of Technology under a contract with the National Aeronautics and Space Administration. author : Ian Fenty and Ou Wang cdm_data_type : Grid comment : Fields provided on a regular lat-lon grid. They have been mapped to the regular lat-lon grid from the original ECCO lat-lon-cap 90 (llc90) native model grid. SSH (dynamic sea surface height) = SSHNOIBC (dynamic sea surface without the inverse barometer correction) - SSHIBC (inverse barometer correction). The inverted barometer correction accounts for variations in sea surface height due to atmospheric pressure variations. coordinates_comment : Note: the global 'coordinates' attribute describes auxillary coordinates. creator_email : ecco-group@mit.edu creator_institution : NASA Jet Propulsion Laboratory (JPL) creator_name : ECCO Consortium creator_type : group creator_url : https://ecco-group.org date_created : 2020-12-18T09:39:51 date_issued : 2020-12-18T09:39:51 date_metadata_modified : 2021-03-15T22:07:49 date_modified : 2021-03-15T22:07:49 geospatial_bounds_crs : EPSG:4326 geospatial_lat_max : 90.0 geospatial_lat_min : -90.0 geospatial_lat_resolution : 0.5 geospatial_lat_units : degrees_north geospatial_lon_max : 180.0 geospatial_lon_min : -180.0 geospatial_lon_resolution : 0.5 geospatial_lon_units : degrees_east history : Inaugural release of an ECCO Central Estimate solution to PO.DAAC id : 10.5067/ECG5M-SSH44 institution : NASA Jet Propulsion Laboratory (JPL) instrument_vocabulary : GCMD instrument keywords keywords : EARTH SCIENCE > OCEANS > SEA SURFACE TOPOGRAPHY > SEA SURFACE HEIGHT, EARTH SCIENCE SERVICES > MODELS > EARTH SCIENCE REANALYSES/ASSIMILATION MODELS keywords_vocabulary : NASA Global Change Master Directory (GCMD) Science Keywords license : Public Domain metadata_link : https://cmr.earthdata.nasa.gov/search/collections.umm_json?ShortName=ECCO_L4_SSH_05DEG_MONTHLY_V4R4 naming_authority : gov.nasa.jpl platform : ERS-1/2, TOPEX/Poseidon, Geosat Follow-On (GFO), ENVISAT, Jason-1, Jason-2, CryoSat-2, SARAL/AltiKa, Jason-3, AVHRR, Aquarius, SSM/I, SSMIS, GRACE, DTU17MDT, Argo, WOCE, GO-SHIP, MEOP, Ice Tethered Profilers (ITP) platform_vocabulary : GCMD platform keywords processing_level : L4 product_name : SEA_SURFACE_HEIGHT_mon_mean_2014-12_ECCO_V4r4_latlon_0p50deg.nc product_time_coverage_end : 2018-01-01T00:00:00 product_time_coverage_start : 1992-01-01T12:00:00 product_version : Version 4, Release 4 program : NASA Physical Oceanography, Cryosphere, Modeling, Analysis, and Prediction (MAP) project : Estimating the Circulation and Climate of the Ocean (ECCO) publisher_email : podaac@podaac.jpl.nasa.gov publisher_institution : PO.DAAC publisher_name : Physical Oceanography Distributed Active Archive Center (PO.DAAC) publisher_type : institution publisher_url : https://podaac.jpl.nasa.gov references : ECCO Consortium, Fukumori, I., Wang, O., Fenty, I., Forget, G., Heimbach, P., & Ponte, R. M. 2020. Synopsis of the ECCO Central Production Global Ocean and Sea-Ice State Estimate (Version 4 Release 4). doi:10.5281/zenodo.3765928 source : The ECCO V4r4 state estimate was produced by fitting a free-running solution of the MITgcm (checkpoint 66g) to satellite and in situ observational data in a least squares sense using the adjoint method standard_name_vocabulary : NetCDF Climate and Forecast (CF) Metadata Convention summary : This dataset provides monthly-averaged dynamic sea surface height interpolated to a regular 0.5-degree grid from the ECCO Version 4 Release 4 (V4r4) ocean and sea-ice state estimate. Estimating the Circulation and Climate of the Ocean (ECCO) state estimates are dynamically and kinematically-consistent reconstructions of the three-dimensional, time-evolving ocean, sea-ice, and surface atmospheric states. ECCO V4r4 is a free-running solution of a global, nominally 1-degree configuration of the MIT general circulation model (MITgcm) that has been fit to observations in a least-squares sense. Observational data constraints used in V4r4 include sea surface height (SSH) from satellite altimeters [ERS-1/2, TOPEX/Poseidon, GFO, ENVISAT, Jason-1,2,3, CryoSat-2, and SARAL/AltiKa]; sea surface temperature (SST) from satellite radiometers [AVHRR], sea surface salinity (SSS) from the Aquarius satellite radiometer/scatterometer, ocean bottom pressure (OBP) from the GRACE satellite gravimeter; sea-ice concentration from satellite radiometers [SSM/I and SSMIS], and in-situ ocean temperature and salinity measured with conductivity-temperature-depth (CTD) sensors and expendable bathythermographs (XBTs) from several programs [e.g., WOCE, GO-SHIP, Argo, and others] and platforms [e.g., research vessels, gliders, moorings, ice-tethered profilers, and instrumented pinnipeds]. V4r4 covers the period 1992-01-01T12:00:00 to 2018-01-01T00:00:00. time_coverage_duration : P1M time_coverage_end : 2015-01-01T00:00:00 time_coverage_resolution : P1M time_coverage_start : 2014-12-01T00:00:00 title : ECCO Sea Surface Height - Monthly Mean 0.5 Degree (Version 4 Release 4) uuid : 08a2fc68-4158-11eb-b498-0cc47a3f6943
Read multiple netCDF4 files using Kerchunk reference file
Combine the individual reference files into a single time series reference object
%% time
ds_k = []
for ref in reference_list:
s_opts = s_opts
r_opts = r_opts
fs = fsspec.filesystem("reference" ,
fo= ref,
ref_storage_args= s_opts,
remote_protocol= 's3' ,
remote_options= r_opts)
m = fs.get_mapper("" )
ds_k.append(xr.open_dataset(m, engine= "zarr" , backend_kwargs= {'consolidated' :False }, chunks= {}))
ds_multi = xr.concat(ds_k, dim= 'time' )
ds_multi
CPU times: user 735 ms, sys: 31.4 ms, total: 766 ms
Wall time: 3.57 s
<xarray.Dataset>
Dimensions: (time: 13, latitude: 360, longitude: 720, nv: 2)
Coordinates:
* latitude (latitude) float32 -89.75 -89.25 -88.75 ... 89.25 89.75
latitude_bnds (latitude, nv) float32 -90.0 -89.5 -89.5 ... 89.5 89.5 90.0
* longitude (longitude) float32 -179.8 -179.2 -178.8 ... 179.2 179.8
longitude_bnds (longitude, nv) float32 -180.0 -179.5 -179.5 ... 179.5 180.0
* time (time) datetime64[ns] 2014-12-16T12:00:00 ... 2015-12-16T...
time_bnds (time, nv) datetime64[ns] dask.array<chunksize=(1, 2), meta=np.ndarray>
Dimensions without coordinates: nv
Data variables:
SSH (time, latitude, longitude) float32 dask.array<chunksize=(1, 360, 720), meta=np.ndarray>
SSHIBC (time, latitude, longitude) float32 dask.array<chunksize=(1, 360, 720), meta=np.ndarray>
SSHNOIBC (time, latitude, longitude) float32 dask.array<chunksize=(1, 360, 720), meta=np.ndarray>
Attributes: (12/57)
Conventions: CF-1.8, ACDD-1.3
acknowledgement: This research was carried out by the Jet Pr...
author: Ian Fenty and Ou Wang
cdm_data_type: Grid
comment: Fields provided on a regular lat-lon grid. ...
coordinates_comment: Note: the global 'coordinates' attribute de...
... ...
time_coverage_duration: P1M
time_coverage_end: 2015-01-01T00:00:00
time_coverage_resolution: P1M
time_coverage_start: 2014-12-01T00:00:00
title: ECCO Sea Surface Height - Monthly Mean 0.5 ...
uuid: 08a2fc68-4158-11eb-b498-0cc47a3f6943 Dimensions: time : 13latitude : 360longitude : 720nv : 2
Coordinates: (6)
latitude
(latitude)
float32
-89.75 -89.25 ... 89.25 89.75
axis : Y bounds : latitude_bnds comment : uniform grid spacing from -89.75 to 89.75 by 0.5 coverage_content_type : coordinate long_name : latitude at grid cell center standard_name : latitude units : degrees_north array([-89.75, -89.25, -88.75, ..., 88.75, 89.25, 89.75], dtype=float32) latitude_bnds
(latitude, nv)
float32
-90.0 -89.5 -89.5 ... 89.5 90.0
coverage_content_type : coordinate long_name : latitude bounds grid cells array([[-90. , -89.5],
[-89.5, -89. ],
[-89. , -88.5],
[-88.5, -88. ],
[-88. , -87.5],
[-87.5, -87. ],
[-87. , -86.5],
[-86.5, -86. ],
[-86. , -85.5],
[-85.5, -85. ],
[-85. , -84.5],
[-84.5, -84. ],
[-84. , -83.5],
[-83.5, -83. ],
[-83. , -82.5],
[-82.5, -82. ],
[-82. , -81.5],
[-81.5, -81. ],
[-81. , -80.5],
[-80.5, -80. ],
...
[ 80. , 80.5],
[ 80.5, 81. ],
[ 81. , 81.5],
[ 81.5, 82. ],
[ 82. , 82.5],
[ 82.5, 83. ],
[ 83. , 83.5],
[ 83.5, 84. ],
[ 84. , 84.5],
[ 84.5, 85. ],
[ 85. , 85.5],
[ 85.5, 86. ],
[ 86. , 86.5],
[ 86.5, 87. ],
[ 87. , 87.5],
[ 87.5, 88. ],
[ 88. , 88.5],
[ 88.5, 89. ],
[ 89. , 89.5],
[ 89.5, 90. ]], dtype=float32) longitude
(longitude)
float32
-179.8 -179.2 ... 179.2 179.8
axis : X bounds : longitude_bnds comment : uniform grid spacing from -179.75 to 179.75 by 0.5 coverage_content_type : coordinate long_name : longitude at grid cell center standard_name : longitude units : degrees_east array([-179.75, -179.25, -178.75, ..., 178.75, 179.25, 179.75],
dtype=float32) longitude_bnds
(longitude, nv)
float32
-180.0 -179.5 ... 179.5 180.0
coverage_content_type : coordinate long_name : longitude bounds grid cells array([[-180. , -179.5],
[-179.5, -179. ],
[-179. , -178.5],
...,
[ 178.5, 179. ],
[ 179. , 179.5],
[ 179.5, 180. ]], dtype=float32) time
(time)
datetime64[ns]
2014-12-16T12:00:00 ... 2015-12-...
axis : T bounds : time_bnds coverage_content_type : coordinate long_name : center time of averaging period standard_name : time array(['2014-12-16T12:00:00.000000000', '2015-01-16T12:00:00.000000000',
'2015-02-15T00:00:00.000000000', '2015-03-16T12:00:00.000000000',
'2015-04-16T00:00:00.000000000', '2015-05-16T12:00:00.000000000',
'2015-06-16T00:00:00.000000000', '2015-07-16T12:00:00.000000000',
'2015-08-16T12:00:00.000000000', '2015-09-16T00:00:00.000000000',
'2015-10-16T12:00:00.000000000', '2015-11-16T00:00:00.000000000',
'2015-12-16T12:00:00.000000000'], dtype='datetime64[ns]') time_bnds
(time, nv)
datetime64[ns]
dask.array<chunksize=(1, 2), meta=np.ndarray>
comment : Start and end times of averaging period. coverage_content_type : coordinate long_name : time bounds of averaging period
Bytes
208 B
16 B
Shape
(13, 2)
(1, 2)
Count
39 Tasks
13 Chunks
Type
datetime64[ns]
numpy.ndarray
2 13
Data variables: (3)
SSH
(time, latitude, longitude)
float32
dask.array<chunksize=(1, 360, 720), meta=np.ndarray>
comment : Dynamic sea surface height anomaly above the geoid, suitable for comparisons with altimetry sea surface height data products that apply the inverse barometer (IB) correction. Note: SSH is calculated by correcting model sea level anomaly ETAN for three effects: a) global mean steric sea level changes related to density changes in the Boussinesq volume-conserving model (Greatbatch correction, see sterGloH), b) the inverted barometer (IB) effect (see SSHIBC) and c) sea level displacement due to sea-ice and snow pressure loading (see sIceLoad). SSH can be compared with the similarly-named SSH variable in previous ECCO products that did not include atmospheric pressure loading (e.g., Version 4 Release 3). Use SSHNOIBC for comparisons with altimetry data products that do NOT apply the IB correction. coverage_content_type : modelResult long_name : Dynamic sea surface height anomaly standard_name : sea_surface_height_above_geoid units : m valid_max : 1.4207719564437866 valid_min : -1.8805772066116333
Bytes
12.85 MiB
0.99 MiB
Shape
(13, 360, 720)
(1, 360, 720)
Count
39 Tasks
13 Chunks
Type
float32
numpy.ndarray
720 360 13
SSHIBC
(time, latitude, longitude)
float32
dask.array<chunksize=(1, 360, 720), meta=np.ndarray>
comment : Not an SSH itself, but a correction to model sea level anomaly (ETAN) required to account for the static part of sea surface displacement by atmosphere pressure loading: SSH = SSHNOIBC - SSHIBC. Note: Use SSH for model-data comparisons with altimetry data products that DO apply the IB correction and SSHNOIBC for comparisons with altimetry data products that do NOT apply the IB correction. coverage_content_type : modelResult long_name : The inverted barometer (IB) correction to sea surface height due to atmospheric pressure loading units : m valid_max : 0.5245633721351624 valid_min : -0.30144819617271423
Bytes
12.85 MiB
0.99 MiB
Shape
(13, 360, 720)
(1, 360, 720)
Count
39 Tasks
13 Chunks
Type
float32
numpy.ndarray
720 360 13
SSHNOIBC
(time, latitude, longitude)
float32
dask.array<chunksize=(1, 360, 720), meta=np.ndarray>
comment : Sea surface height anomaly above the geoid without the inverse barometer (IB) correction, suitable for comparisons with altimetry sea surface height data products that do NOT apply the inverse barometer (IB) correction. Note: SSHNOIBC is calculated by correcting model sea level anomaly ETAN for two effects: a) global mean steric sea level changes related to density changes in the Boussinesq volume-conserving model (Greatbatch correction, see sterGloH), b) sea level displacement due to sea-ice and snow pressure loading (see sIceLoad). In ECCO Version 4 Release 4 the model is forced with atmospheric pressure loading. SSHNOIBC does not correct for the static part of the effect of atmosphere pressure loading on sea surface height (the so-called inverse barometer (IB) correction). Use SSH for comparisons with altimetry data products that DO apply the IB correction. coverage_content_type : modelResult long_name : Sea surface height anomaly without the inverted barometer (IB) correction units : m valid_max : 1.4550364017486572 valid_min : -1.6654272079467773
Bytes
12.85 MiB
0.99 MiB
Shape
(13, 360, 720)
(1, 360, 720)
Count
39 Tasks
13 Chunks
Type
float32
numpy.ndarray
720 360 13
Attributes: (57)
Conventions : CF-1.8, ACDD-1.3 acknowledgement : This research was carried out by the Jet Propulsion Laboratory, managed by the California Institute of Technology under a contract with the National Aeronautics and Space Administration. author : Ian Fenty and Ou Wang cdm_data_type : Grid comment : Fields provided on a regular lat-lon grid. They have been mapped to the regular lat-lon grid from the original ECCO lat-lon-cap 90 (llc90) native model grid. SSH (dynamic sea surface height) = SSHNOIBC (dynamic sea surface without the inverse barometer correction) - SSHIBC (inverse barometer correction). The inverted barometer correction accounts for variations in sea surface height due to atmospheric pressure variations. coordinates_comment : Note: the global 'coordinates' attribute describes auxillary coordinates. creator_email : ecco-group@mit.edu creator_institution : NASA Jet Propulsion Laboratory (JPL) creator_name : ECCO Consortium creator_type : group creator_url : https://ecco-group.org date_created : 2020-12-18T09:39:51 date_issued : 2020-12-18T09:39:51 date_metadata_modified : 2021-03-15T22:07:49 date_modified : 2021-03-15T22:07:49 geospatial_bounds_crs : EPSG:4326 geospatial_lat_max : 90.0 geospatial_lat_min : -90.0 geospatial_lat_resolution : 0.5 geospatial_lat_units : degrees_north geospatial_lon_max : 180.0 geospatial_lon_min : -180.0 geospatial_lon_resolution : 0.5 geospatial_lon_units : degrees_east history : Inaugural release of an ECCO Central Estimate solution to PO.DAAC id : 10.5067/ECG5M-SSH44 institution : NASA Jet Propulsion Laboratory (JPL) instrument_vocabulary : GCMD instrument keywords keywords : EARTH SCIENCE > OCEANS > SEA SURFACE TOPOGRAPHY > SEA SURFACE HEIGHT, EARTH SCIENCE SERVICES > MODELS > EARTH SCIENCE REANALYSES/ASSIMILATION MODELS keywords_vocabulary : NASA Global Change Master Directory (GCMD) Science Keywords license : Public Domain metadata_link : https://cmr.earthdata.nasa.gov/search/collections.umm_json?ShortName=ECCO_L4_SSH_05DEG_MONTHLY_V4R4 naming_authority : gov.nasa.jpl platform : ERS-1/2, TOPEX/Poseidon, Geosat Follow-On (GFO), ENVISAT, Jason-1, Jason-2, CryoSat-2, SARAL/AltiKa, Jason-3, AVHRR, Aquarius, SSM/I, SSMIS, GRACE, DTU17MDT, Argo, WOCE, GO-SHIP, MEOP, Ice Tethered Profilers (ITP) platform_vocabulary : GCMD platform keywords processing_level : L4 product_name : SEA_SURFACE_HEIGHT_mon_mean_2014-12_ECCO_V4r4_latlon_0p50deg.nc product_time_coverage_end : 2018-01-01T00:00:00 product_time_coverage_start : 1992-01-01T12:00:00 product_version : Version 4, Release 4 program : NASA Physical Oceanography, Cryosphere, Modeling, Analysis, and Prediction (MAP) project : Estimating the Circulation and Climate of the Ocean (ECCO) publisher_email : podaac@podaac.jpl.nasa.gov publisher_institution : PO.DAAC publisher_name : Physical Oceanography Distributed Active Archive Center (PO.DAAC) publisher_type : institution publisher_url : https://podaac.jpl.nasa.gov references : ECCO Consortium, Fukumori, I., Wang, O., Fenty, I., Forget, G., Heimbach, P., & Ponte, R. M. 2020. Synopsis of the ECCO Central Production Global Ocean and Sea-Ice State Estimate (Version 4 Release 4). doi:10.5281/zenodo.3765928 source : The ECCO V4r4 state estimate was produced by fitting a free-running solution of the MITgcm (checkpoint 66g) to satellite and in situ observational data in a least squares sense using the adjoint method standard_name_vocabulary : NetCDF Climate and Forecast (CF) Metadata Convention summary : This dataset provides monthly-averaged dynamic sea surface height interpolated to a regular 0.5-degree grid from the ECCO Version 4 Release 4 (V4r4) ocean and sea-ice state estimate. Estimating the Circulation and Climate of the Ocean (ECCO) state estimates are dynamically and kinematically-consistent reconstructions of the three-dimensional, time-evolving ocean, sea-ice, and surface atmospheric states. ECCO V4r4 is a free-running solution of a global, nominally 1-degree configuration of the MIT general circulation model (MITgcm) that has been fit to observations in a least-squares sense. Observational data constraints used in V4r4 include sea surface height (SSH) from satellite altimeters [ERS-1/2, TOPEX/Poseidon, GFO, ENVISAT, Jason-1,2,3, CryoSat-2, and SARAL/AltiKa]; sea surface temperature (SST) from satellite radiometers [AVHRR], sea surface salinity (SSS) from the Aquarius satellite radiometer/scatterometer, ocean bottom pressure (OBP) from the GRACE satellite gravimeter; sea-ice concentration from satellite radiometers [SSM/I and SSMIS], and in-situ ocean temperature and salinity measured with conductivity-temperature-depth (CTD) sensors and expendable bathythermographs (XBTs) from several programs [e.g., WOCE, GO-SHIP, Argo, and others] and platforms [e.g., research vessels, gliders, moorings, ice-tethered profilers, and instrumented pinnipeds]. V4r4 covers the period 1992-01-01T12:00:00 to 2018-01-01T00:00:00. time_coverage_duration : P1M time_coverage_end : 2015-01-01T00:00:00 time_coverage_resolution : P1M time_coverage_start : 2014-12-01T00:00:00 title : ECCO Sea Surface Height - Monthly Mean 0.5 Degree (Version 4 Release 4) uuid : 08a2fc68-4158-11eb-b498-0cc47a3f6943
<xarray.DataArray 'SSH' (time: 13, latitude: 360, longitude: 720)>
dask.array<concatenate, shape=(13, 360, 720), dtype=float32, chunksize=(1, 360, 720), chunktype=numpy.ndarray>
Coordinates:
* latitude (latitude) float32 -89.75 -89.25 -88.75 ... 88.75 89.25 89.75
* longitude (longitude) float32 -179.8 -179.2 -178.8 ... 178.8 179.2 179.8
* time (time) datetime64[ns] 2014-12-16T12:00:00 ... 2015-12-16T12:00:00
Attributes:
comment: Dynamic sea surface height anomaly above the geoi...
coverage_content_type: modelResult
long_name: Dynamic sea surface height anomaly
standard_name: sea_surface_height_above_geoid
units: m
valid_max: 1.4207719564437866
valid_min: -1.8805772066116333 Coordinates: (3)
latitude
(latitude)
float32
-89.75 -89.25 ... 89.25 89.75
axis : Y bounds : latitude_bnds comment : uniform grid spacing from -89.75 to 89.75 by 0.5 coverage_content_type : coordinate long_name : latitude at grid cell center standard_name : latitude units : degrees_north array([-89.75, -89.25, -88.75, ..., 88.75, 89.25, 89.75], dtype=float32) longitude
(longitude)
float32
-179.8 -179.2 ... 179.2 179.8
axis : X bounds : longitude_bnds comment : uniform grid spacing from -179.75 to 179.75 by 0.5 coverage_content_type : coordinate long_name : longitude at grid cell center standard_name : longitude units : degrees_east array([-179.75, -179.25, -178.75, ..., 178.75, 179.25, 179.75],
dtype=float32) time
(time)
datetime64[ns]
2014-12-16T12:00:00 ... 2015-12-...
axis : T bounds : time_bnds coverage_content_type : coordinate long_name : center time of averaging period standard_name : time array(['2014-12-16T12:00:00.000000000', '2015-01-16T12:00:00.000000000',
'2015-02-15T00:00:00.000000000', '2015-03-16T12:00:00.000000000',
'2015-04-16T00:00:00.000000000', '2015-05-16T12:00:00.000000000',
'2015-06-16T00:00:00.000000000', '2015-07-16T12:00:00.000000000',
'2015-08-16T12:00:00.000000000', '2015-09-16T00:00:00.000000000',
'2015-10-16T12:00:00.000000000', '2015-11-16T00:00:00.000000000',
'2015-12-16T12:00:00.000000000'], dtype='datetime64[ns]') Attributes: (7)
comment : Dynamic sea surface height anomaly above the geoid, suitable for comparisons with altimetry sea surface height data products that apply the inverse barometer (IB) correction. Note: SSH is calculated by correcting model sea level anomaly ETAN for three effects: a) global mean steric sea level changes related to density changes in the Boussinesq volume-conserving model (Greatbatch correction, see sterGloH), b) the inverted barometer (IB) effect (see SSHIBC) and c) sea level displacement due to sea-ice and snow pressure loading (see sIceLoad). SSH can be compared with the similarly-named SSH variable in previous ECCO products that did not include atmospheric pressure loading (e.g., Version 4 Release 3). Use SSHNOIBC for comparisons with altimetry data products that do NOT apply the IB correction. coverage_content_type : modelResult long_name : Dynamic sea surface height anomaly standard_name : sea_surface_height_above_geoid units : m valid_max : 1.4207719564437866 valid_min : -1.8805772066116333
# Commenting for quarto site render
# ds_multi['SSH'].hvplot.image()
References
https://github.com/fsspec/kerchunk
https://medium.com/pangeo/fake-it-until-you-make-it-reading-goes-netcdf4-data-on-aws-s3-as-zarr-for-rapid-data-access-61e33f8fe685
https://medium.com/pangeo/cloud-performant-reading-of-netcdf4-hdf5-data-using-the-zarr-library-1a95c5c92314