From 111b14924f6b7f24779f2140ccbff5ba257ae612 Mon Sep 17 00:00:00 2001 From: Emmanuel Mathot Date: Fri, 4 Sep 2020 17:31:14 +0200 Subject: [PATCH] running notebooks --- .binder/Dockerfile | 86 ++++++++++++ .binder/NuGet.config | 16 +++ .vscode/settings.json | 4 +- docs/notebooks/.gitkeep | 0 docs/notebooks/example.ipynb | 260 +++++++++++++++++++++++++++++++++++ packages-microsoft-prod.deb | Bin 0 -> 3124 bytes 6 files changed, 365 insertions(+), 1 deletion(-) create mode 100644 .binder/Dockerfile create mode 100644 .binder/NuGet.config create mode 100644 docs/notebooks/.gitkeep create mode 100644 docs/notebooks/example.ipynb create mode 100644 packages-microsoft-prod.deb diff --git a/.binder/Dockerfile b/.binder/Dockerfile new file mode 100644 index 00000000..af9eeeb2 --- /dev/null +++ b/.binder/Dockerfile @@ -0,0 +1,86 @@ +FROM jupyter/base-notebook:latest + +# Install .NET CLI dependencies + +ARG NB_USER=jovyan +ARG NB_UID=1000 +ENV USER ${NB_USER} +ENV NB_UID ${NB_UID} +ENV HOME /home/${NB_USER} + +WORKDIR ${HOME} + +USER root +RUN apt-get update +RUN apt-get install -y curl + +ENV \ + # Enable detection of running in a container + DOTNET_RUNNING_IN_CONTAINER=true \ + # Enable correct mode for dotnet watch (only mode supported in a container) + DOTNET_USE_POLLING_FILE_WATCHER=true \ + # Skip extraction of XML docs - generally not useful within an image/container - helps performance + NUGET_XMLDOC_MODE=skip \ + # Opt out of telemetry until after we install jupyter when building the image, this prevents caching of machine id + DOTNET_TRY_CLI_TELEMETRY_OPTOUT=true + +# Install .NET CLI dependencies +RUN apt-get update \ + && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ + libc6 \ + libgcc1 \ + libgssapi-krb5-2 \ + libicu66 \ + libssl1.1 \ + libstdc++6 \ + zlib1g \ + && rm -rf /var/lib/apt/lists/* + +# Install .NET Core SDK + +# When updating the SDK version, the sha512 value a few lines down must also be updated. +ENV DOTNET_SDK_VERSION 3.1.301 + +RUN dotnet_sdk_version=3.1.301 \ + && curl -SL --output dotnet.tar.gz https://dotnetcli.azureedge.net/dotnet/Sdk/$dotnet_sdk_version/dotnet-sdk-$dotnet_sdk_version-linux-x64.tar.gz \ + && dotnet_sha512='dd39931df438b8c1561f9a3bdb50f72372e29e5706d3fb4c490692f04a3d55f5acc0b46b8049bc7ea34dedba63c71b4c64c57032740cbea81eef1dce41929b4e' \ + && echo "$dotnet_sha512 dotnet.tar.gz" | sha512sum -c - \ + && mkdir -p /usr/share/dotnet \ + && tar -ozxf dotnet.tar.gz -C /usr/share/dotnet \ + && rm dotnet.tar.gz \ + && ln -s /usr/share/dotnet/dotnet /usr/bin/dotnet \ + # Trigger first run experience by running arbitrary cmd + && dotnet help + +# Copy notebooks + +COPY ./notebooks/ ${HOME}/notebooks/ + +# Copy package sources + +COPY ./.binder/NuGet.config ${HOME}/nuget.config + +RUN chown -R ${NB_UID} ${HOME} +USER ${USER} + +#Install nteract +RUN pip install nteract_on_jupyter + +# Install lastest build from master branch of Microsoft.DotNet.Interactive from myget +RUN dotnet tool install -g Microsoft.dotnet-interactive --add-source "https://dotnet.myget.org/F/dotnet-try/api/v3/index.json" + +#latest stable from nuget.org +#RUN dotnet tool install -g Microsoft.dotnet-interactive --add-source "https://api.nuget.org/v3/index.json" + +ENV PATH="${PATH}:${HOME}/.dotnet/tools" +RUN echo "$PATH" + +# Install kernel specs +RUN dotnet interactive jupyter install + +# Enable telemetry once we install jupyter for the image +ENV DOTNET_TRY_CLI_TELEMETRY_OPTOUT=false + +# Set root to notebooks +WORKDIR ${HOME}/notebooks/ + diff --git a/.binder/NuGet.config b/.binder/NuGet.config new file mode 100644 index 00000000..c5b00b52 --- /dev/null +++ b/.binder/NuGet.config @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/.vscode/settings.json b/.vscode/settings.json index e0e1ac93..3e6fb202 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,5 @@ { - "dotnet-test-explorer.testProjectPath": "**/*Test.@(csproj|vbproj|fsproj)" + "dotnet-test-explorer.testProjectPath": "**/*Test.@(csproj|vbproj|fsproj)", + "python.dataScience.jupyterServerURI": "local", + "python.pythonPath": "/bin/python3" } \ No newline at end of file diff --git a/docs/notebooks/.gitkeep b/docs/notebooks/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/docs/notebooks/example.ipynb b/docs/notebooks/example.ipynb new file mode 100644 index 00000000..a9fca1d8 --- /dev/null +++ b/docs/notebooks/example.ipynb @@ -0,0 +1,260 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": "Installed package DotNetStac version 0.2.0" + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "#r \"nuget:DotNetStac,0.2.0\"" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "tags": [] + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": "CBERS4 MUX 027\n0.7.0\nCBERS4 MUX 027/069\nCBERS4 MUX 027/070\nCBERS4 MUX 027/071\nCBERS4 MUX 027/072\nCBERS4 MUX 027/073\nCBERS4 MUX 027/074\nCBERS4 MUX 027/076\nCBERS4 MUX 027/077\nCBERS4 MUX 027/078\nCBERS4 MUX 027/079\nCBERS4 MUX 027/080\nCBERS4 MUX 027/081\nCBERS4 MUX 027/082\nCBERS4 MUX 027/083\nCBERS4 MUX 027/084\nCBERS4 MUX 027/085\nCBERS4 MUX 027/086\nCBERS4 MUX 027/087\nCBERS4 MUX 027/088\nCBERS4 MUX 027/089\nCBERS4 MUX 027/090\nCBERS4 MUX 027/091\n" + } + ], + "source": [ + "using Stac;\n", + "using Stac.Catalog;\n", + "\n", + "public static class Sample {\n", + " public static void ListChildrensItemsAndAssets(IStacCatalog catalog, string prefix = \"\")\n", + " {\n", + " foreach (var child in catalog.GetChildren().Values)\n", + " {\n", + " Console.Out.WriteLine(prefix + child.Id);\n", + "\n", + " foreach(var item in catalog.GetItems().Values){\n", + " Console.Out.WriteLine(prefix + item.Id);\n", + " foreach(var asset in item.Assets.Values){\n", + " Console.Out.WriteLine(prefix + asset.Uri);\n", + " }\n", + " }\n", + "\n", + " ListChildrensItemsAndAssets(child, prefix + \" \");\n", + " }\n", + " }\n", + "}\n", + "\n", + "IStacCatalog catalog = (IStacCatalog)StacFactory.Load(\"https://cbers-stac-0-7.s3.amazonaws.com/CBERS4/MUX/027/catalog.json\");\n", + "\n", + "Console.Out.WriteLine(catalog.Id);\n", + "Console.Out.WriteLine(catalog.StacVersion);\n", + "\n", + "Sample.ListChildrensItemsAndAssets(catalog);\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\"extent\":{\"spatial\":{\"bbox\":[[-180.0,-56.0,180.0,83.0]]},\"temporal\":{\"interval\":[[\"2015-06-23T00:00:00Z\",null]]}},\"summaries\":{\"datetime\":{\"min\":\"2015-06-23T00:00:00Z\",\"max\":\"2019-07-10T13:44:56Z\"},\"platform\":[\"sentinel-2a\",\"sentinel-2b\"],\"constellation\":[\"sentinel-2\"],\"instruments\":[\"msi\"],\"view:off_nadir\":{\"min\":0.0,\"max\":100.0},\"view:sun_elevation\":{\"min\":6.78,\"max\":89.9},\"sci:citation\":[\"Copernicus Sentinel data [Year]\"],\"gsd\":[10,30,60],\"proj:epsg\":[32601,32602,32603,32604,32605,32606,32607,32608,32609,32610,32611,32612,32613,32614,32615,32616,32617,32618,32619,32620,32621,32622,32623,32624,32625,32626,32627,32628,32629,32630,32631,32632,32633,32634,32635,32636,32637,32638,32639,32640,32641,32642,32643,32644,32645,32646,32647,32648,32649,32650,32651,32652,32653,32654,32655,32656,32657,32658,32659,32660],\"eo:bands\":[{\"name\":\"B1\",\"common_name\":\"coastal\",\"center_wavelength\":4.439},{\"name\":\"B2\",\"common_name\":\"blue\",\"center_wavelength\":4.966},{\"name\":\"B3\",\"common_name\":\"green\",\"center_wavelength\":5.6},{\"name\":\"B4\",\"common_name\":\"red\",\"center_wavelength\":6.645},{\"name\":\"B5\",\"center_wavelength\":7.039},{\"name\":\"B6\",\"center_wavelength\":7.402},{\"name\":\"B7\",\"center_wavelength\":7.825},{\"name\":\"B8\",\"common_name\":\"nir\",\"center_wavelength\":8.351},{\"name\":\"B8A\",\"center_wavelength\":8.648},{\"name\":\"B9\",\"center_wavelength\":9.45},{\"name\":\"B10\",\"center_wavelength\":1.3735},{\"name\":\"B11\",\"common_name\":\"swir16\",\"center_wavelength\":1.6137},{\"name\":\"B12\",\"common_name\":\"swir22\",\"center_wavelength\":2.2024}]},\"license\":\"proprietary\",\"providers\":[{\"name\":\"European Union/ESA/Copernicus\",\"roles\":[\"producer\",\"licensor\"],\"url\":\"https://sentinel.esa.int/web/sentinel/user-guides/sentinel-2-msi\"}],\"keywords\":[\"copernicus\",\"esa\",\"eu\",\"msi\",\"radiance\",\"sentinel\"],\"stac_extensions\":[],\"stac_version\":\"1.0.0-beta.1\",\"links\":[{\"rel\":\"self\",\"href\":\"https://storage.cloud.google.com/earthengine-test/catalog/COPERNICUS_S2.json\"},{\"rel\":\"parent\",\"href\":\"https://storage.cloud.google.com/earthengine-test/catalog/catalog.json\"},{\"rel\":\"root\",\"href\":\"https://storage.cloud.google.com/earthengine-test/catalog/catalog.json\"},{\"rel\":\"license\",\"title\":\"Legal notice on the use of Copernicus Sentinel Data and Service Information\",\"href\":\"https://scihub.copernicus.eu/twiki/pub/SciHubWebPortal/TermsConditions/Sentinel_Data_Terms_and_Conditions.pdf\"}],\"description\":\"Sentinel-2 is a wide-swath, high-resolution, multi-spectral\\nimaging mission supporting Copernicus Land Monitoring studies,...\",\"id\":\"COPERNICUS/S2\",\"title\":\"Sentinel-2 MSI: MultiSpectral Instrument, Level-1C\"}\n" + ] + } + ], + "source": [ + "using Newtonsoft.Json;\n", + "using Newtonsoft.Json.Linq;\n", + "using Stac;\n", + "using Stac.Catalog;\n", + "using Stac.Collection;\n", + "using System;\n", + "using System.Collections.Generic;\n", + "\n", + " StacExtent extent = new StacExtent();\n", + " extent.Spatial = new StacSpatialExtent(-180, -56, 180, 83);\n", + " extent.Temporal = new StacTemporalExtent(DateTime.Parse(\"2015-06-23T00:00:00Z\").ToUniversalTime(), null);\n", + "\n", + " StacCollection collection = new StacCollection(\"COPERNICUS/S2\",\n", + " \"Sentinel-2 is a wide-swath, high-resolution, multi-spectral\\nimaging mission supporting Copernicus Land Monitoring studies,...\",\n", + " extent);\n", + "\n", + " collection.Title = \"Sentinel-2 MSI: MultiSpectral Instrument, Level-1C\";\n", + "\n", + " collection.Links.Add(StacLink.CreateSelfLink(new Uri(\"https://storage.cloud.google.com/earthengine-test/catalog/COPERNICUS_S2.json\")));\n", + " collection.Links.Add(StacLink.CreateParentLink(new Uri(\"https://storage.cloud.google.com/earthengine-test/catalog/catalog.json\")));\n", + " collection.Links.Add(StacLink.CreateRootLink(new Uri(\"https://storage.cloud.google.com/earthengine-test/catalog/catalog.json\")));\n", + " collection.Links.Add(new StacLink(new Uri(\"https://scihub.copernicus.eu/twiki/pub/SciHubWebPortal/TermsConditions/Sentinel_Data_Terms_and_Conditions.pdf\"), \"license\", \"Legal notice on the use of Copernicus Sentinel Data and Service Information\", null));\n", + "\n", + " collection.Keywords = new System.Collections.ObjectModel.Collection(new string[] {\n", + " \"copernicus\",\n", + " \"esa\",\n", + " \"eu\",\n", + " \"msi\",\n", + " \"radiance\",\n", + " \"sentinel\"});\n", + "\n", + " collection.Providers = new System.Collections.ObjectModel.Collection(\n", + " new StacProvider[]{new StacProvider(\"European Union/ESA/Copernicus\"){\n", + " Roles = new List() { StacProviderRole.producer, StacProviderRole.licensor},\n", + " Uri = new Uri(\"https://sentinel.esa.int/web/sentinel/user-guides/sentinel-2-msi\")\n", + " }});\n", + "\n", + " collection.Summaries.Add(\"datetime\",\n", + " new StacSummaryStatsObject(\n", + " DateTime.Parse(\"2015-06-23T00:00:00Z\").ToUniversalTime(),\n", + " DateTime.Parse(\"2019-07-10T13:44:56Z\").ToUniversalTime()\n", + " )\n", + " );\n", + "\n", + " collection.Summaries.Add(\"platform\",\n", + " new StacSummaryValueSet(new string[] { \"sentinel-2a\", \"sentinel-2b\" })\n", + " );\n", + "\n", + " collection.Summaries.Add(\"constellation\",\n", + " new StacSummaryValueSet(new string[] { \"sentinel-2\" })\n", + " );\n", + "\n", + " collection.Summaries.Add(\"instruments\",\n", + " new StacSummaryValueSet(new string[] { \"msi\" })\n", + " );\n", + "\n", + " collection.Summaries.Add(\"view:off_nadir\",\n", + " new StacSummaryStatsObject(\n", + " 0.0,\n", + " 100\n", + " )\n", + " );\n", + "\n", + " collection.Summaries.Add(\"view:sun_elevation\",\n", + " new StacSummaryStatsObject(\n", + " 6.78,\n", + " 89.9\n", + " )\n", + " );\n", + "\n", + " collection.Summaries.Add(\"sci:citation\",\n", + " new StacSummaryValueSet(new string[] { \"Copernicus Sentinel data [Year]\" })\n", + " );\n", + "\n", + " collection.Summaries.Add(\"gsd\",\n", + " new StacSummaryValueSet(new int[] {\n", + " 10,\n", + " 30,\n", + " 60\n", + " })\n", + " );\n", + "\n", + " collection.Summaries.Add(\"proj:epsg\",\n", + " new StacSummaryValueSet(new int[]\n", + " { 32601,32602,32603,32604,32605,32606,32607,32608,32609,32610,32611,32612,32613,32614,32615,32616,32617,32618,32619,32620,32621,32622,32623,32624,32625,32626,32627,32628,32629,32630,32631,32632,32633,32634,32635,32636,32637,32638,32639,32640,32641,32642,32643,32644,32645,32646,32647,32648,32649,32650,32651,32652,32653,32654,32655,32656,32657,32658,32659,32660}\n", + " )\n", + " );\n", + "\n", + " collection.Summaries.Add(\"eo:bands\",\n", + " new StacSummaryValueSet(new JObject[] {\n", + " new JObject {\n", + " { \"name\", \"B1\" },\n", + " { \"common_name\", \"coastal\" },\n", + " { \"center_wavelength\", 4.439 }\n", + " },\n", + " new JObject {\n", + " { \"name\", \"B2\"},\n", + " { \"common_name\", \"blue\"},\n", + " { \"center_wavelength\", 4.966}\n", + " },\n", + " new JObject {\n", + " { \"name\", \"B3\"},\n", + " { \"common_name\", \"green\"},\n", + " { \"center_wavelength\", 5.6}\n", + " },\n", + " new JObject {\n", + " { \"name\", \"B4\"},\n", + " { \"common_name\", \"red\"},\n", + " { \"center_wavelength\", 6.645}\n", + " },\n", + " new JObject {\n", + " { \"name\", \"B5\"},\n", + " { \"center_wavelength\", 7.039}\n", + " },\n", + " new JObject {\n", + " { \"name\", \"B6\"},\n", + " { \"center_wavelength\", 7.402}\n", + " },\n", + " new JObject {\n", + " { \"name\", \"B7\"},\n", + " { \"center_wavelength\", 7.825}\n", + " },\n", + " new JObject {\n", + " { \"name\", \"B8\"},\n", + " { \"common_name\", \"nir\"},\n", + " { \"center_wavelength\", 8.351}\n", + " },\n", + " new JObject {\n", + " { \"name\", \"B8A\"},\n", + " { \"center_wavelength\", 8.648}\n", + " },\n", + " new JObject {\n", + " { \"name\", \"B9\"},\n", + " { \"center_wavelength\", 9.45}\n", + " },\n", + " new JObject {\n", + " { \"name\", \"B10\"},\n", + " { \"center_wavelength\", 1.3735}\n", + " },\n", + " new JObject {\n", + " { \"name\", \"B11\"},\n", + " { \"common_name\", \"swir16\"},\n", + " { \"center_wavelength\", 1.6137}\n", + " },\n", + " new JObject {\n", + " { \"name\", \"B12\"},\n", + " { \"common_name\", \"swir22\"},\n", + " { \"center_wavelength\", 2.2024}\n", + " }\n", + " })\n", + " );\n", + "\n", + " var json = JsonConvert.SerializeObject(collection);\n", + "\n", + " Console.WriteLine(json);" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".NET (C#)", + "language": "C#", + "name": ".net-csharp" + }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/x-csharp", + "name": "C#", + "pygments_lexer": "csharp", + "version": "3.8.2-final" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} \ No newline at end of file diff --git a/packages-microsoft-prod.deb b/packages-microsoft-prod.deb new file mode 100644 index 0000000000000000000000000000000000000000..92839d8e0aa2c71cb5ab58370d8eb1ddb542c2bb GIT binary patch literal 3124 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