diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..b61d2a9 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.ipynb filter=jupyternotebook \ No newline at end of file diff --git a/.gitconfig b/.gitconfig new file mode 100644 index 0000000..b92634b --- /dev/null +++ b/.gitconfig @@ -0,0 +1,3 @@ +[filter "jupyternotebook"] + clean = jupyter nbconvert --ClearOutputPreprocessor.enabled=True --inplace %f + required \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b6e4761 --- /dev/null +++ b/.gitignore @@ -0,0 +1,129 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +.python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..659f68d --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,13 @@ +default_language_version: + python: python3 + +repos: +- repo: https://github.com/psf/black + rev: 8a59528c2d8ae1ef5f366039c728614aaf1a470b + hooks: + - id: black + - id: black-jupyter +- repo: https://github.com/kynan/nbstripout + rev: 0.5.0 + hooks: + - id: nbstripout \ No newline at end of file diff --git a/CONTRIBUTE.md b/CONTRIBUTE.md new file mode 100644 index 0000000..04da2bb --- /dev/null +++ b/CONTRIBUTE.md @@ -0,0 +1,30 @@ +# GEE source + +First off, thank you for considering contributing to the development of this module. It's people like you that make SEPAL a living platform. If it's your first time contributing on a github project take a look at this [link](http://makeapullrequest.com/) to better understand what a PR is. + +Following these guidelines helps to communicate that you respect the time of the developers managing and developing this open source project. In return, they should reciprocate that respect in addressing your issue, assessing changes, and helping you finalize your pull requests. + +This module is an open source project and we love to receive contributions from our community — you! There are many ways to contribute, from writing tutorials in google Classroom, improving the documentation, submitting bug reports and feature requests or writing code which can be incorporated into the module itself. + +## set up your environment + +SEPAL modules are of course meant to work on the sepal plateform so you should use the same [requirements](https://github.com/openforis/sepal/blob/master/modules/geospatial-toolkit/docker/config/requirements.txt) as we use on the prod platform if you work locally. But of course the easyest way is to work directly from [SEPAL](https://sepal.io) ! + +> don't forget to use the `earthengine authenticate` command to connect to your GEE account. + +To develop in this project first fork the module in your own github repositories and clone the repository with a terminal: + +``` +$ git clone https://github.com/12rambau/gee_source +``` + +## how to work with the issue tracker + +If you find yourself wishing for a feature that doesn't exist in this module, you are probably not alone. There should be others out there with similar needs. Many of the features that the module provide today have been added because our users saw the need. Open an issue on our issues list on GitHub which describes the feature you would like to see, why you need it, and how it should work. + +As a contributor you can also send PR (pull request) to solve issues tagged as "help wanted" or small correction (typo, documentation improvement, examples). For bigger contributions or new fonctionnalities please open an issue and discuss with our team before sending PR. + +## code guidelines + +We try our best to follow the [PEP 8](https://www.python.org/dev/peps/pep-0008/) rules for python coding. +This module is develop within the framework of the `sepal-ui` lib, check out its [documentation](https://sepal-ui.readthedocs.io/en/latest/) to better understand the design guidelines. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..f3b3ebe --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Food and Agriculture Organization of the United Nations (FAO) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..cedca1c --- /dev/null +++ b/README.md @@ -0,0 +1,8 @@ +# GEE source + +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/12rambau/gee_source/blob/master/LICENSE) +[![Black badge](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) + +# About + +extract source code from any GEE product URL diff --git a/about_ui.ipynb b/about_ui.ipynb new file mode 100644 index 0000000..830ebc8 --- /dev/null +++ b/about_ui.ipynb @@ -0,0 +1,77 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from sepal_ui import sepalwidgets as sw" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# create the Html body of your about section\n", + "about_tile = sw.TileAbout(\"utils/ABOUT.md\") # relative path to your markdown file" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# create the html body of the FAO disclaimer\n", + "# its mother class is sw.Tile so you can still replace it with another message if you want (discouraged)\n", + "disclaimer_tile = sw.TileDisclaimer()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# this tile will only be displayed if this very notebook is launched\n", + "# usefull for debugging\n", + "about_tile" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# this tile will only be displayed if this very notebook is launched\n", + "# usefull for debugging\n", + "disclaimer_tile" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.9" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/component/message/__init__.py b/component/message/__init__.py new file mode 100644 index 0000000..0e78b9c --- /dev/null +++ b/component/message/__init__.py @@ -0,0 +1,19 @@ +import os +from pathlib import Path + +from sepal_ui.translator import Translator + +# the sepal_ui allows you to create a translation interface +# at the moment this variable is not yet available but it's a good practice to build your app translatio-ready + +# first select the language env variable to load the destination locale +# it will default to en +lang = "en" +if "CUSTOM_LANGUAGE" in os.environ: + lang = os.environ["CUSTOM_LANGUAGE"] + +# create a ms object that will be used to translate all the messages +# the base language is english and every untranslated messages will be fallback to the english key +# complete the json file the add keys in the app +# avoid hard written messages at all cost +cm = Translator(Path(__file__).parent, lang) diff --git a/component/message/en.json b/component/message/en.json new file mode 100644 index 0000000..d91fec2 --- /dev/null +++ b/component/message/en.json @@ -0,0 +1,10 @@ +{ + "not_translated": "this message only exist in the en dict", + "app": { + "title": "GEE source", + "footer": "The sky is the limit \u00a9 {}", + "drawer_item": { + "about": "About" + } + } +} \ No newline at end of file diff --git a/component/message/fr.json b/component/message/fr.json new file mode 100644 index 0000000..fde66ef --- /dev/null +++ b/component/message/fr.json @@ -0,0 +1,9 @@ +{ + "app": { + "title": "GEE source", + "footer": "vers l'infini et au-del\u00e0 \u00a9 {}", + "drawer_item": { + "about": "A propos" + } + } +} \ No newline at end of file diff --git a/component/message/test_translation.ipynb b/component/message/test_translation.ipynb new file mode 100644 index 0000000..50ba274 --- /dev/null +++ b/component/message/test_translation.ipynb @@ -0,0 +1,77 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# this notebook is only here to provide the position of the missing keys\n", + "# the base dict is the english one.\n", + "# it should be complete\n", + "\n", + "from pathlib import Path\n", + "\n", + "from sepal_ui.translator import Translator" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# select the language you want to test\n", + "locale = \"en\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "ms = Translator(Path.cwd(), locale)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# normally there is only one key lissing ('not_tranlated')\n", + "# at the root of the file\n", + "print(ms.missing_keys())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.9" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/component/model/__init__.py b/component/model/__init__.py new file mode 100644 index 0000000..67bc954 --- /dev/null +++ b/component/model/__init__.py @@ -0,0 +1,4 @@ +# if you only have few io a module is not necessary and you can simply use a scripts.py file +# in a big module with lot of model, it can make sense to split things in separate for the sake of maintenance + +# if you use a module import all the functions here to only have 1 call to make diff --git a/component/parameter/__init__.py b/component/parameter/__init__.py new file mode 100644 index 0000000..1cd74bc --- /dev/null +++ b/component/parameter/__init__.py @@ -0,0 +1,6 @@ +# if you only have few parameters, a module is not necessary and you can simply use a tile.py file +# in a big module with lot of parameters, it can make sense to split things in separate for the sake of maintenance +# this should be the only place you hard-code parameters + +# if you use a module import all the functions here to only have 1 call to make +from .directory import * diff --git a/component/parameter/directory.py b/component/parameter/directory.py new file mode 100644 index 0000000..5117da8 --- /dev/null +++ b/component/parameter/directory.py @@ -0,0 +1,9 @@ +from pathlib import Path + +# this directory is the root directory of all sepal dashboard app. +# please make sure that any result that you produce is embeded inside this folder +# create a folder adapted to your need inside this folder to save anything in sepal +module_dir = Path.home() / "module_results" +module_dir.mkdir(exist_ok=True) + +# add all the directory that will be used in the app. diff --git a/component/scripts/__init__.py b/component/scripts/__init__.py new file mode 100644 index 0000000..5ef9a19 --- /dev/null +++ b/component/scripts/__init__.py @@ -0,0 +1,4 @@ +# if you only have few funcitions a module is not necessary and you can simply use a scripts.py file +# in a big module with lot of functions, it can make sense to split things in separate for the sake of maintenance + +# if you use a module import all the functions here to only have 1 call to make diff --git a/component/tile/__init__.py b/component/tile/__init__.py new file mode 100644 index 0000000..b8f7950 --- /dev/null +++ b/component/tile/__init__.py @@ -0,0 +1,4 @@ +# if you only have few tiles a module is not necessary and you can simply use a tile.py file +# in a big module with lot of tiles, it can make sense to split things in separate for the sake of maintenance + +# if you use a module import all the functions here to only have 1 call to make diff --git a/component/widget/__init__.py b/component/widget/__init__.py new file mode 100644 index 0000000..ac4e5be --- /dev/null +++ b/component/widget/__init__.py @@ -0,0 +1,4 @@ +# if you only have few widgets, a module is not necessary and you can simply use a widget.py file +# in a big module with lot of custom widgets, it can make sense to split things in separate files for the sake of maintenance + +# if you use a module import all the functions here to only have 1 call to make diff --git a/doc/en.rst b/doc/en.rst new file mode 100644 index 0000000..83d0206 --- /dev/null +++ b/doc/en.rst @@ -0,0 +1,10 @@ +GEE source +========== + +.. warning:: + + The english documentation of the module have not been set. + +.. tip:: + + Please open an issue on their repository : https://github.com/12rambau/gee_source/issues/new \ No newline at end of file diff --git a/doc/es.rst b/doc/es.rst new file mode 100644 index 0000000..808f2de --- /dev/null +++ b/doc/es.rst @@ -0,0 +1,10 @@ +GEE source +========== + +.. warning:: + + La documentación en español del módulo no ha sido fijada. + +.. tip:: + + Por favor, abre una incidencia en su repositorio : https://github.com/12rambau/gee_source/issues/new \ No newline at end of file diff --git a/doc/fr.rst b/doc/fr.rst new file mode 100644 index 0000000..5339dfc --- /dev/null +++ b/doc/fr.rst @@ -0,0 +1,10 @@ +GEE source +========== + +.. warning:: + + La documenation en français de ce module n'a pas été rédigée. + +.. tip:: + + Nous vous invitons à ouvrir une issue sur leur repository : https://github.com/12rambau/gee_source/issues/new \ No newline at end of file diff --git a/doc/img/full_app.png b/doc/img/full_app.png new file mode 100644 index 0000000..81b8469 Binary files /dev/null and b/doc/img/full_app.png differ diff --git a/no_ui.ipynb b/no_ui.ipynb new file mode 100644 index 0000000..093eb1a --- /dev/null +++ b/no_ui.ipynb @@ -0,0 +1,70 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# !!! testing purpose !!!\n", + "# this cell is for testing the translation component\n", + "# try uncomment the 2 following line to see the fr translation of the module\n", + "# import os\n", + "# os.environ[\"CUSTOM_LANGUAGE\"] = \"fr\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# fore debuggin purposes you can run all the tiles of your app without being in voila\n", + "# if you free the methods from their try catch statement, you'll be able to see all the error traceback\n", + "# you can also display the evolution of your io in extra cells along the process execution\n", + "\n", + "# of course the notebook should be run with 'kernel'->'restart and run all'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# load the patial files\n", + "%run 'about_ui.ipynb'" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# display each tile individually" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.9" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..d536d5f --- /dev/null +++ b/requirements.txt @@ -0,0 +1,18 @@ +# these libs are requested to build common python libs +# if you are an advance user and are sure to not use them you can comment the following lines +wheel +Cython +pybind11 +pre-commit + +# if you require GDAL and or pyproj in your module please uncomment these lines +# there are set up to be inlined with SEPAL implementation of GDAL and PROJ version +GDAL==3.0.4 +pyproj<3.0.0 + +# comment if you don't want to run your module with GEE in SEPAL +git+git://github.com/openforis/earthengine-api.git@v0.1.270#egg=earthengine-api&subdirectory=python + +# the base lib to run any sepal_ui based app +# don't forget to fix it to a specific version when you're app is ready +sepal_ui diff --git a/ui.ipynb b/ui.ipynb new file mode 100644 index 0000000..409cf38 --- /dev/null +++ b/ui.ipynb @@ -0,0 +1,142 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# !!! testing purpose !!!\n", + "# this cell is for testing the translation component\n", + "# try uncomment the 2 following line to see the fr translation of the module\n", + "# import os\n", + "# os.environ[\"CUSTOM_LANGUAGE\"] = \"fr\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from sepal_ui import sepalwidgets as sw\n", + "from component.message import cm" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Create an appBar\n", + "app_bar = sw.AppBar(cm.app.title)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Create a footer\n", + "# the footer will be display in the bottom of the page\n", + "# it's not a mandatory feature\n", + "app_footer = sw.Footer(cm.app.footer.format(2020))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# load the patial files\n", + "%run 'about_ui.ipynb'\n", + "\n", + "# Gather all the partial tiles that you created previously\n", + "app_content = [about_tile, disclaimer_tile]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# create a drawer for each group of tile\n", + "# use the DrawerItem widget from sepalwidget (name_of_drawer, icon, the id of the widgets you want to display)\n", + "# use the display_tile() method to link the times with the drawer items\n", + "items = [sw.DrawerItem(cm.app.drawer_item.about, \"mdi-help-circle\", card=\"about_tile\")]\n", + "\n", + "# !!! not mandatory !!!\n", + "# Add the links to the code, wiki and issue tracker of your\n", + "code_link = \"https://github.com/12rambau/gee_source\"\n", + "wiki_link = \"https://github.com/12rambau/gee_source/blob/master/doc/en.rst\"\n", + "issue_link = \"https://github.com/12rambau/gee_source/issues/new\"\n", + "\n", + "# Create the side drawer with all its components\n", + "# The display_drawer() method link the drawer with the app bar\n", + "app_drawer = sw.NavDrawer(items=items, code=code_link, wiki=wiki_link, issue=issue_link)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# build the Html final app by gathering everything\n", + "app = sw.App(\n", + " tiles=app_content, appBar=app_bar, footer=app_footer, navDrawer=app_drawer\n", + ").show_tile(\n", + " \"about_tile\"\n", + ") # id of the tile you want to display" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# display the app\n", + "# this final cell will be the only one displaying something in this notebook\n", + "# if you run all this notebook you may see elements displayed on the left side of your screen but it won't work\n", + "# it can only be launched with voila as it's creating a full page javascript interface\n", + "app" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.9" + }, + "voila": { + "theme": "dark" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/utils/ABOUT.md b/utils/ABOUT.md new file mode 100644 index 0000000..5eb31b5 --- /dev/null +++ b/utils/ABOUT.md @@ -0,0 +1 @@ +extract source code from any GEE product URL