From 7356c6130fe1add16c721c2dfeb7aab4e7f98b17 Mon Sep 17 00:00:00 2001 From: Macbook-pro Date: Sat, 5 Aug 2023 21:56:25 +0200 Subject: [PATCH 01/16] init pypi branch --- .github/workflows/pypi.yml | 40 +++ .gitignore | 2 + Docs.md | 612 ++++++++++++++++++++++++++++++++++++ README.md | 629 +------------------------------------ resources/.DS_Store | Bin 0 -> 6148 bytes setup.py | 3 +- 6 files changed, 667 insertions(+), 619 deletions(-) create mode 100644 .github/workflows/pypi.yml create mode 100644 Docs.md create mode 100644 resources/.DS_Store diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml new file mode 100644 index 0000000..d835161 --- /dev/null +++ b/.github/workflows/pypi.yml @@ -0,0 +1,40 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +# GitHub recommends pinning actions to a commit SHA. +# To get a newer version, you will need to update the SHA. +# You can also reference a tag or branch, but the action may change without warning. + +name: Build and publish PyRawS distribution to PyPI + +on: + push: + branches: [ "pypi" ] # CHANGE THIS. This workflow only runs when a commit is pushed to the pypi branch. + + +jobs: + pypi-publish: + name: Upload release to PyPI + runs-on: ubuntu-latest + permissions: + id-token: write # IMPORTANT: this permission is mandatory for trusted publishing + steps: + - name: Check out code + uses: actions/checkout@v2 + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.8' + + - name: Build Python package + run: python setup.py bdist_wheel + + - name: Publish package distributions to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + user: sirbastiano94 + password: ${{ secrets.PYPI_PASSWORD }} + repository-url: https://pypi.org/project/pyraws/1.0.0/ diff --git a/.gitignore b/.gitignore index 3d3d7db..f533eba 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,5 @@ scripts_and_studies/Test/ *.pkl scripts_and_studies/coregistration_study/superglue_models pyraws/sys_config.py +dist +build \ No newline at end of file diff --git a/Docs.md b/Docs.md new file mode 100644 index 0000000..afd5440 --- /dev/null +++ b/Docs.md @@ -0,0 +1,612 @@ + +# Documentation + + +
+ Table of Contents +
    +
  1. About the Project
  2. +
  3. Content of the repository
  4. +
  5. Installation + +
  6. PyRawS databases
  7. +
  8. Raw events and Raw granules
  9. +
  10. Quickstart + +
  11. +
  12. Glossary
  13. +
  14. Contributing
  15. +
  16. License
  17. +
  18. Contacts
  19. +
+
+ + + + +## Content of the repository +The PyRawS repository includes the following directories: + + +* **quickstart**: it contains some subdirectories including [jupyter notebooks](https://jupyter-notebook.readthedocs.io/en/stable/index.html): + 1. `API demonstration`: it contains a notebook to demonstrate PyRawS API. + 2. `DB_creation`: it contains a notebook to automatically create a database for a target dataset. + 3. `geographical_distribution`: it contains a notebook to diplay the geographical distribution of the events of a dataset into a map. + +* **PyRawS**: it contains the PyRawS package. The latter is made of the following subdirectories: + 1. `database`: it contains various [PyRawS database](#PyRawS-databases) and other databases. + 2. `raw`: it includes the `Raw_event` and `Raw_granule` classes used to model, respectively, [Sentinel-2 Raw events](#sentinel-2-raw-event) and [Sentinel-2 Raw granules](#sentinel-2-raw-granule). + 3. `l1`: it contains the `L1_event` and `L1_tiles` classes used to model, respectively, [Sentinel-2 L1C events](#sentinel-2-l1c-event) and [Sentinel-2 L1C tiles](#sentinel-2-l1c-tile). + 4. `utils`: it contains some utilities for the PYRAW package. + +* **resources**: it contains various resources (i.e., images for the README) +* **scripts_and_studies**: it contains various scripts and code for different studies realized to create the `THRAWS` dataset. In particular: + 1. `coregistration_study`: it contains utils used to perform the coregistration study and desing the [coarse coregistration](#coarse-coregistration) technique. + 2. `dataset_preparation`: it contains scripts and other files used to design the `THRAWS` files (i.e., download data, select events, and others). + 3. `hta_detection_algorithms`: it contains custom and simplified implementation of various high-thermal-anomalies-dection algorithms, including [1](#ref1) used to design the `THRAWS` dataset. + 4. `runscripts`: it contains some runscripts and utils to crop [Sentinel-2 L1C tiles](#sentinel-2-l1c-tile) and generate useful images and export tif. + 5. `granules_filtering`: it contains a script to run and [[1]](#ref1) on [cropped Sentinel-2 L1-C tiles](#sentinel-2-l1c-tile), extract bounding boxes and map them to the correspondent [Raw granules](#sentinel-2-raw-granule). + 6. `download_thraws`: it contains the utility for the download of the dataset [THRAWS](https://zenodo.org/record/7908728). + + + +## Installation +### Pre-requirements +Before all, clone this repository. We suggest using git from CLI, execute: + +``` git clone https://github.com/ESA-PhiLab/PyRawS ``` + + +### Create the PyRawS environment +#### - On Linux +``` +# For Linux, the installation is straightforward. +# You just need to run the following command from the main directory: + +\bin\bash\ source pyraws_install.sh + +# NB: Your data should be placed in the data directory in the main. +``` + +#### - On Other Os +``` +# To install the environment, we suggest to use anaconda. +# You can create a dedicated conda environment by using the `environment.yml` file by running the following command from the main directory: + +conda env create -f environment.yml + +# To activate your environment, please execute: + +conda activate PyRawS + +``` + +Create a file `sys_cfg.py` in the directory `pyraws\pyraws`, and add two variables as follows: + +``` PYRAWS_HOME_PATH="Absolute path to the main pyraws directory.``` + +``` DATA_PATH="Absolute path to the data directory. " ``` + +By default the data directory is located in PyRawS main directory. + + +### Docker + +To use PyRawS with docker, use one of the following methods. + + +#### Method 1: Pull the docker image from Docker Hub + +``` docker pull sirbastiano94/pyraws:latest ``` + +#### Method 2: Build docker image + +Follow these steps: + +1. Clone the repository and build the docker image by running the following command from the main directory: + +``` docker build -t pyraws:latest --build-arg CACHEBUST=$(date +%s) -f dockerfile . ``` + +2. Run the docker image by executing: + +``` docker run -it --rm -p 8888:8888 pyraws:latest ``` + + +### Set-up for coregistration study + +If you want to perform the coregistration study, you need to: + +* clone the repository [SuperGlue Inference and Evaluation Demo Script](https://github.com/magicleap/SuperGluePretrainedNetwork); +* rename the subdirectory `models` to `superglue_models`; +* move `superglue_models` into `coregistration_study`. + +Coregistration study results can be generated by using the `pyraws_coregistration_study.ipynb` notebook. The database `coregistration_study_db.csv` containing info on the discarded eruption events is used to generate results in the notebook. + +Coregistration notebook results can be generated by using the `pyraws_coregistration_profiling.ipynb` notebook. + +### Data directory + +All the data used by PyRawS need to be located in a directory called `data`, containing all the different datasets. You can place the `data` directory where you want and update the `DATA_PATH` variable in the `sys_cfg.py` file with its path (please, refer to: [Set-up for coregistration study](#set-up-for-coregistration-study)). +By default the data directory is located in PyRawS main directory. +
+To create a specific dataset, you need to create subfolder with the dataset name (e.g., `THRAWS`) in the `data` directory specific for your dataset. Such directory shall contain the following subdirectories: + +* `raw`: it will contain [decompressed raw](#sentinel-2-raw-data). +* `l1c`: it will contain [L1C](#sentinel-2-l1c-data). + +Every [raw data](#sentinel-2-decompressed-raw-data) and [L1C](#sentinel-2-l1c-data) data shall be contained in a specific subdirectory --placed in `raw`or `l1c`-- whose name shall match one of the **ID_event** entries of the **.csv** file, located in `database` directory. + +## PyRawS databases + +To create the "THRAWS" database, the user should refer to the notebook called "database_creation.ipynb". This notebook contains the necessary code and instructions for creating the database. Simply follow the steps outlined in the notebook to successfully create the "THRAWS" database. + +Please note that it is important to carefully follow the instructions in the notebook to ensure that the database is created correctly and without errors. Additionally, make sure that all required dependencies and packages are installed before running the code in the notebook. + +![Alt Text](resources/images/database_structure.png) + + +This respository contains an example of database (`THRAWS`) that is used by PyRawS to read and process [Sentinel-2 Raw data](#sentinel-2-raw-data) and [Sentinel-2 L1 data](#sentinel-2-l1-data) correctly. The minimal fields of the database include: + +* **ID_event**: ID of the event (e.g., volcanic-eruption, wildfire, not-event). All the other fields of the row are referred to that `Sentinel-2` acquisition. +* **class**: class of the event (e.g., eruption, fire, not-event). Leave it **empty** +* **Raw_useful_granules**: list of [Raw useful granules](#raw-useful-granule). Set to `None` or leave it empty if you do not know what are the [Raw useful granules](#raw-useful-granule). +* **Raw_complementary_granules**: list of [Raw complementry granules](#raw-complementary-granule). Set to `None` or leave it empty if you do not know what are the [Raw complementry granules](#raw-complementary-granule). +* **Raw_files**: list of [Raw granules](#sentinel-2-raw-granule) (**mandatory**). +* **l1c_files**: list of [L1 tiles](#sentinel-2-l1c-tile) (mandatory if you need L1C data). +* **bbox_list**: dictionary {[Raw useful granules](#raw-useful-granule) : [bounding box list for that granule]}. Set to `None` or leave it **empty** if you do not know the bounding box location. + +To create a new database (e.g., `my_database_name`), please, proceed as follows: + +1. Create a ".csv" file with the structure shown above and place it into the `database`subfloders (e.g., `my_db.csv`). You can use start from the [thraws_db.csv](https://github.com/ESA-PhiLab/PyRawS/-/blob/main/PyRawS/database/thraws_db.csv) database and edit it accordingly to your specification. +2. Create subdirectory `my_database_name` in the `data` subdirectory and populate it with the correspondent [Sentinel-2 Raw data](#sentinel-2-raw-data) and [Sentinel-2 L1 data](#sentinel-2-l1-data) as described in [Data directory](#data-directory). +3. Update the `DATABASE_FILE_DICTIONARY` in `PyRawS/utils/constants.py` as follows: + +```DATABASE_FILE_DICTIONARY={"THRAWS" : "thraws_db.csv", "my_database_name" : "my_db.csv"}``` + +Now, you should be able to use your new database.
+**N.B** The creation of a database is not mandatory. However, it is strongly advisable. Indeed, without creating a database you can still open `Raw data` as described in [Open a Raw event from path](#open-a-raw-event-from-path). However, some pieces of information such as the [Raw useful granules](#raw-useful-granule) associated to a specific event, the event bounding boxes or the image class can be retrieved only when the database is set-up. + +## Raw events and Raw granules +![Alt Text](resources/images/etna_00_granules.png) + +Downloading [Sentinel-2 Raw data](#sentinel-2-raw-data) requires to specify a polygon surrounding the area of interest and a date. Given the pushbroom nature of the [Sentinel-2](https://sentinel.esa.int/documents/247904/685211/sentinel-2-products-specification-document) sensor, bands of data at [Raw](#sentinel-2-raw-data) level do not look at the same area (i.e., they are not registered). Therefore,to be sure to collect all the band around an event (i.e., volcanic eruptions, wildfires) rectangular polygons centered on the events of area 28x10 $km^2$ are used (white rectangular in the image above). This leads to download all the [Raw granules](#sentinel-2-raw-granule) whose reference band (`B02`) interesects the polygon area.
The image above shows the footprint of the all the [Sentinel-2 Raw granules](#sentinel-2-raw-granule) that are downloaded for the eruption named "`Etna_00`" in our database by using the white rectangular polygon. We define the collection of [Raw granules](#sentinel-2-raw-granule) that are downloaded for each of the rows of our database "[Sentinel-2 Raw event](#Sentinel-2-RAW-event)".
However, as you can see in the image above, most of the [Sentinel-2 Raw granules](#sentinel-2-raw-granule) in `Etna_00` [Sentinel-2 Raw event](#Sentinel-2-RAW-event) do not contain the volcanic eruption (big red spot) of interest (red rectangulars). Indeed, only the yellow and the pink rectangulars intersects or include part of the volcanic eruption.
In addition, the fact that one [Raw granule](#sentinel-2-raw-granule) intersects or include one event, this does not mean that the latter interesects or is included in all the bands of that [Raw granule](#sentinel-2-raw-granule). In particular, +since we use the bands [`B8A`, `B11`, `B12`] to detect wildfires and volcanic eruptions, we consider [Raw useful granules](#raw-useful-granule) those granules whose band `B8A` interesects the event. This is true for the yellow rectangular but not for the pink one (you need to trust us here, since the bands are not displaced in the image above). We take the band `B8A` only because after the coregistration, the other bands will be moved to match the area of `B8A`.
+Finally, for some [Raw useful granules](#raw-useful-granule) part of the eruptions or the wildfire could extend until the top or the bottom edge of the polygon. In this case, some of the bands could be missing for a portion of the area of interest. To be sure that this is not happening, in addition to the [Raw useful granules](#raw-useful-granule), it is important to consider [Raw complementary granules](#raw-complementary-granule), which fills the missing part of the interest bands of the [Raw useful granules](#raw-useful-granule).
For each [Sentinel-2 Raw event](#Sentinel-2-RAW-event), the `THRAWS` dataset clearly states those [Raw granules](#sentinel-2-raw-granule) that are [Raw useful granules](#raw-useful-granule) or [Raw complementary granules](#raw-complementary-granule). However, the entire [Raw granules](#sentinel-2-raw-granule) collection is provided for each [Raw event](#sentinel-2-raw-event) to permit users that wants to use other bands to detect warm temeprature anomalies to do it. + + +## Quickstart +The next examples (with the exception of [Open a Raw event from path](#open-a-raw-event-from-path)) will exploit the `THRAWS` database to showcase the use of PyRawS, but they are applicable to any [databases compatible with PyRawS](#PyRawS-databases). + +### Open a Raw event from path +The next code snipped will showcase how to use PyRawS to open a [Raw_event](#sentinel-2-raw-event) `My_Raw_data`, included in the `THRAWS` database by using its `PATH`. We assume to have the `My_RAW_data` directory in the same directory where you execute the code snippet below.
+To manipulate [Raw events](#sentinel-2-raw-event), `PyRawS` offer a class called `Raw_event`. To open an avent, we will use the [Raw_event](#sentinel-2-raw-event) class method `from_path(...)`, which parses the database specified, retrieves the event specified by `id_event` and opens it with the requested bands (`bands_list`). +When you open an event, you can specify which bands to use. If `bands_list` is not specified, the method `from_path(...)` will return all the bands. + +```py +from pyraws.raw.raw_event import Raw_event +#Instantiate an empty Raw_event +raw_event=Raw_event() + +#Bands to open. +bands_list=["B8A", "B11", "B12"] + +#Read "Etna_00" from THRAWS +raw_event.from_path(#Path to the Etna_00 event + raw_dir_path="Path_to_my_RAW_data", + #Bands to open. Leave to None to use all the bands. + bands_list=bands_list, + #If True, verbose mode is on. + verbose=True) +``` +The example above can be used directly, **even if you did not set up a** [PyRawS database](#PyRawS-databases). However, `PyRawS` offer some API to parse directly [Raw_event](#sentinel-2-raw-event) parsing a database. with no need to specify a path. Please, check [Open a Raw event from database](#open-a-raw-event-from-database). + +### Open a Raw event from database +The next code snipped will showcase how to use PyRawS to open the [Raw_event](#sentinel-2-raw-event) `Etna_00` included in the `THRAWS` database.
To do that, +To manipulate [Raw events](#sentinel-2-raw-event) objects, `PyRawS` will exploits the `Raw_event` class method `from_database(...)`, which parses the associated `.csv` file located in `PyRawS/database` with no need to specify the `PATH` from the user. To execute the next code snipped, we assume to you have already downloaded and set-up the `THRAWS` database as specificied in [databases compatible with PyRawS](#PyRawS-databases). +As for the method `from_path(...)` described in [Open a Raw event from path](#open-an-raw-event-from-path), you can specify which bands to use. If `bands_list` is not specified, the method `from_database(...)` will return all the bands. + +```py +from pyraws.raw.raw_event import Raw_event +#Instantiate an empty Raw_event +raw_event=Raw_event() + +#Bands to open. +bands_list=["B8A", "B11", "B12"] + +#Read "Etna_00" from THRAWS +raw_event.from_database(#Database ID_EVENT + id_event="Etna_00", + #Bands to open. Leave to None to use all the bands. + bands_list=bands_list, + #If True, verbose mode is on. + verbose=True, + #Database name + database="THRAWS") +``` +All the next examples will assume you already have downloaded and set-up the `THRAWS` database as specificied in [databases compatible with PyRawS](#PyRawS-databases). However, they can work by using `from_path(...)` instead of `from_database(...)` and specifying the `PATH` to the `Etna_00` event manually. + +### Show Raw granules information of a Raw event +As specified in [Raw events and Raw granules](#raw-events-and-raw-granules), an [Raw event](#sentinel-2-raw-event) is a collection of [Raw granules](#sentinel-2-raw-granule). As for [Raw_event](#sentinel-2-raw-event), [Raw granules](#sentinel-2-raw-granule) are modelled in PyRawS through a dedicated class `Raw_granule`.
+The next code snippet will show how to get the information about the [Raw granules](#sentinel-2-raw-granule) that compose the `Etna_00` [Raw_event](#sentinel-2-raw-event). The class method `show_granules_info()` will print the list of events and some metada for each event. To get the same information as a dictionary `{granule name : granule info}` for an easy manipulation, you can use the `Raw_event` class method `get_granules_info(...)`. + +```py +from pyraws.raw.raw_event import Raw_event +#Instantiate an empty Raw_event +raw_event=Raw_event() + +#Bands to open. +bands_list=["B8A", "B11", "B12"] + +#Read "Etna_00" from THRAWS database. +#You can also read it by using raw_event.from_path(...). +raw_event.from_database( #Database ID_EVENT + id_event="Etna_00", + #Bands to open. Leave to None to use all the bands. + bands_list=bands_list, + #If True, verbose mode is on. + verbose=True, + #Database name + database="THRAWS") +# Printing granules info +raw_event.show_granules_info() + +#Getting Raw granules info dictionary {granule name : granule info} +granules_info_dict=raw_event.get_granules_info() +``` + +### Get a single Raw\_granule from a Raw\_event +The class `Raw_event` contains a list of objects `Raw_granule`, each one modelling a specific [Raw granule](#sentinel-2-raw-granule) that belongs to that [Raw_event](#sentinel-2-raw-event) (please, check [Raw events and Raw granules](#raw-events-and-raw-granules) for more information).
+The different `Raw_granule` objects are sorted alphabetically and are accessible through indices. The next code snippet will show how to get a specific [Raw granule](#sentinel-2-raw-granule) by using the `Raw_event` class method `get_granule(granule_idx)`, where `granule_idx` is the granule indices. The function returns an `Raw_granule` object. As for `Raw_event` objects, it is possible to print or retrieve metadata information for a spefic `Raw_granule` by using the `Raw_granule` methods `get_granule_info()` and `show_granule_info()`. + +```py +from pyraws.raw.raw_event import Raw_event +#Instantiate an empty Raw_event +raw_event=Raw_event() + +#Bands to open. +bands_list=["B8A", "B11", "B12"] + +#Read "Etna_00" from THRAWS database. +#You can also read it by using raw_event.from_path(...). +raw_event.from_database( #Database ID_EVENT + id_event="Etna_00", + #Bands to open. Leave to None to use all the bands. + bands_list=bands_list, + #If True, verbose mode is on. + verbose=True, + #Database name + database="THRAWS") + +#Read the granule 0 of the Etna_00 event. +raw_granule_0 = raw_event.get_granule(0) + +# Printing the info of the granule 0 +raw_granule_0.show_granule_info() + +#Getting Raw granules info dictionary {granule name : granule info} +granule_0_info_dict=raw_granule_0.get_granule_info() +``` + +### Access a Raw\_granule pixels +To visualize the values of an `Raw_data` object, it is possible to return it as a [PyTorch](https://pytorch.org/) tensor. However, since the different bands have different resolutions, depending on the bands that we want to shape as a tensor, it is necessary to upsample/downsample some of them to adapt them to the band with higher/smaller resolution. The next code snippet will open the `Etna_00` with bands `B02` (10 m), `B8A` (20 m), `B11` (20 m), get the granule with index 1, and will return the first two bands in the collection as tensor by performing upsample. + +```py +from pyraws.raw.raw_event import Raw_event +#Instantiate an empty Raw_event +raw_event=Raw_event() + +#Bands to open. +bands_list=["B04", "B8A", "B11"] + +#Read "Etna_00" from THRAWS database. +#You can also read it by using raw_event.from_path(...). +raw_event.from_database( #Database ID_EVENT + id_event="Etna_00", + #Bands to open. Leave to None to use all the bands. + bands_list=bands_list, + #If True, verbose mode is on. + verbose=True, + #Database name + database="THRAWS") + +#Read the granule 1 of the Etna_00 event. +raw_granule_1 = raw_event.get_granule(1) + +#Returning the bands B04 and B8A of raw_granule_1 as tensor by upsampling. +raw_granule_1_tensor=raw_granule_1.as_tensor(#list of bands to transform as tensor + requested_bands=["B04", "B8A"], + #Set to True to perform downsampling (default) + downsampling=False) +``` + +### Superimpose Raw\_granule bands +It is possible to superimpose `Raw_granule` bands by using the class method `show_bands_superimposition(...)`. (N.B. it is possible to superimpose up to three bands). +In case bands have different resolution, you need to specify if you want to superimpose them by performing downsampling (default) or upsampling. The next code snippet will open the `Etna_00` with bands `B02`, `B8A`, `B11`, `B12`, get the granule with index 0, and will superimpose the last three bands. + +```py +from pyraws.raw.raw_event import Raw_event +import matplotlib.pyplot as plt + +#Instantiate an empty Raw_event +raw_event=Raw_event() + +#Bands to open. +bands_list=["B04", "B8A", "B11", "B12"] + +#Read "Etna_00" from THRAWS database. +#You can also read it by using raw_event.from_path(...). +raw_event.from_database( #Database ID_EVENT + id_event="Etna_00", + #Bands to open. Leave to None to use all the bands. + bands_list=bands_list, + #If True, verbose mode is on. + verbose=True, + #Database name + database="THRAWS") + +#Read the granule 0 of the Etna_00 event. +raw_granule_0 = raw_event.get_granule(0) + +#Returning the bands B04 and B8A of raw_granule_1 as tensor by upsampling. +raw_granule_0.show_bands_superimposition(#Bands to superimpose + requested_bands=["B04", "B11", "B12"], + #Set to True to perform downsampling + downsampling=True) +plt.show() +``` + +The previous code snippet will display the image below. As you can see, the various bands of the image lack of coregistration of the various bands. + +![Alt Text](resources/images/granule_superimposition.png) + +### How to perform the coarse coregisteration of Raw\_granules +PyRawS offers some utils to perform [coarse coregistration](#coarse-coregistration) on `Raw_granule` objects. You can coregister a specific `Raw_granule` object of the `Raw_event` collection by calling the `coarse_coregistration(...)` method of the `Raw_event` class by selecting the correspondent index through the `granules_idx` input.
+ +```py +from pyraws.raw.raw_event import Raw_event + +#Instantiate an empty Raw_event +raw_event=Raw_event() + +#Bands to open. +bands_list=["B04", "B8A", "B11"] + +#Read "Etna_00" from THRAWS database. +#You can also read it by using raw_event.from_path(...). +raw_event.from_database( #Database ID_EVENT + id_event="Etna_00", + #Bands to open. Leave to None to use all the bands. + bands_list=bands_list, + #If True, verbose mode is on. + verbose=True, + #Database name + database="THRAWS") + +# Perform the corase coregistration of the "Etna_00" event. +# Missing pixels will be filled with zeros. +raw_coreg_granule_2=raw_event.coarse_coregistration( # granule index to coregister. + granules_idx=[2]) +``` + +The previous code snippet returns the coarse coregistration of the granule 2 of the "Etna_00" event. The coarse coregistration is performed by shifting the bands `B8A` and `B11` with respect to the band `B04`, which is the first in the collection. The missing pixels produced by the shift of the bands `B8A` and `B11` will be filled by zeros. The superimposition of the coregistered bands with zero-filling is shown in the image below ("coregistration") +It is possible to launch crop the missing values by setting the argument `crop_empty_pixels=True`, as in the snippet below. + +```py +from pyraws.raw.raw_event import Raw_event + +#Instantiate an empty Raw_event +raw_event=Raw_event() + +#Bands to open. +bands_list=["B04", "B8A", "B11"] + +#Read "Etna_00" from THRAWS database. +#You can also read it by using raw_event.from_path(...). +raw_event.from_database( #Database ID_EVENT + id_event="Etna_00", + #Bands to open. Leave to None to use all the bands. + bands_list=bands_list, + #If True, verbose mode is on. + verbose=True, + #Database name + database="THRAWS") + +# Perform the corase coregistration of the "Etna_00" event. +# Missing pixels will be cropped. +raw_coreg_granule_0_with_crop=raw_event.coarse_coregistration(# granule index to coregister. + granules_idx=[2], + # Cropping missing pixels. + crop_empty_pixels=True) +``` + +Alternatively, you can fill the pixing pixels with filler elements taken from other `Raw_granule` objects when available. This is done by setting the argument `use_complementary_granules=True`. In this case, the compatibility of adjacent `Raw_granule` objects will be checked by the `coarse_coregistration(...)` API and use it in case it is available. +When filling `Raw_granule` objects are not available, missing pixels will be cropped if `crop_empty_pixels` is set to True. The superimposition of the coregistered bands with crop is shown in the image below ("coregistration with crop). + +```py +from pyraws.raw.raw_event import Raw_event + +#Instantiate an empty Raw_event +raw_event=Raw_event() + +#Bands to open. +bands_list=["B04", "B8A", "B11"] + +#Read "Etna_00" from THRAWS database. +#You can also read it by using raw_event.from_path(...). +raw_event.from_database( #Database ID_EVENT + id_event="Etna_00", + #Bands to open. Leave to None to use all the bands. + bands_list=bands_list, + #If True, verbose mode is on. + verbose=True, + #Database name + database="THRAWS") + +# Perform the corase coregistration of the "Etna_00" event. +# Missing pixels will be cropped. +raw_coreg_granule_0_with_fill=raw_event.coarse_coregistration(# granule index to coregister. + granules_idx=[2], + # Search for filling elements + # among adjacent Raw granules + use_complementary_granules=True, + # Cropping missing pixels + # when compatible Raw granules + # are not available + crop_empty_pixels=True) +``` +The superimposition of the coregistered bands with filling elements is shown in the image below ("coregistration with fill). + +![Alt Text](resources/images/coregistration.png) + +### How to get the coordinates of a Raw granule band +It is possible to get coordinates of the vertices of a `Raw_granule` object. Georeferencing is performed by using the information of the bands shift used to perform the [coarse coregistration](#coarse-coregistration) with respect to the band `B02` and by exploiting the coordinates of the [Raw granule](#sentinel-2-raw-granule) footprint (please, refer to [Sentinel-2 Products Specification Document](https://sentinel.esa.int/documents/247904/685211/sentinel-2-products-specification-document)). The code snippet below shows ho to get the information of the differnet bands of an [Raw granule](#sentinel-2-raw-granule). + +```py +from pyraws.raw.raw_event import Raw_event + +#Instantiate an empty Raw_event +raw_event=Raw_event() + +#Bands to open. +bands_list=["B04", "B8A", "B11"] + +#Read "Etna_00" from THRAWS database. +#You can also read it by using raw_event.from_path(...). +raw_event.from_database( #Database ID_EVENT + id_event="Etna_00", + #Bands to open. Leave to None to use all the bands. + bands_list=bands_list, + #If True, verbose mode is on. + verbose=True, + #Database name + database="THRAWS") + +#Read the granule 1 of the Etna_00 event. +raw_granule_1 = raw_event.get_granule(1) + +#Get bands coordinates +bands_coordinates_dict=raw_granule_1.get_bands_coordinates() +``` +The code snipped above returns a `bands_coordinates_dict`, a dictionary structured as `{band_name : [BOTTOM-LEFT(lat, lon), BOTTOM-RIGHT(lat, lon), TOP-RIGHT(lat, lon), TOP-LEFT(lat, lon)]}`. + +### Raw_event: database metadata +This example will show you how to extract database metadata associated to an [Raw event](#sentinel-2-raw-event). To run the next example it is necessary to have set up database how described in [databases compatible with PyRawS](#PyRawS-databases).
+Database metadata include: +* Event class (e.g., `eruption`, `fire`, `not_event`) +* List of [Raw useful granules](#raw-useful-granule) +* {Useful granule : Bounding box} dictionary + +```py +from pyraws.raw.raw_event import Raw_event + +#Instantiate an empty Raw_event +raw_event=Raw_event() + +#Bands to open. +bands_list=["B04", "B8A", "B11"] + +#Read "Etna_00" from THRAWS database. +#raw_event.from_path(...) cannot be used. + +raw_event.from_database( #Database ID_EVENT + id_event="Etna_00", + #Bands to open. Leave to None to use all the bands. + bands_list=bands_list, + #If True, verbose mode is on. + verbose=True, + #Database name + database="THRAWS") + +#Extract event class. +raw_event.get_event_class() + +#Extract indices of Raw useful granules +raw_event.get_useful_granules_idx() + +#Get {Useful granule : Bounding box} dictionary +raw_event.get_bounding_box_dict() +``` +### Export a Raw_granule to TIF +This example will shows how to export an `Raw_granule` to [TIF](https://en.wikipedia.org/wiki/TIFF) files. To this aim, you need to provide the path to a target directory, which will contain a TIF file for each band. + +```py +from pyraws.raw.raw_event import Raw_event + +#Instantiate an empty Raw_event +raw_event=Raw_event() + +#Bands to open. +bands_list=["B04", "B8A", "B11"] + +#Read "Etna_00" from THRAWS database. +#raw_event.from_path(...) cannot be used. + +raw_event.from_database( #Database ID_EVENT + id_event="Etna_00", + #Bands to open. Leave to None to use all the bands. + bands_list=bands_list, + #If True, verbose mode is on. + verbose=True, + #Database name + database="THRAWS") + +#Apply coarse coregistration to the Raw granule with index 0 and return it +raw_granule_0=raw_event.coarse_coregistration([0]) + +#Save folder path +output_tif_folder="raw_target_folder" + +#Export a TIF file for each band. +raw_granule_0.export_to_tif(save_path=output_tif_folder) +``` + +## Glossary +* ### Coarse coregistration + Lightweight spatial coregistration method optimized for onboard-satellite applications. It simply shifts the various bands of a fixed factor that depends only on the bands, the satellite and detector number. + +* ### Sentinel-2 L0 data + Sentinel-2 data at `level-0` (`L0`) are data that are transmitted to Ground from Sentinel-2 satellites. The `L0` format is compressed to diminish downlink bandwidth requirements. For more information, refer to the [Sentinel-2 Products Specification Document](https://sentinel.esa.int/documents/247904/685211/sentinel-2-products-specification-document) + +* ### Sentinel-2 Raw data + In the frame of this project, the [Sentinel-2 Raw](#sentinel-2-raw-data) represents a particular product in the Sentinel-2 processing chain that matches a decompressed version of [Sentinel-2 L0 data](sentinel-2-l0-data) with additional metadata that are produced on ground. Once decompressed, `Sentinel-2 Raw data` are the data available on Ground that better emulate the one produced by Sentinel-2 detectors with the exception of the effects due to compression and onboard equalization, which are not compensated at this stage. Therefore, `Sentinel-2 raw data` are those exploited in this project. For more information, refer to the [Sentinel-2 Products Specification Document](https://sentinel.esa.int/documents/247904/685211/sentinel-2-products-specification-document).
+**N.B**: the nomenclature ```raw data``` and its location in the Sentinel-2 processing chain is specific for this project only. + +* ### Sentinel-2 Raw granule + A `granule` is the image acquired by a Sentinel-2 detector during a single acquisition lasting 3.6 s. Granules are defined at [L0](#sentinel-2-raw-data) level. However, since the processing perfomed on the ground between L0 and raw data does not alter the image content (with the exception of the decompression process) but just provide additional metadata, granules are defined also at [Sentinel-2 Raw](#sentinel-2-raw-data) level. + Given the pushbroom nature of the Sentinel-2 sensor, bands do not look at the same area at [Raw](#sentinel-2-raw-data) level. For more information, refer to the [Sentinel-2 Products Specification Document](https://sentinel.esa.int/documents/247904/685211/sentinel-2-products-specification-document) + +* ### Sentinel-2 Raw event + [Sentinel-2 Raw data](#sentinel-2-raw-data) are produced by decompressing [Sentinel-2 L0 data](sentinel-2-raw-data). To download L0 data, it is necessary to specify one polygon that surrounds a particular area-of-interest. This leads to download all those [Sentinel-2 Raw granules](#sentinel-2-raw-granule) whose reference band intersects the specified polygon. Such collection is a `Raw-event`. Each `Raw-event` matches one of the `ID_event` entry of the database.
+ For each `Raw-event`, we do not provide all the collection of [Sentinel-2 Raw granules](#sentinel-2-Raw-granule), but only the set of [Raw data useful granules](#raw-data-useful-granule) and [Raw data complementary granules](#Raw-data-complementary-granule). For an intuitive example, please, check [Raw events and granules](#raw-events-and-raw-granules). + +* ### Sentinel-2 L1C data + The `Level 1-C` (`L1C`) is one format for `Sentinel-2` data. To convert [Sentinel-2 Raw data](#sentinel-2-raw-data) to `L1C` data, numerous processing steps are applied to correct defects, including bands coregistration, ortho-rectification, decompression, noise-suppression and other. For more information, refer to the [Sentinel-2 Products Specification Document](https://sentinel.esa.int/documents/247904/685211/sentinel-2-products-specification-document). + +* ### Sentinel-2 L1C event + Same concept for [Sentinel-2 Raw events](#sentinel-2-raw-event) but applied on [Sentinel-2 L1C data](#sentinel-2-l1c-data). + +* ### Sentinel-2 L1C tile + The `Sentinel-2 L1C tile` is the minimum `L1C` product that can be downloaded. + +* ### Raw complementary granule + Given a certain set of bands of interest `[Bx,By,...,Bz]`, `Raw complementarey granules` are the granules adjacents at [Raw-useful-granules](#raw-useful-granule) that that can be used to fill missing pixels of `[By,...,Bz]` bands due to their coregistration with respecto the band `Bx`. For an intuitive example, please, check [Raw events and granules](#raw-events-and-raw-granules). + +* ### Raw useful granule + Given a certain set of bands of interest `[Bx,By,...,Bz]`, where `Bx` is the first band in the set, an `Raw useful granule` is one of the collection of [Sentinel-2 Raw granules](#sentinel-2-raw-granule) that compose a [Sentinel-2 Raw event](#sentinel-2-raw-event) whose band `Bx` include (or intersects) a certain area of interest (e.g., an eruption or an area covered by a fire). For an intuitive example, please, check [Raw data events and granules](#raw-events-and-raw-granules). \ No newline at end of file diff --git a/README.md b/README.md index 947471f..ce6587b 100644 --- a/README.md +++ b/README.md @@ -4,16 +4,19 @@ ![GitHub issues](https://img.shields.io/github/issues/ESA-PhiLab/PyRawS?style=flat-square) ![GitHub pull requests](https://img.shields.io/github/issues-pr/ESA-PhiLab/PyRawS?style=flat-square) [![Tests](https://github.com/ESA-PhiLab/PyRawS/actions/workflows/run_tests.yml/badge.svg)](https://github.com/ESA-PhiLab/PyRawS/actions/workflows/run_tests.yml) - +![Python 3.8](https://img.shields.io/badge/python-3.8-blue.svg) +![Python 3.9](https://img.shields.io/badge/python-3.9-blue.svg) +![Python 3.10](https://img.shields.io/badge/python-3.10-blue.svg) +[![PyPI](https://img.shields.io/pypi/v/pyraws.svg)](https://pypi.org/project/pyraws/1.0.0/) # PyRawS -![Alt Text](resources/images/PyRawS_logo.png) +[![Py-Raw-S-logo.png](https://i.postimg.cc/7Yptgf5y/Py-Raw-S-logo.png)](https://postimg.cc/vctvy87P) ## About the project -`Python for RAW Sentinel2 data (PyRawS)` is a powerful open-source Python package that provides a comprehensive set of tools for working with [Sentinel-2 Raw data](#sentinel-2-raw-data)šŸ”¬. +`Python for RAW Sentinel2 data (PyRawS)` is a powerful open-source Python package that provides a comprehensive set of tools for working with [Sentinel-2 Raw data](#sentinel-2-raw-data). 1 -It provides utilities for coarse spatial bands coregistration, geo-referencing, data visualizationšŸ“Š, and image processingšŸ–¼ļø. -The software is demonstrated on the first Sentinel-2 šŸ›°ļø Raw database for warm temperature hotspots šŸ”„ detection/classification, making it an ideal tool for a wide range of applications in remote sensing and earth observationšŸŒ. -The package is written in Python and is open sourcešŸ’», making it easy to use and modify for your specific needs. -The systme is based on [pytorch]("https://pytorch.org/"), which be installed with `CUDA` support, to enable GPU acceleation. +It provides utilities for coarse spatial bands coregistration, geo-referencing, data visualization, and image processing. +The software is demonstrated on the first Sentinel-2 Raw database for warm temperature hotspots detection/classification, making it an ideal tool for a wide range of applications in remote sensing and earth observation. +The package is written in Python and is open source, making it easy to use and modify for your specific needs. +The systme is based on [pytorch]("https://pytorch.org/"), which be installed with `CUDA 11` support, to enable GPU acceleation. NB: What we call raw data in this project are Sentinel-2 data generated by the decompression and metadata addition of Sentinel-2 L0 data. Because of that, with the exception of the effects due to onboard equalization and lossy compression, they are the most similar version of the rawest form of data acquired by the satellite's sensors. Both the compression and equalization are applied onboard the satellite to reduce the amount of data transmitted to the ground station. For easy naming convention, this repo refer to the term "Raw" as the products decompressed with ancillary information appended. For further information browse our paper at https://arxiv.org/abs/2305.11891 @@ -21,615 +24,6 @@ NB: What we call raw data in this project are Sentinel-2 data generated by the d *(Disclaimer: This project is currently under development.)* - -
- Table of Contents -
    -
  1. About the Project
  2. -
  3. Content of the repository
  4. -
  5. Installation - -
  6. PyRawS databases
  7. -
  8. Raw events and Raw granules
  9. -
  10. Quickstart - -
  11. -
  12. Glossary
  13. -
  14. Contributing
  15. -
  16. License
  17. -
  18. Contacts
  19. -
-
- - -## Sentinel-2 Raw granules and events - -## Content of the repository -The PyRawS repository includes the following directories: - - -* **quickstart**: it contains some subdirectories including [jupyter notebooks](https://jupyter-notebook.readthedocs.io/en/stable/index.html): - 1. `API demonstration`: it contains a notebook to demonstrate PyRawS API. - 2. `DB_creation`: it contains a notebook to automatically create a database for a target dataset. - 3. `geographical_distribution`: it contains a notebook to diplay the geographical distribution of the events of a dataset into a map. - -* **PyRawS**: it contains the PyRawS package. The latter is made of the following subdirectories: - 1. `database`: it contains various [PyRawS database](#PyRawS-databases) and other databases. - 2. `raw`: it includes the `Raw_event` and `Raw_granule` classes used to model, respectively, [Sentinel-2 Raw events](#sentinel-2-raw-event) and [Sentinel-2 Raw granules](#sentinel-2-raw-granule). - 3. `l1`: it contains the `L1_event` and `L1_tiles` classes used to model, respectively, [Sentinel-2 L1C events](#sentinel-2-l1c-event) and [Sentinel-2 L1C tiles](#sentinel-2-l1c-tile). - 4. `utils`: it contains some utilities for the PYRAW package. - -* **resources**: it contains various resources (i.e., images for the README) -* **scripts_and_studies**: it contains various scripts and code for different studies realized to create the `THRAWS` dataset. In particular: - 1. `coregistration_study`: it contains utils used to perform the coregistration study and desing the [coarse coregistration](#coarse-coregistration) technique. - 2. `dataset_preparation`: it contains scripts and other files used to design the `THRAWS` files (i.e., download data, select events, and others). - 3. `hta_detection_algorithms`: it contains custom and simplified implementation of various high-thermal-anomalies-dection algorithms, including [1](#ref1) used to design the `THRAWS` dataset. - 4. `runscripts`: it contains some runscripts and utils to crop [Sentinel-2 L1C tiles](#sentinel-2-l1c-tile) and generate useful images and export tif. - 5. `granules_filtering`: it contains a script to run and [[1]](#ref1) on [cropped Sentinel-2 L1-C tiles](#sentinel-2-l1c-tile), extract bounding boxes and map them to the correspondent [Raw granules](#sentinel-2-raw-granule). - 6. `download_thraws`: it contains the utility for the download of the dataset [THRAWS](https://zenodo.org/record/7908728). - - - -## Installation -### Pre-requirements -Before all, clone this repository. We suggest using git from CLI, execute: - -``` git clone https://github.com/ESA-PhiLab/PyRawS ``` - - -### Create the PyRawS environment -#### - On Linux -``` -# For Linux, the installation is straightforward. -# You just need to run the following command from the main directory: - -\bin\bash\ source pyraws_install.sh - -# NB: Your data should be placed in the data directory in the main. -``` - -#### - On Other Os -``` -# To install the environment, we suggest to use anaconda. -# You can create a dedicated conda environment by using the `environment.yml` file by running the following command from the main directory: - -conda env create -f environment.yml - -# To activate your environment, please execute: - -conda activate PyRawS - -``` - -Create a file `sys_cfg.py` in the directory `pyraws\pyraws`, and add two variables as follows: - -``` PYRAWS_HOME_PATH="Absolute path to the main pyraws directory.``` - -``` DATA_PATH="Absolute path to the data directory. " ``` - -By default the data directory is located in PyRawS main directory. - - -### Docker - -To use PyRawS with docker, use one of the following methods. - - -#### Method 1: Pull the docker image from Docker Hub - -``` docker pull sirbastiano94/pyraws:latest ``` - -#### Method 2: Build docker image - -Follow these steps: - -1. Clone the repository and build the docker image by running the following command from the main directory: - -``` docker build -t pyraws:latest --build-arg CACHEBUST=$(date +%s) -f dockerfile . ``` - -2. Run the docker image by executing: - -``` docker run -it --rm -p 8888:8888 pyraws:latest ``` - - -### Set-up for coregistration study - -If you want to perform the coregistration study, you need to: - -* clone the repository [SuperGlue Inference and Evaluation Demo Script](https://github.com/magicleap/SuperGluePretrainedNetwork); -* rename the subdirectory `models` to `superglue_models`; -* move `superglue_models` into `coregistration_study`. - -Coregistration study results can be generated by using the `pyraws_coregistration_study.ipynb` notebook. The database `coregistration_study_db.csv` containing info on the discarded eruption events is used to generate results in the notebook. - -Coregistration notebook results can be generated by using the `pyraws_coregistration_profiling.ipynb` notebook. - -### Data directory - -All the data used by PyRawS need to be located in a directory called `data`, containing all the different datasets. You can place the `data` directory where you want and update the `DATA_PATH` variable in the `sys_cfg.py` file with its path (please, refer to: [Set-up for coregistration study](#set-up-for-coregistration-study)). -By default the data directory is located in PyRawS main directory. -
-To create a specific dataset, you need to create subfolder with the dataset name (e.g., `THRAWS`) in the `data` directory specific for your dataset. Such directory shall contain the following subdirectories: - -* `raw`: it will contain [decompressed raw](#sentinel-2-raw-data). -* `l1c`: it will contain [L1C](#sentinel-2-l1c-data). - -Every [raw data](#sentinel-2-decompressed-raw-data) and [L1C](#sentinel-2-l1c-data) data shall be contained in a specific subdirectory --placed in `raw`or `l1c`-- whose name shall match one of the **ID_event** entries of the **.csv** file, located in `database` directory. - -## PyRawS databases - -To create the "THRAWS" database, the user should refer to the notebook called "database_creation.ipynb". This notebook contains the necessary code and instructions for creating the database. Simply follow the steps outlined in the notebook to successfully create the "THRAWS" database. - -Please note that it is important to carefully follow the instructions in the notebook to ensure that the database is created correctly and without errors. Additionally, make sure that all required dependencies and packages are installed before running the code in the notebook. - -![Alt Text](resources/images/database_structure.png) - - -This respository contains an example of database (`THRAWS`) that is used by PyRawS to read and process [Sentinel-2 Raw data](#sentinel-2-raw-data) and [Sentinel-2 L1 data](#sentinel-2-l1-data) correctly. The minimal fields of the database include: - -* **ID_event**: ID of the event (e.g., volcanic-eruption, wildfire, not-event). All the other fields of the row are referred to that `Sentinel-2` acquisition. -* **class**: class of the event (e.g., eruption, fire, not-event). Leave it **empty** -* **Raw_useful_granules**: list of [Raw useful granules](#raw-useful-granule). Set to `None` or leave it empty if you do not know what are the [Raw useful granules](#raw-useful-granule). -* **Raw_complementary_granules**: list of [Raw complementry granules](#raw-complementary-granule). Set to `None` or leave it empty if you do not know what are the [Raw complementry granules](#raw-complementary-granule). -* **Raw_files**: list of [Raw granules](#sentinel-2-raw-granule) (**mandatory**). -* **l1c_files**: list of [L1 tiles](#sentinel-2-l1c-tile) (mandatory if you need L1C data). -* **bbox_list**: dictionary {[Raw useful granules](#raw-useful-granule) : [bounding box list for that granule]}. Set to `None` or leave it **empty** if you do not know the bounding box location. - -To create a new database (e.g., `my_database_name`), please, proceed as follows: - -1. Create a ".csv" file with the structure shown above and place it into the `database`subfloders (e.g., `my_db.csv`). You can use start from the [thraws_db.csv](https://github.com/ESA-PhiLab/PyRawS/-/blob/main/PyRawS/database/thraws_db.csv) database and edit it accordingly to your specification. -2. Create subdirectory `my_database_name` in the `data` subdirectory and populate it with the correspondent [Sentinel-2 Raw data](#sentinel-2-raw-data) and [Sentinel-2 L1 data](#sentinel-2-l1-data) as described in [Data directory](#data-directory). -3. Update the `DATABASE_FILE_DICTIONARY` in `PyRawS/utils/constants.py` as follows: - -```DATABASE_FILE_DICTIONARY={"THRAWS" : "thraws_db.csv", "my_database_name" : "my_db.csv"}``` - -Now, you should be able to use your new database.
-**N.B** The creation of a database is not mandatory. However, it is strongly advisable. Indeed, without creating a database you can still open `Raw data` as described in [Open a Raw event from path](#open-a-raw-event-from-path). However, some pieces of information such as the [Raw useful granules](#raw-useful-granule) associated to a specific event, the event bounding boxes or the image class can be retrieved only when the database is set-up. - -## Raw events and Raw granules -![Alt Text](resources/images/etna_00_granules.png) - -Downloading [Sentinel-2 Raw data](#sentinel-2-raw-data) requires to specify a polygon surrounding the area of interest and a date. Given the pushbroom nature of the [Sentinel-2](https://sentinel.esa.int/documents/247904/685211/sentinel-2-products-specification-document) sensor, bands of data at [Raw](#sentinel-2-raw-data) level do not look at the same area (i.e., they are not registered). Therefore,to be sure to collect all the band around an event (i.e., volcanic eruptions, wildfires) rectangular polygons centered on the events of area 28x10 $km^2$ are used (white rectangular in the image above). This leads to download all the [Raw granules](#sentinel-2-raw-granule) whose reference band (`B02`) interesects the polygon area.
The image above shows the footprint of the all the [Sentinel-2 Raw granules](#sentinel-2-raw-granule) that are downloaded for the eruption named "`Etna_00`" in our database by using the white rectangular polygon. We define the collection of [Raw granules](#sentinel-2-raw-granule) that are downloaded for each of the rows of our database "[Sentinel-2 Raw event](#Sentinel-2-RAW-event)".
However, as you can see in the image above, most of the [Sentinel-2 Raw granules](#sentinel-2-raw-granule) in `Etna_00` [Sentinel-2 Raw event](#Sentinel-2-RAW-event) do not contain the volcanic eruption (big red spot) of interest (red rectangulars). Indeed, only the yellow and the pink rectangulars intersects or include part of the volcanic eruption.
In addition, the fact that one [Raw granule](#sentinel-2-raw-granule) intersects or include one event, this does not mean that the latter interesects or is included in all the bands of that [Raw granule](#sentinel-2-raw-granule). In particular, -since we use the bands [`B8A`, `B11`, `B12`] to detect wildfires and volcanic eruptions, we consider [Raw useful granules](#raw-useful-granule) those granules whose band `B8A` interesects the event. This is true for the yellow rectangular but not for the pink one (you need to trust us here, since the bands are not displaced in the image above). We take the band `B8A` only because after the coregistration, the other bands will be moved to match the area of `B8A`.
-Finally, for some [Raw useful granules](#raw-useful-granule) part of the eruptions or the wildfire could extend until the top or the bottom edge of the polygon. In this case, some of the bands could be missing for a portion of the area of interest. To be sure that this is not happening, in addition to the [Raw useful granules](#raw-useful-granule), it is important to consider [Raw complementary granules](#raw-complementary-granule), which fills the missing part of the interest bands of the [Raw useful granules](#raw-useful-granule).
For each [Sentinel-2 Raw event](#Sentinel-2-RAW-event), the `THRAWS` dataset clearly states those [Raw granules](#sentinel-2-raw-granule) that are [Raw useful granules](#raw-useful-granule) or [Raw complementary granules](#raw-complementary-granule). However, the entire [Raw granules](#sentinel-2-raw-granule) collection is provided for each [Raw event](#sentinel-2-raw-event) to permit users that wants to use other bands to detect warm temeprature anomalies to do it. - - -## Quickstart -The next examples (with the exception of [Open a Raw event from path](#open-a-raw-event-from-path)) will exploit the `THRAWS` database to showcase the use of PyRawS, but they are applicable to any [databases compatible with PyRawS](#PyRawS-databases). - -### Open a Raw event from path -The next code snipped will showcase how to use PyRawS to open a [Raw_event](#sentinel-2-raw-event) `My_Raw_data`, included in the `THRAWS` database by using its `PATH`. We assume to have the `My_RAW_data` directory in the same directory where you execute the code snippet below.
-To manipulate [Raw events](#sentinel-2-raw-event), `PyRawS` offer a class called `Raw_event`. To open an avent, we will use the [Raw_event](#sentinel-2-raw-event) class method `from_path(...)`, which parses the database specified, retrieves the event specified by `id_event` and opens it with the requested bands (`bands_list`). -When you open an event, you can specify which bands to use. If `bands_list` is not specified, the method `from_path(...)` will return all the bands. - -```py -from pyraws.raw.raw_event import Raw_event -#Instantiate an empty Raw_event -raw_event=Raw_event() - -#Bands to open. -bands_list=["B8A", "B11", "B12"] - -#Read "Etna_00" from THRAWS -raw_event.from_path(#Path to the Etna_00 event - raw_dir_path="Path_to_my_RAW_data", - #Bands to open. Leave to None to use all the bands. - bands_list=bands_list, - #If True, verbose mode is on. - verbose=True) -``` -The example above can be used directly, **even if you did not set up a** [PyRawS database](#PyRawS-databases). However, `PyRawS` offer some API to parse directly [Raw_event](#sentinel-2-raw-event) parsing a database. with no need to specify a path. Please, check [Open a Raw event from database](#open-a-raw-event-from-database). - -### Open a Raw event from database -The next code snipped will showcase how to use PyRawS to open the [Raw_event](#sentinel-2-raw-event) `Etna_00` included in the `THRAWS` database.
To do that, -To manipulate [Raw events](#sentinel-2-raw-event) objects, `PyRawS` will exploits the `Raw_event` class method `from_database(...)`, which parses the associated `.csv` file located in `PyRawS/database` with no need to specify the `PATH` from the user. To execute the next code snipped, we assume to you have already downloaded and set-up the `THRAWS` database as specificied in [databases compatible with PyRawS](#PyRawS-databases). -As for the method `from_path(...)` described in [Open a Raw event from path](#open-an-raw-event-from-path), you can specify which bands to use. If `bands_list` is not specified, the method `from_database(...)` will return all the bands. - -```py -from pyraws.raw.raw_event import Raw_event -#Instantiate an empty Raw_event -raw_event=Raw_event() - -#Bands to open. -bands_list=["B8A", "B11", "B12"] - -#Read "Etna_00" from THRAWS -raw_event.from_database(#Database ID_EVENT - id_event="Etna_00", - #Bands to open. Leave to None to use all the bands. - bands_list=bands_list, - #If True, verbose mode is on. - verbose=True, - #Database name - database="THRAWS") -``` -All the next examples will assume you already have downloaded and set-up the `THRAWS` database as specificied in [databases compatible with PyRawS](#PyRawS-databases). However, they can work by using `from_path(...)` instead of `from_database(...)` and specifying the `PATH` to the `Etna_00` event manually. - -### Show Raw granules information of a Raw event -As specified in [Raw events and Raw granules](#raw-events-and-raw-granules), an [Raw event](#sentinel-2-raw-event) is a collection of [Raw granules](#sentinel-2-raw-granule). As for [Raw_event](#sentinel-2-raw-event), [Raw granules](#sentinel-2-raw-granule) are modelled in PyRawS through a dedicated class `Raw_granule`.
-The next code snippet will show how to get the information about the [Raw granules](#sentinel-2-raw-granule) that compose the `Etna_00` [Raw_event](#sentinel-2-raw-event). The class method `show_granules_info()` will print the list of events and some metada for each event. To get the same information as a dictionary `{granule name : granule info}` for an easy manipulation, you can use the `Raw_event` class method `get_granules_info(...)`. - -```py -from pyraws.raw.raw_event import Raw_event -#Instantiate an empty Raw_event -raw_event=Raw_event() - -#Bands to open. -bands_list=["B8A", "B11", "B12"] - -#Read "Etna_00" from THRAWS database. -#You can also read it by using raw_event.from_path(...). -raw_event.from_database( #Database ID_EVENT - id_event="Etna_00", - #Bands to open. Leave to None to use all the bands. - bands_list=bands_list, - #If True, verbose mode is on. - verbose=True, - #Database name - database="THRAWS") -# Printing granules info -raw_event.show_granules_info() - -#Getting Raw granules info dictionary {granule name : granule info} -granules_info_dict=raw_event.get_granules_info() -``` - -### Get a single Raw\_granule from a Raw\_event -The class `Raw_event` contains a list of objects `Raw_granule`, each one modelling a specific [Raw granule](#sentinel-2-raw-granule) that belongs to that [Raw_event](#sentinel-2-raw-event) (please, check [Raw events and Raw granules](#raw-events-and-raw-granules) for more information).
-The different `Raw_granule` objects are sorted alphabetically and are accessible through indices. The next code snippet will show how to get a specific [Raw granule](#sentinel-2-raw-granule) by using the `Raw_event` class method `get_granule(granule_idx)`, where `granule_idx` is the granule indices. The function returns an `Raw_granule` object. As for `Raw_event` objects, it is possible to print or retrieve metadata information for a spefic `Raw_granule` by using the `Raw_granule` methods `get_granule_info()` and `show_granule_info()`. - -```py -from pyraws.raw.raw_event import Raw_event -#Instantiate an empty Raw_event -raw_event=Raw_event() - -#Bands to open. -bands_list=["B8A", "B11", "B12"] - -#Read "Etna_00" from THRAWS database. -#You can also read it by using raw_event.from_path(...). -raw_event.from_database( #Database ID_EVENT - id_event="Etna_00", - #Bands to open. Leave to None to use all the bands. - bands_list=bands_list, - #If True, verbose mode is on. - verbose=True, - #Database name - database="THRAWS") - -#Read the granule 0 of the Etna_00 event. -raw_granule_0 = raw_event.get_granule(0) - -# Printing the info of the granule 0 -raw_granule_0.show_granule_info() - -#Getting Raw granules info dictionary {granule name : granule info} -granule_0_info_dict=raw_granule_0.get_granule_info() -``` - -### Access a Raw\_granule pixels -To visualize the values of an `Raw_data` object, it is possible to return it as a [PyTorch](https://pytorch.org/) tensor. However, since the different bands have different resolutions, depending on the bands that we want to shape as a tensor, it is necessary to upsample/downsample some of them to adapt them to the band with higher/smaller resolution. The next code snippet will open the `Etna_00` with bands `B02` (10 m), `B8A` (20 m), `B11` (20 m), get the granule with index 1, and will return the first two bands in the collection as tensor by performing upsample. - -```py -from pyraws.raw.raw_event import Raw_event -#Instantiate an empty Raw_event -raw_event=Raw_event() - -#Bands to open. -bands_list=["B04", "B8A", "B11"] - -#Read "Etna_00" from THRAWS database. -#You can also read it by using raw_event.from_path(...). -raw_event.from_database( #Database ID_EVENT - id_event="Etna_00", - #Bands to open. Leave to None to use all the bands. - bands_list=bands_list, - #If True, verbose mode is on. - verbose=True, - #Database name - database="THRAWS") - -#Read the granule 1 of the Etna_00 event. -raw_granule_1 = raw_event.get_granule(1) - -#Returning the bands B04 and B8A of raw_granule_1 as tensor by upsampling. -raw_granule_1_tensor=raw_granule_1.as_tensor(#list of bands to transform as tensor - requested_bands=["B04", "B8A"], - #Set to True to perform downsampling (default) - downsampling=False) -``` - -### Superimpose Raw\_granule bands -It is possible to superimpose `Raw_granule` bands by using the class method `show_bands_superimposition(...)`. (N.B. it is possible to superimpose up to three bands). -In case bands have different resolution, you need to specify if you want to superimpose them by performing downsampling (default) or upsampling. The next code snippet will open the `Etna_00` with bands `B02`, `B8A`, `B11`, `B12`, get the granule with index 0, and will superimpose the last three bands. - -```py -from pyraws.raw.raw_event import Raw_event -import matplotlib.pyplot as plt - -#Instantiate an empty Raw_event -raw_event=Raw_event() - -#Bands to open. -bands_list=["B04", "B8A", "B11", "B12"] - -#Read "Etna_00" from THRAWS database. -#You can also read it by using raw_event.from_path(...). -raw_event.from_database( #Database ID_EVENT - id_event="Etna_00", - #Bands to open. Leave to None to use all the bands. - bands_list=bands_list, - #If True, verbose mode is on. - verbose=True, - #Database name - database="THRAWS") - -#Read the granule 0 of the Etna_00 event. -raw_granule_0 = raw_event.get_granule(0) - -#Returning the bands B04 and B8A of raw_granule_1 as tensor by upsampling. -raw_granule_0.show_bands_superimposition(#Bands to superimpose - requested_bands=["B04", "B11", "B12"], - #Set to True to perform downsampling - downsampling=True) -plt.show() -``` - -The previous code snippet will display the image below. As you can see, the various bands of the image lack of coregistration of the various bands. - -![Alt Text](resources/images/granule_superimposition.png) - -### How to perform the coarse coregisteration of Raw\_granules -PyRawS offers some utils to perform [coarse coregistration](#coarse-coregistration) on `Raw_granule` objects. You can coregister a specific `Raw_granule` object of the `Raw_event` collection by calling the `coarse_coregistration(...)` method of the `Raw_event` class by selecting the correspondent index through the `granules_idx` input.
- -```py -from pyraws.raw.raw_event import Raw_event - -#Instantiate an empty Raw_event -raw_event=Raw_event() - -#Bands to open. -bands_list=["B04", "B8A", "B11"] - -#Read "Etna_00" from THRAWS database. -#You can also read it by using raw_event.from_path(...). -raw_event.from_database( #Database ID_EVENT - id_event="Etna_00", - #Bands to open. Leave to None to use all the bands. - bands_list=bands_list, - #If True, verbose mode is on. - verbose=True, - #Database name - database="THRAWS") - -# Perform the corase coregistration of the "Etna_00" event. -# Missing pixels will be filled with zeros. -raw_coreg_granule_2=raw_event.coarse_coregistration( # granule index to coregister. - granules_idx=[2]) -``` - -The previous code snippet returns the coarse coregistration of the granule 2 of the "Etna_00" event. The coarse coregistration is performed by shifting the bands `B8A` and `B11` with respect to the band `B04`, which is the first in the collection. The missing pixels produced by the shift of the bands `B8A` and `B11` will be filled by zeros. The superimposition of the coregistered bands with zero-filling is shown in the image below ("coregistration") -It is possible to launch crop the missing values by setting the argument `crop_empty_pixels=True`, as in the snippet below. - -```py -from pyraws.raw.raw_event import Raw_event - -#Instantiate an empty Raw_event -raw_event=Raw_event() - -#Bands to open. -bands_list=["B04", "B8A", "B11"] - -#Read "Etna_00" from THRAWS database. -#You can also read it by using raw_event.from_path(...). -raw_event.from_database( #Database ID_EVENT - id_event="Etna_00", - #Bands to open. Leave to None to use all the bands. - bands_list=bands_list, - #If True, verbose mode is on. - verbose=True, - #Database name - database="THRAWS") - -# Perform the corase coregistration of the "Etna_00" event. -# Missing pixels will be cropped. -raw_coreg_granule_0_with_crop=raw_event.coarse_coregistration(# granule index to coregister. - granules_idx=[2], - # Cropping missing pixels. - crop_empty_pixels=True) -``` - -Alternatively, you can fill the pixing pixels with filler elements taken from other `Raw_granule` objects when available. This is done by setting the argument `use_complementary_granules=True`. In this case, the compatibility of adjacent `Raw_granule` objects will be checked by the `coarse_coregistration(...)` API and use it in case it is available. -When filling `Raw_granule` objects are not available, missing pixels will be cropped if `crop_empty_pixels` is set to True. The superimposition of the coregistered bands with crop is shown in the image below ("coregistration with crop). - -```py -from pyraws.raw.raw_event import Raw_event - -#Instantiate an empty Raw_event -raw_event=Raw_event() - -#Bands to open. -bands_list=["B04", "B8A", "B11"] - -#Read "Etna_00" from THRAWS database. -#You can also read it by using raw_event.from_path(...). -raw_event.from_database( #Database ID_EVENT - id_event="Etna_00", - #Bands to open. Leave to None to use all the bands. - bands_list=bands_list, - #If True, verbose mode is on. - verbose=True, - #Database name - database="THRAWS") - -# Perform the corase coregistration of the "Etna_00" event. -# Missing pixels will be cropped. -raw_coreg_granule_0_with_fill=raw_event.coarse_coregistration(# granule index to coregister. - granules_idx=[2], - # Search for filling elements - # among adjacent Raw granules - use_complementary_granules=True, - # Cropping missing pixels - # when compatible Raw granules - # are not available - crop_empty_pixels=True) -``` -The superimposition of the coregistered bands with filling elements is shown in the image below ("coregistration with fill). - -![Alt Text](resources/images/coregistration.png) - -### How to get the coordinates of a Raw granule band -It is possible to get coordinates of the vertices of a `Raw_granule` object. Georeferencing is performed by using the information of the bands shift used to perform the [coarse coregistration](#coarse-coregistration) with respect to the band `B02` and by exploiting the coordinates of the [Raw granule](#sentinel-2-raw-granule) footprint (please, refer to [Sentinel-2 Products Specification Document](https://sentinel.esa.int/documents/247904/685211/sentinel-2-products-specification-document)). The code snippet below shows ho to get the information of the differnet bands of an [Raw granule](#sentinel-2-raw-granule). - -```py -from pyraws.raw.raw_event import Raw_event - -#Instantiate an empty Raw_event -raw_event=Raw_event() - -#Bands to open. -bands_list=["B04", "B8A", "B11"] - -#Read "Etna_00" from THRAWS database. -#You can also read it by using raw_event.from_path(...). -raw_event.from_database( #Database ID_EVENT - id_event="Etna_00", - #Bands to open. Leave to None to use all the bands. - bands_list=bands_list, - #If True, verbose mode is on. - verbose=True, - #Database name - database="THRAWS") - -#Read the granule 1 of the Etna_00 event. -raw_granule_1 = raw_event.get_granule(1) - -#Get bands coordinates -bands_coordinates_dict=raw_granule_1.get_bands_coordinates() -``` -The code snipped above returns a `bands_coordinates_dict`, a dictionary structured as `{band_name : [BOTTOM-LEFT(lat, lon), BOTTOM-RIGHT(lat, lon), TOP-RIGHT(lat, lon), TOP-LEFT(lat, lon)]}`. - -### Raw_event: database metadata -This example will show you how to extract database metadata associated to an [Raw event](#sentinel-2-raw-event). To run the next example it is necessary to have set up database how described in [databases compatible with PyRawS](#PyRawS-databases).
-Database metadata include: -* Event class (e.g., `eruption`, `fire`, `not_event`) -* List of [Raw useful granules](#raw-useful-granule) -* {Useful granule : Bounding box} dictionary - -```py -from pyraws.raw.raw_event import Raw_event - -#Instantiate an empty Raw_event -raw_event=Raw_event() - -#Bands to open. -bands_list=["B04", "B8A", "B11"] - -#Read "Etna_00" from THRAWS database. -#raw_event.from_path(...) cannot be used. - -raw_event.from_database( #Database ID_EVENT - id_event="Etna_00", - #Bands to open. Leave to None to use all the bands. - bands_list=bands_list, - #If True, verbose mode is on. - verbose=True, - #Database name - database="THRAWS") - -#Extract event class. -raw_event.get_event_class() - -#Extract indices of Raw useful granules -raw_event.get_useful_granules_idx() - -#Get {Useful granule : Bounding box} dictionary -raw_event.get_bounding_box_dict() -``` -### Export a Raw_granule to TIF -This example will shows how to export an `Raw_granule` to [TIF](https://en.wikipedia.org/wiki/TIFF) files. To this aim, you need to provide the path to a target directory, which will contain a TIF file for each band. - -```py -from pyraws.raw.raw_event import Raw_event - -#Instantiate an empty Raw_event -raw_event=Raw_event() - -#Bands to open. -bands_list=["B04", "B8A", "B11"] - -#Read "Etna_00" from THRAWS database. -#raw_event.from_path(...) cannot be used. - -raw_event.from_database( #Database ID_EVENT - id_event="Etna_00", - #Bands to open. Leave to None to use all the bands. - bands_list=bands_list, - #If True, verbose mode is on. - verbose=True, - #Database name - database="THRAWS") - -#Apply coarse coregistration to the Raw granule with index 0 and return it -raw_granule_0=raw_event.coarse_coregistration([0]) - -#Save folder path -output_tif_folder="raw_target_folder" - -#Export a TIF file for each band. -raw_granule_0.export_to_tif(save_path=output_tif_folder) -``` - -## Glossary -* ### Coarse coregistration - Lightweight spatial coregistration method optimized for onboard-satellite applications. It simply shifts the various bands of a fixed factor that depends only on the bands, the satellite and detector number. - -* ### Sentinel-2 L0 data - Sentinel-2 data at `level-0` (`L0`) are data that are transmitted to Ground from Sentinel-2 satellites. The `L0` format is compressed to diminish downlink bandwidth requirements. For more information, refer to the [Sentinel-2 Products Specification Document](https://sentinel.esa.int/documents/247904/685211/sentinel-2-products-specification-document) - -* ### Sentinel-2 Raw data - In the frame of this project, the [Sentinel-2 Raw](#sentinel-2-raw-data) represents a particular product in the Sentinel-2 processing chain that matches a decompressed version of [Sentinel-2 L0 data](sentinel-2-l0-data) with additional metadata that are produced on ground. Once decompressed, `Sentinel-2 Raw data` are the data available on Ground that better emulate the one produced by Sentinel-2 detectors with the exception of the effects due to compression and onboard equalization, which are not compensated at this stage. Therefore, `Sentinel-2 raw data` are those exploited in this project. For more information, refer to the [Sentinel-2 Products Specification Document](https://sentinel.esa.int/documents/247904/685211/sentinel-2-products-specification-document).
-**N.B**: the nomenclature ```raw data``` and its location in the Sentinel-2 processing chain is specific for this project only. - -* ### Sentinel-2 Raw granule - A `granule` is the image acquired by a Sentinel-2 detector during a single acquisition lasting 3.6 s. Granules are defined at [L0](#sentinel-2-raw-data) level. However, since the processing perfomed on the ground between L0 and raw data does not alter the image content (with the exception of the decompression process) but just provide additional metadata, granules are defined also at [Sentinel-2 Raw](#sentinel-2-raw-data) level. - Given the pushbroom nature of the Sentinel-2 sensor, bands do not look at the same area at [Raw](#sentinel-2-raw-data) level. For more information, refer to the [Sentinel-2 Products Specification Document](https://sentinel.esa.int/documents/247904/685211/sentinel-2-products-specification-document) - -* ### Sentinel-2 Raw event - [Sentinel-2 Raw data](#sentinel-2-raw-data) are produced by decompressing [Sentinel-2 L0 data](sentinel-2-raw-data). To download L0 data, it is necessary to specify one polygon that surrounds a particular area-of-interest. This leads to download all those [Sentinel-2 Raw granules](#sentinel-2-raw-granule) whose reference band intersects the specified polygon. Such collection is a `Raw-event`. Each `Raw-event` matches one of the `ID_event` entry of the database.
- For each `Raw-event`, we do not provide all the collection of [Sentinel-2 Raw granules](#sentinel-2-Raw-granule), but only the set of [Raw data useful granules](#raw-data-useful-granule) and [Raw data complementary granules](#Raw-data-complementary-granule). For an intuitive example, please, check [Raw events and granules](#raw-events-and-raw-granules). - -* ### Sentinel-2 L1C data - The `Level 1-C` (`L1C`) is one format for `Sentinel-2` data. To convert [Sentinel-2 Raw data](#sentinel-2-raw-data) to `L1C` data, numerous processing steps are applied to correct defects, including bands coregistration, ortho-rectification, decompression, noise-suppression and other. For more information, refer to the [Sentinel-2 Products Specification Document](https://sentinel.esa.int/documents/247904/685211/sentinel-2-products-specification-document). - -* ### Sentinel-2 L1C event - Same concept for [Sentinel-2 Raw events](#sentinel-2-raw-event) but applied on [Sentinel-2 L1C data](#sentinel-2-l1c-data). - -* ### Sentinel-2 L1C tile - The `Sentinel-2 L1C tile` is the minimum `L1C` product that can be downloaded. - -* ### Raw complementary granule - Given a certain set of bands of interest `[Bx,By,...,Bz]`, `Raw complementarey granules` are the granules adjacents at [Raw-useful-granules](#raw-useful-granule) that that can be used to fill missing pixels of `[By,...,Bz]` bands due to their coregistration with respecto the band `Bx`. For an intuitive example, please, check [Raw events and granules](#raw-events-and-raw-granules). - -* ### Raw useful granule - Given a certain set of bands of interest `[Bx,By,...,Bz]`, where `Bx` is the first band in the set, an `Raw useful granule` is one of the collection of [Sentinel-2 Raw granules](#sentinel-2-raw-granule) that compose a [Sentinel-2 Raw event](#sentinel-2-raw-event) whose band `Bx` include (or intersects) a certain area of interest (e.g., an eruption or an area covered by a fire). For an intuitive example, please, check [Raw data events and granules](#raw-events-and-raw-granules). ## Contributing The ```PyRawS``` project is open to contributions. To discuss new ideas and applications, please, reach us via email (please, refer to [Contacts](#contacts)). To report a bug or request a new feature, please, open an [issue](https://github.com/ESA-PhiLab/PyRawS/issues) to report a bug or to request a new feature. @@ -654,5 +48,4 @@ Created by the European Space Agency $\Phi$-[lab](https://phi.esa.int/). * Federico Serva - federico.serva at ext.esa.int ## References - ### Ref1 - [Massimetti, Francesco, et al. ""Volcanic hot-spot detection using SENTINEL-2: a comparison with MODISā€“MIROVA thermal data series."" Remote Sensing 12.5 (2020): 820."](https://www.mdpi.com/2072-4292/12/5/820) \ No newline at end of file + ### [1]: [Massimetti, Francesco, et al. ""Volcanic hot-spot detection using SENTINEL-2: a comparison with MODISā€“MIROVA thermal data series."" Remote Sensing 12.5 (2020): 820."](https://www.mdpi.com/2072-4292/12/5/820) \ No newline at end of file diff --git a/resources/.DS_Store b/resources/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..b9beb4436b284f80e9f77d18ac3713d034d19a86 GIT binary patch literal 6148 zcmeHK%}T>S5Z-NTn^J@x6nb3nTClYu7B3;z7cim+m70)HgK4%jtvQrJ&iX<=iO=KA z?&c5-coVTRu=~x<&u->}>(IS;VR6BNv&`I;w_2x;x4g&Ejg+xp z=$?NYh1s-wa4D0O7bW3RB}738ArE&^63EPv>m*23uB#nZ+iFj{z0GDg9{0s?biVD2 z&G=-{7pJ4M?Y3g-0lAlZ! literal 0 HcmV?d00001 diff --git a/setup.py b/setup.py index 4aa32bc..7c694c7 100644 --- a/setup.py +++ b/setup.py @@ -40,9 +40,10 @@ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "Intended Audience :: Science/Research", - "Topic :: Scientific/Engineering :: Computer Vision", + "Topic :: Scientific/Engineering :: GIS", "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", "Programming Language :: Python :: 3.8", + "Environment :: GPU :: NVIDIA CUDA :: 11.0", ], packages=["pyraws", "pyraws.database", "pyraws.raw", "pyraws.l1", "pyraws.utils"], python_requires=">=3.8, <4", From c54a65acc7b77c0609a455cda6fecdf6270f76a2 Mon Sep 17 00:00:00 2001 From: Macbook-pro Date: Sat, 5 Aug 2023 22:01:22 +0200 Subject: [PATCH 02/16] installing dependencies --- .github/workflows/pypi.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index d835161..06d568b 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -13,7 +13,6 @@ on: push: branches: [ "pypi" ] # CHANGE THIS. This workflow only runs when a commit is pushed to the pypi branch. - jobs: pypi-publish: name: Upload release to PyPI @@ -29,6 +28,11 @@ jobs: with: python-version: '3.8' + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install setuptools wheel + - name: Build Python package run: python setup.py bdist_wheel From e5e80380c1c16037cfbeab4780e6caa2fd33c79c Mon Sep 17 00:00:00 2001 From: Macbook-pro Date: Sat, 5 Aug 2023 22:06:15 +0200 Subject: [PATCH 03/16] correct repo url --- .github/workflows/pypi.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index 06d568b..6482204 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -41,4 +41,4 @@ jobs: with: user: sirbastiano94 password: ${{ secrets.PYPI_PASSWORD }} - repository-url: https://pypi.org/project/pyraws/1.0.0/ + repository-url: https://upload.pypi.org/legacy/ From 3c35b3db98408bc43f9a998a83a98331fcd6d0e8 Mon Sep 17 00:00:00 2001 From: Macbook-pro Date: Sat, 5 Aug 2023 22:16:16 +0200 Subject: [PATCH 04/16] versioning --- .github/update_version.py | 11 ++++++ .github/workflows/docker.yml | 1 - .github/workflows/pypi.yml | 67 +++++++++++++++++++++--------------- 3 files changed, 50 insertions(+), 29 deletions(-) create mode 100644 .github/update_version.py diff --git a/.github/update_version.py b/.github/update_version.py new file mode 100644 index 0000000..764ea2e --- /dev/null +++ b/.github/update_version.py @@ -0,0 +1,11 @@ +# .github/update_version.py +import sys +import re + +version = sys.argv[1] +with open('setup.py', 'r+') as f: + content = f.read() + content_new = re.sub(r'version=".*",', f'version="{version}",', content) + f.seek(0) + f.write(content_new) + f.truncate() \ No newline at end of file diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 150e248..7b853af 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -11,7 +11,6 @@ name: Build and Push Docker Image for PYRAWS on: push: - branches: [ "main" ] jobs: diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index 6482204..9335039 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -14,31 +14,42 @@ on: branches: [ "pypi" ] # CHANGE THIS. This workflow only runs when a commit is pushed to the pypi branch. jobs: - pypi-publish: - name: Upload release to PyPI - runs-on: ubuntu-latest - permissions: - id-token: write # IMPORTANT: this permission is mandatory for trusted publishing - steps: - - name: Check out code - uses: actions/checkout@v2 - - - name: Set up Python - uses: actions/setup-python@v2 - with: - python-version: '3.8' - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install setuptools wheel - - - name: Build Python package - run: python setup.py bdist_wheel - - - name: Publish package distributions to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 - with: - user: sirbastiano94 - password: ${{ secrets.PYPI_PASSWORD }} - repository-url: https://upload.pypi.org/legacy/ + pypi-publish: + name: Upload release to PyPI + runs-on: ubuntu-latest + permissions: + id-token: write # IMPORTANT: this permission is mandatory for trusted publishing + steps: + - name: Check out code + uses: actions/checkout@v2 + + - name: Bump version and push tag + id: create_tag + uses: anothrNick/github-tag-action@1.34.0 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + WITH_V: true + DEFAULT_BUMP: patch + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.8' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install setuptools wheel + + - name: Update setup.py version + run: python .github/update_version.py ${{ steps.create_tag.outputs.new_tag }} + + - name: Build Python package + run: python setup.py bdist_wheel + + - name: Publish package distributions to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + user: sirbastiano94 + password: ${{ secrets.PYPI_PASSWORD }} + repository-url: https://upload.pypi.org/legacy/ From b1e843e57df49f2113d2e849f57af0c2a2c48862 Mon Sep 17 00:00:00 2001 From: Macbook-pro Date: Sat, 5 Aug 2023 22:37:42 +0200 Subject: [PATCH 05/16] versioning test2 --- .github/update_version.py | 19 +++++++---- .github/workflows/pypi.yml | 70 +++++++++++++++++--------------------- 2 files changed, 44 insertions(+), 45 deletions(-) diff --git a/.github/update_version.py b/.github/update_version.py index 764ea2e..2aeeec4 100644 --- a/.github/update_version.py +++ b/.github/update_version.py @@ -1,11 +1,18 @@ # .github/update_version.py -import sys import re -version = sys.argv[1] +def increment_version(version): + major, minor, patch = map(int, version.split('.')) + patch += 1 + return f"{major}.{minor}.{patch}" + with open('setup.py', 'r+') as f: content = f.read() - content_new = re.sub(r'version=".*",', f'version="{version}",', content) - f.seek(0) - f.write(content_new) - f.truncate() \ No newline at end of file + version_match = re.search(r'version="(.*)",', content) + if version_match: + old_version = version_match.group(1) + new_version = increment_version(old_version) + content_new = re.sub(old_version, new_version, content) + f.seek(0) + f.write(content_new) + f.truncate() diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index 9335039..3650b9e 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -14,42 +14,34 @@ on: branches: [ "pypi" ] # CHANGE THIS. This workflow only runs when a commit is pushed to the pypi branch. jobs: - pypi-publish: - name: Upload release to PyPI - runs-on: ubuntu-latest - permissions: - id-token: write # IMPORTANT: this permission is mandatory for trusted publishing - steps: - - name: Check out code - uses: actions/checkout@v2 - - - name: Bump version and push tag - id: create_tag - uses: anothrNick/github-tag-action@1.34.0 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - WITH_V: true - DEFAULT_BUMP: patch - - - name: Set up Python - uses: actions/setup-python@v2 - with: - python-version: '3.8' - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install setuptools wheel - - - name: Update setup.py version - run: python .github/update_version.py ${{ steps.create_tag.outputs.new_tag }} - - - name: Build Python package - run: python setup.py bdist_wheel - - - name: Publish package distributions to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 - with: - user: sirbastiano94 - password: ${{ secrets.PYPI_PASSWORD }} - repository-url: https://upload.pypi.org/legacy/ + pypi-publish: + name: Upload release to PyPI + runs-on: ubuntu-latest + permissions: + id-token: write # IMPORTANT: this permission is mandatory for trusted publishing + steps: + - name: Check out code + uses: actions/checkout@v2 + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: '3.8' + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install setuptools wheel + + - name: Update setup.py version + run: python .github/update_version.py + + - name: Build Python package + run: python setup.py bdist_wheel + + - name: Publish package distributions to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + user: sirbastiano94 + password: ${{ secrets.PYPI_PASSWORD }} + repository-url: https://upload.pypi.org/legacy/ From 497ab682cee39f2a703fa8a28b306e9c8beccb99 Mon Sep 17 00:00:00 2001 From: Macbook-pro Date: Sat, 5 Aug 2023 22:40:09 +0200 Subject: [PATCH 06/16] black formatted --- .github/update_version.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/update_version.py b/.github/update_version.py index 2aeeec4..c6badaa 100644 --- a/.github/update_version.py +++ b/.github/update_version.py @@ -1,12 +1,14 @@ # .github/update_version.py import re + def increment_version(version): - major, minor, patch = map(int, version.split('.')) + major, minor, patch = map(int, version.split(".")) patch += 1 return f"{major}.{minor}.{patch}" -with open('setup.py', 'r+') as f: + +with open("setup.py", "r+") as f: content = f.read() version_match = re.search(r'version="(.*)",', content) if version_match: From 3679d4c4984f9c5a0f1db84b99dc800dfea52002 Mon Sep 17 00:00:00 2001 From: Macbook-pro Date: Sat, 5 Aug 2023 22:45:27 +0200 Subject: [PATCH 07/16] new version control --- .github/workflows/pypi.yml | 16 +++++++++++++--- setup.py | 2 +- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index 3650b9e..f4d31f4 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -12,6 +12,8 @@ name: Build and publish PyRawS distribution to PyPI on: push: branches: [ "pypi" ] # CHANGE THIS. This workflow only runs when a commit is pushed to the pypi branch. + paths-ignore: + - 'setup.py' jobs: pypi-publish: @@ -31,17 +33,25 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install setuptools wheel + pip install setuptools wheel twine - name: Update setup.py version run: python .github/update_version.py - + - name: Build Python package run: python setup.py bdist_wheel - + - name: Publish package distributions to PyPI uses: pypa/gh-action-pypi-publish@release/v1 with: user: sirbastiano94 password: ${{ secrets.PYPI_PASSWORD }} repository-url: https://upload.pypi.org/legacy/ + + - name: Commit and push changes + run: | + git config --global user.name sirbastiano + git config --global user.email 'robertodelprete88@.com' + git add setup.py + git commit -m 'Bump version' + git push diff --git a/setup.py b/setup.py index 7c694c7..458b76a 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ setup( name="pyraws", - version="1.0.0", + version="1.0.1", description="Python for RAW Sentinel2 data (PyRawS) is a powerful open-source Python package" + " that provides a comprehensive set of tools for working with Sentinel-2 Raw data. It provides utilities for" + " coarse spatial bands coregistration, geo-referencing, data visualization, and image processing.", From 4c1b7bbd4c5c60a0cecc0c2711a7450eafbdfdb5 Mon Sep 17 00:00:00 2001 From: Macbook-pro Date: Sat, 5 Aug 2023 22:49:18 +0200 Subject: [PATCH 08/16] add token write --- .github/workflows/pypi.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index f4d31f4..edbb08a 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -55,3 +55,5 @@ jobs: git add setup.py git commit -m 'Bump version' git push + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 1bdb56446b3734f887217f95188528e07ed8fbd7 Mon Sep 17 00:00:00 2001 From: Macbook-pro Date: Sat, 5 Aug 2023 22:51:40 +0200 Subject: [PATCH 09/16] test --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 458b76a..7c694c7 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ setup( name="pyraws", - version="1.0.1", + version="1.0.0", description="Python for RAW Sentinel2 data (PyRawS) is a powerful open-source Python package" + " that provides a comprehensive set of tools for working with Sentinel-2 Raw data. It provides utilities for" + " coarse spatial bands coregistration, geo-referencing, data visualization, and image processing.", From 324fd67b8779db2298423a9d7f3c36d850ea68e4 Mon Sep 17 00:00:00 2001 From: Macbook-pro Date: Sat, 5 Aug 2023 22:53:07 +0200 Subject: [PATCH 10/16] ok --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ce6587b..33c09fb 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ The software is demonstrated on the first Sentinel-2 Raw database for warm tempe The package is written in Python and is open source, making it easy to use and modify for your specific needs. The systme is based on [pytorch]("https://pytorch.org/"), which be installed with `CUDA 11` support, to enable GPU acceleation. +TEST 1 NB: What we call raw data in this project are Sentinel-2 data generated by the decompression and metadata addition of Sentinel-2 L0 data. Because of that, with the exception of the effects due to onboard equalization and lossy compression, they are the most similar version of the rawest form of data acquired by the satellite's sensors. Both the compression and equalization are applied onboard the satellite to reduce the amount of data transmitted to the ground station. For easy naming convention, this repo refer to the term "Raw" as the products decompressed with ancillary information appended. For further information browse our paper at https://arxiv.org/abs/2305.11891 From 0f13c0107c73d1bcf9437aa30fdf745bd35f838f Mon Sep 17 00:00:00 2001 From: Macbook-pro Date: Sat, 5 Aug 2023 22:55:40 +0200 Subject: [PATCH 11/16] test --- README.md | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 33c09fb..de5a9c2 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ The software is demonstrated on the first Sentinel-2 Raw database for warm tempe The package is written in Python and is open source, making it easy to use and modify for your specific needs. The systme is based on [pytorch]("https://pytorch.org/"), which be installed with `CUDA 11` support, to enable GPU acceleation. -TEST 1 +TEST 2 NB: What we call raw data in this project are Sentinel-2 data generated by the decompression and metadata addition of Sentinel-2 L0 data. Because of that, with the exception of the effects due to onboard equalization and lossy compression, they are the most similar version of the rawest form of data acquired by the satellite's sensors. Both the compression and equalization are applied onboard the satellite to reduce the amount of data transmitted to the ground station. For easy naming convention, this repo refer to the term "Raw" as the products decompressed with ancillary information appended. For further information browse our paper at https://arxiv.org/abs/2305.11891 diff --git a/setup.py b/setup.py index 7c694c7..71f156b 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ setup( name="pyraws", - version="1.0.0", + version="1.0.4", description="Python for RAW Sentinel2 data (PyRawS) is a powerful open-source Python package" + " that provides a comprehensive set of tools for working with Sentinel-2 Raw data. It provides utilities for" + " coarse spatial bands coregistration, geo-referencing, data visualization, and image processing.", From 2d1bc35fc22d5b00e2b4c39d1428140d98c62f5d Mon Sep 17 00:00:00 2001 From: Macbook-pro Date: Sat, 5 Aug 2023 23:04:01 +0200 Subject: [PATCH 12/16] removed versioning --- .github/update_version.py | 20 -------------------- .github/workflows/pypi.yml | 17 ++--------------- 2 files changed, 2 insertions(+), 35 deletions(-) delete mode 100644 .github/update_version.py diff --git a/.github/update_version.py b/.github/update_version.py deleted file mode 100644 index c6badaa..0000000 --- a/.github/update_version.py +++ /dev/null @@ -1,20 +0,0 @@ -# .github/update_version.py -import re - - -def increment_version(version): - major, minor, patch = map(int, version.split(".")) - patch += 1 - return f"{major}.{minor}.{patch}" - - -with open("setup.py", "r+") as f: - content = f.read() - version_match = re.search(r'version="(.*)",', content) - if version_match: - old_version = version_match.group(1) - new_version = increment_version(old_version) - content_new = re.sub(old_version, new_version, content) - f.seek(0) - f.write(content_new) - f.truncate() diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index edbb08a..255fd84 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -11,7 +11,7 @@ name: Build and publish PyRawS distribution to PyPI on: push: - branches: [ "pypi" ] # CHANGE THIS. This workflow only runs when a commit is pushed to the pypi branch. + branches: [ "pypi" ] paths-ignore: - 'setup.py' @@ -33,10 +33,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install setuptools wheel twine - - - name: Update setup.py version - run: python .github/update_version.py + pip install setuptools wheel - name: Build Python package run: python setup.py bdist_wheel @@ -47,13 +44,3 @@ jobs: user: sirbastiano94 password: ${{ secrets.PYPI_PASSWORD }} repository-url: https://upload.pypi.org/legacy/ - - - name: Commit and push changes - run: | - git config --global user.name sirbastiano - git config --global user.email 'robertodelprete88@.com' - git add setup.py - git commit -m 'Bump version' - git push - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 4de54095d7c7f4c7c63ea1ef3120559165a80e8d Mon Sep 17 00:00:00 2001 From: Macbook-pro Date: Sat, 5 Aug 2023 23:11:26 +0200 Subject: [PATCH 13/16] first version --- .github/workflows/pypi.yml | 6 ++---- setup.py | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index 255fd84..92a6fc5 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -10,10 +10,8 @@ name: Build and publish PyRawS distribution to PyPI on: - push: - branches: [ "pypi" ] - paths-ignore: - - 'setup.py' + release: + types: [created] jobs: pypi-publish: diff --git a/setup.py b/setup.py index 71f156b..827dd2e 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ setup( name="pyraws", - version="1.0.4", + version="0.0.1", description="Python for RAW Sentinel2 data (PyRawS) is a powerful open-source Python package" + " that provides a comprehensive set of tools for working with Sentinel-2 Raw data. It provides utilities for" + " coarse spatial bands coregistration, geo-referencing, data visualization, and image processing.", From 72712f78558d62c688d660ded8ffdfb58ad8818d Mon Sep 17 00:00:00 2001 From: Macbook-pro Date: Sat, 5 Aug 2023 23:23:08 +0200 Subject: [PATCH 14/16] change the CI/CD on release trigger --- README.md | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index de5a9c2..6a21290 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ ![Python 3.8](https://img.shields.io/badge/python-3.8-blue.svg) ![Python 3.9](https://img.shields.io/badge/python-3.9-blue.svg) ![Python 3.10](https://img.shields.io/badge/python-3.10-blue.svg) -[![PyPI](https://img.shields.io/pypi/v/pyraws.svg)](https://pypi.org/project/pyraws/1.0.0/) +[![PyPI](https://img.shields.io/pypi/v/pyraws.svg)](https://pypi.org/project/pyraws/) # PyRawS [![Py-Raw-S-logo.png](https://i.postimg.cc/7Yptgf5y/Py-Raw-S-logo.png)](https://postimg.cc/vctvy87P) ## About the project diff --git a/setup.py b/setup.py index 827dd2e..38f48e2 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ setup( name="pyraws", - version="0.0.1", + version="v0.0.2", description="Python for RAW Sentinel2 data (PyRawS) is a powerful open-source Python package" + " that provides a comprehensive set of tools for working with Sentinel-2 Raw data. It provides utilities for" + " coarse spatial bands coregistration, geo-referencing, data visualization, and image processing.", From 6570440216733baffd429e2d6f05ce1b6f504b45 Mon Sep 17 00:00:00 2001 From: Macbook-pro Date: Sat, 5 Aug 2023 23:42:24 +0200 Subject: [PATCH 15/16] change version to 0.0.03 --- .gitignore | 3 ++- README.md | 1 - setup.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index f533eba..906a9d3 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ scripts_and_studies/Test/ scripts_and_studies/coregistration_study/superglue_models pyraws/sys_config.py dist -build \ No newline at end of file +build +myRunscripts \ No newline at end of file diff --git a/README.md b/README.md index 6a21290..390511d 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,6 @@ The software is demonstrated on the first Sentinel-2 Raw database for warm tempe The package is written in Python and is open source, making it easy to use and modify for your specific needs. The systme is based on [pytorch]("https://pytorch.org/"), which be installed with `CUDA 11` support, to enable GPU acceleation. -TEST 2 NB: What we call raw data in this project are Sentinel-2 data generated by the decompression and metadata addition of Sentinel-2 L0 data. Because of that, with the exception of the effects due to onboard equalization and lossy compression, they are the most similar version of the rawest form of data acquired by the satellite's sensors. Both the compression and equalization are applied onboard the satellite to reduce the amount of data transmitted to the ground station. For easy naming convention, this repo refer to the term "Raw" as the products decompressed with ancillary information appended. For further information browse our paper at https://arxiv.org/abs/2305.11891 diff --git a/setup.py b/setup.py index 38f48e2..c4db0da 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ setup( name="pyraws", - version="v0.0.2", + version="v0.0.3", description="Python for RAW Sentinel2 data (PyRawS) is a powerful open-source Python package" + " that provides a comprehensive set of tools for working with Sentinel-2 Raw data. It provides utilities for" + " coarse spatial bands coregistration, geo-referencing, data visualization, and image processing.", From 9ca5eb8e22e6cfd534d4f434319f99fd3e1cf371 Mon Sep 17 00:00:00 2001 From: Roberto Del Prete <71963566+sirbastiano@users.noreply.github.com> Date: Sun, 6 Aug 2023 22:27:16 +0200 Subject: [PATCH 16/16] Update README.md Update badge --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 390511d..bdc3fac 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,10 @@ ![Python 3.9](https://img.shields.io/badge/python-3.9-blue.svg) ![Python 3.10](https://img.shields.io/badge/python-3.10-blue.svg) [![PyPI](https://img.shields.io/pypi/v/pyraws.svg)](https://pypi.org/project/pyraws/) +[![Docs](https://img.shields.io/badge/Docs-GitHub%20Pages-blue)](https://esa-philab.github.io/PyRawS/) + + + # PyRawS [![Py-Raw-S-logo.png](https://i.postimg.cc/7Yptgf5y/Py-Raw-S-logo.png)](https://postimg.cc/vctvy87P) ## About the project @@ -48,4 +52,4 @@ Created by the European Space Agency $\Phi$-[lab](https://phi.esa.int/). * Federico Serva - federico.serva at ext.esa.int ## References - ### [1]: [Massimetti, Francesco, et al. ""Volcanic hot-spot detection using SENTINEL-2: a comparison with MODISā€“MIROVA thermal data series."" Remote Sensing 12.5 (2020): 820."](https://www.mdpi.com/2072-4292/12/5/820) \ No newline at end of file + ### [1]: [Massimetti, Francesco, et al. ""Volcanic hot-spot detection using SENTINEL-2: a comparison with MODISā€“MIROVA thermal data series."" Remote Sensing 12.5 (2020): 820."](https://www.mdpi.com/2072-4292/12/5/820)