├── tests
├── __init__.py
├── data
│ ├── __init__.py
│ ├── L5_2020-01-01
│ │ ├── __init__.py
│ │ ├── L5_B1.tif
│ │ ├── L5_B2.tif
│ │ ├── L5_B3.tif
│ │ ├── L5_B4.tif
│ │ ├── L5_B5.tif
│ │ └── L5_B7.tif
│ ├── L8_2020-01-01
│ │ ├── __init__.py
│ │ ├── L8_B1.tif
│ │ ├── L8_B10.tif
│ │ ├── L8_B2.tif
│ │ ├── L8_B3.tif
│ │ ├── L8_B4.tif
│ │ ├── L8_B5.tif
│ │ ├── L8_B6.tif
│ │ └── L8_B7.tif
│ ├── S2_2020-01-01
│ │ ├── __init__.py
│ │ ├── S2_B01.tif
│ │ ├── S2_B02.tif
│ │ ├── S2_B03.tif
│ │ ├── S2_B04.tif
│ │ ├── S2_B05.tif
│ │ ├── S2_B06.tif
│ │ ├── S2_B07.tif
│ │ ├── S2_B08.tif
│ │ ├── S2_B09.tif
│ │ ├── S2_B11.tif
│ │ ├── S2_B12.tif
│ │ └── S2_B8A.tif
│ ├── S2_2020-01-02
│ │ ├── __init__.py
│ │ ├── S2_B02.tif
│ │ ├── S2_B03.tif
│ │ └── S2_B04.tif
│ ├── S2_2020-01-03
│ │ ├── __init__.py
│ │ ├── S2_B02.tif
│ │ ├── S2_B03.tif
│ │ └── S2_B04.tif
│ ├── S2_2020-01-04
│ │ ├── __init__.py
│ │ ├── S2_B02.tif
│ │ ├── S2_B03.tif
│ │ └── S2_B04.tif
│ ├── files
│ │ ├── reclass.csv
│ │ ├── spectral_signature_2.csv
│ │ ├── roi.gpkg
│ │ ├── file1.dbf
│ │ ├── spectral_signature_1.csv
│ │ ├── file1.csv
│ │ ├── file2.csv
│ │ ├── landsat_5_metadata_mtl.xml
│ │ ├── sentinel_2_metadata_test_l2a.xml
│ │ ├── sentinel_2_metadata_test_l1c.xml
│ │ └── landsat_8_metadata_mtl.xml
│ └── S2_2020-01-05
│ │ └── S2_2020-01-05.tif
├── test_log.py
├── test_temporary.py
├── test_plot_tools.py
├── test_files_directories.py
├── test_raster_label.py
├── test_band_erosion.py
├── test_output_manager.py
├── test_raster_to_vector.py
├── test_vector_to_raster.py
├── run_tests.py
├── test_band_sieve.py
├── test_download_tools.py
├── test_band_neighbor_pixels.py
├── test_band_stack_split.py
├── test_band_resample.py
├── test_raster_report.py
├── test_band_dilation.py
├── test_band_clustering.py
├── test_raster_edit.py
├── test_band_mask.py
├── test_raster_zonal_stats.py
├── test_band_pca.py
├── test_raster_reclassification.py
├── test_raster_vector.py
├── test_progress.py
├── test_band_spectral_distance.py
├── test_cross_classification.py
├── test_band_clip.py
├── test_band_mosaic.py
├── test_preprocess_products.py
├── test_processor.py
├── test_band_combination.py
└── test_table_manager.py
├── src
└── remotior_sensus
│ ├── core
│ ├── __init__.py
│ ├── messages.py
│ ├── temporary.py
│ ├── output_manager.py
│ └── log.py
│ ├── tools
│ ├── __init__.py
│ ├── band_stack.py
│ ├── raster_to_vector.py
│ ├── raster_split.py
│ ├── band_sieve.py
│ ├── band_dilation.py
│ └── band_erosion.py
│ ├── util
│ ├── __init__.py
│ ├── system_tools.py
│ ├── dates_times.py
│ ├── read_write_files.py
│ └── plot_tools.py
│ └── __init__.py
├── requirements_readthedocs.txt
├── docs
├── source
│ ├── _static
│ │ ├── html_css.css
│ │ ├── logo.png
│ │ ├── bandset.jpg
│ │ ├── favicon.ico
│ │ ├── fromGIStoRS.png
│ │ └── processing.jpg
│ ├── modules.rst
│ ├── api.rst
│ ├── api_core.rst
│ ├── api_tools.rst
│ ├── remotior_sensus.core.log.rst
│ ├── remotior_sensus.core.session.rst
│ ├── remotior_sensus.tools.mosaic.rst
│ ├── remotior_sensus.core.messages.rst
│ ├── remotior_sensus.core.progress.rst
│ ├── remotior_sensus.core.processor.rst
│ ├── remotior_sensus.core.temporary.rst
│ ├── remotior_sensus.tools.band_pca.rst
│ ├── tutorials.rst
│ ├── remotior_sensus.tools.band_calc.rst
│ ├── remotior_sensus.tools.band_clip.rst
│ ├── remotior_sensus.tools.band_mask.rst
│ ├── remotior_sensus.util.plot_tools.rst
│ ├── remotior_sensus.tools.band_sieve.rst
│ ├── remotior_sensus.tools.band_stack.rst
│ ├── remotior_sensus.util.dates_times.rst
│ ├── remotior_sensus.util.shared_tools.rst
│ ├── remotior_sensus.util.system_tools.rst
│ ├── remotior_sensus.core.table_manager.rst
│ ├── remotior_sensus.tools.band_erosion.rst
│ ├── remotior_sensus.tools.raster_label.rst
│ ├── remotior_sensus.tools.raster_split.rst
│ ├── remotior_sensus.util.pytorch_tools.rst
│ ├── remotior_sensus.util.raster_vector.rst
│ ├── remotior_sensus.core.configurations.rst
│ ├── remotior_sensus.core.output_manager.rst
│ ├── remotior_sensus.tools.band_dilation.rst
│ ├── remotior_sensus.tools.band_resample.rst
│ ├── remotior_sensus.tools.raster_report.rst
│ ├── remotior_sensus.util.download_tools.rst
│ ├── remotior_sensus.core.bandset_catalog.rst
│ ├── remotior_sensus.tools.raster_edit.rst
│ ├── remotior_sensus.tools.band_clustering.rst
│ ├── remotior_sensus.tools.band_combination.rst
│ ├── remotior_sensus.util.files_directories.rst
│ ├── remotior_sensus.util.read_write_files.rst
│ ├── remotior_sensus.tools.download_products.rst
│ ├── remotior_sensus.tools.raster_to_vector.rst
│ ├── remotior_sensus.tools.vector_to_raster.rst
│ ├── remotior_sensus.core.processor_functions.rst
│ ├── remotior_sensus.core.spectral_signatures.rst
│ ├── remotior_sensus.core.multiprocess_manager.rst
│ ├── remotior_sensus.tools.band_classification.rst
│ ├── remotior_sensus.tools.preprocess_products.rst
│ ├── remotior_sensus.tools.raster_zonal_stats.rst
│ ├── basic_tutorials.rst
│ ├── remotior_sensus.tools.band_neighbor_pixels.rst
│ ├── remotior_sensus.tools.cross_classification.rst
│ ├── remotior_sensus.tools.band_spectral_distance.rst
│ ├── remotior_sensus.tools.raster_reclassification.rst
│ ├── remotior_sensus.rst
│ ├── tutorial_create_sentinel2_jpg.rst
│ ├── tutorial_ndvi.rst
│ ├── quickstart.rst
│ ├── tutorial_random_forest.rst
│ ├── remotior_sensus.util.rst
│ ├── remotior_sensus.core.rst
│ ├── remotior_sensus.tools.rst
│ ├── installation.rst
│ ├── index.rst
│ ├── conf.py
│ ├── changelog.rst
│ └── introduction.rst
├── Makefile
└── make.bat
├── environment.yml
├── environment_readthedocs.yml
├── .readthedocs.yaml
├── LICENSE
├── pyproject.toml
├── .github
└── workflows
│ └── publish-to-pypi.yml
├── .gitignore
└── README.rst
/tests/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/data/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/remotior_sensus/core/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/remotior_sensus/tools/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/remotior_sensus/util/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/data/L5_2020-01-01/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/data/L8_2020-01-01/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/data/S2_2020-01-01/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/data/S2_2020-01-02/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/data/S2_2020-01-03/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tests/data/S2_2020-01-04/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/requirements_readthedocs.txt:
--------------------------------------------------------------------------------
1 | sphinx_rtd_theme==1.3.0
2 |
--------------------------------------------------------------------------------
/docs/source/_static/html_css.css:
--------------------------------------------------------------------------------
1 | .wy-nav-content {max-width: 100%}
--------------------------------------------------------------------------------
/tests/data/files/reclass.csv:
--------------------------------------------------------------------------------
1 | 1, 1
2 | 425, 425
3 | 500, Null
4 | raster > 500, 2000
--------------------------------------------------------------------------------
/tests/data/files/spectral_signature_2.csv:
--------------------------------------------------------------------------------
1 | 0.1, 0.49
2 | 0.21, 0.6
3 | 0.38, 0.66
4 | 0.16, 0.7
--------------------------------------------------------------------------------
/tests/data/files/roi.gpkg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/files/roi.gpkg
--------------------------------------------------------------------------------
/tests/data/files/file1.dbf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/files/file1.dbf
--------------------------------------------------------------------------------
/docs/source/_static/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/docs/source/_static/logo.png
--------------------------------------------------------------------------------
/tests/data/files/spectral_signature_1.csv:
--------------------------------------------------------------------------------
1 | 0.2, 0.49, 0.02
2 | 0.31, 0.56, 0.02
3 | 0.18, 0.665, 0.02
4 | 0.16, 0.705, 0.02
--------------------------------------------------------------------------------
/docs/source/_static/bandset.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/docs/source/_static/bandset.jpg
--------------------------------------------------------------------------------
/docs/source/_static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/docs/source/_static/favicon.ico
--------------------------------------------------------------------------------
/docs/source/modules.rst:
--------------------------------------------------------------------------------
1 | remotior_sensus
2 | ===============
3 |
4 | .. toctree::
5 | :maxdepth: 4
6 |
7 | remotior_sensus
8 |
--------------------------------------------------------------------------------
/docs/source/_static/fromGIStoRS.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/docs/source/_static/fromGIStoRS.png
--------------------------------------------------------------------------------
/docs/source/_static/processing.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/docs/source/_static/processing.jpg
--------------------------------------------------------------------------------
/tests/data/L5_2020-01-01/L5_B1.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/L5_2020-01-01/L5_B1.tif
--------------------------------------------------------------------------------
/tests/data/L5_2020-01-01/L5_B2.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/L5_2020-01-01/L5_B2.tif
--------------------------------------------------------------------------------
/tests/data/L5_2020-01-01/L5_B3.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/L5_2020-01-01/L5_B3.tif
--------------------------------------------------------------------------------
/tests/data/L5_2020-01-01/L5_B4.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/L5_2020-01-01/L5_B4.tif
--------------------------------------------------------------------------------
/tests/data/L5_2020-01-01/L5_B5.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/L5_2020-01-01/L5_B5.tif
--------------------------------------------------------------------------------
/tests/data/L5_2020-01-01/L5_B7.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/L5_2020-01-01/L5_B7.tif
--------------------------------------------------------------------------------
/tests/data/L8_2020-01-01/L8_B1.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/L8_2020-01-01/L8_B1.tif
--------------------------------------------------------------------------------
/tests/data/L8_2020-01-01/L8_B10.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/L8_2020-01-01/L8_B10.tif
--------------------------------------------------------------------------------
/tests/data/L8_2020-01-01/L8_B2.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/L8_2020-01-01/L8_B2.tif
--------------------------------------------------------------------------------
/tests/data/L8_2020-01-01/L8_B3.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/L8_2020-01-01/L8_B3.tif
--------------------------------------------------------------------------------
/tests/data/L8_2020-01-01/L8_B4.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/L8_2020-01-01/L8_B4.tif
--------------------------------------------------------------------------------
/tests/data/L8_2020-01-01/L8_B5.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/L8_2020-01-01/L8_B5.tif
--------------------------------------------------------------------------------
/tests/data/L8_2020-01-01/L8_B6.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/L8_2020-01-01/L8_B6.tif
--------------------------------------------------------------------------------
/tests/data/L8_2020-01-01/L8_B7.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/L8_2020-01-01/L8_B7.tif
--------------------------------------------------------------------------------
/tests/data/S2_2020-01-01/S2_B01.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/S2_2020-01-01/S2_B01.tif
--------------------------------------------------------------------------------
/tests/data/S2_2020-01-01/S2_B02.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/S2_2020-01-01/S2_B02.tif
--------------------------------------------------------------------------------
/tests/data/S2_2020-01-01/S2_B03.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/S2_2020-01-01/S2_B03.tif
--------------------------------------------------------------------------------
/tests/data/S2_2020-01-01/S2_B04.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/S2_2020-01-01/S2_B04.tif
--------------------------------------------------------------------------------
/tests/data/S2_2020-01-01/S2_B05.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/S2_2020-01-01/S2_B05.tif
--------------------------------------------------------------------------------
/tests/data/S2_2020-01-01/S2_B06.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/S2_2020-01-01/S2_B06.tif
--------------------------------------------------------------------------------
/tests/data/S2_2020-01-01/S2_B07.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/S2_2020-01-01/S2_B07.tif
--------------------------------------------------------------------------------
/tests/data/S2_2020-01-01/S2_B08.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/S2_2020-01-01/S2_B08.tif
--------------------------------------------------------------------------------
/tests/data/S2_2020-01-01/S2_B09.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/S2_2020-01-01/S2_B09.tif
--------------------------------------------------------------------------------
/tests/data/S2_2020-01-01/S2_B11.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/S2_2020-01-01/S2_B11.tif
--------------------------------------------------------------------------------
/tests/data/S2_2020-01-01/S2_B12.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/S2_2020-01-01/S2_B12.tif
--------------------------------------------------------------------------------
/tests/data/S2_2020-01-01/S2_B8A.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/S2_2020-01-01/S2_B8A.tif
--------------------------------------------------------------------------------
/tests/data/S2_2020-01-02/S2_B02.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/S2_2020-01-02/S2_B02.tif
--------------------------------------------------------------------------------
/tests/data/S2_2020-01-02/S2_B03.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/S2_2020-01-02/S2_B03.tif
--------------------------------------------------------------------------------
/tests/data/S2_2020-01-02/S2_B04.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/S2_2020-01-02/S2_B04.tif
--------------------------------------------------------------------------------
/tests/data/S2_2020-01-03/S2_B02.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/S2_2020-01-03/S2_B02.tif
--------------------------------------------------------------------------------
/tests/data/S2_2020-01-03/S2_B03.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/S2_2020-01-03/S2_B03.tif
--------------------------------------------------------------------------------
/tests/data/S2_2020-01-03/S2_B04.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/S2_2020-01-03/S2_B04.tif
--------------------------------------------------------------------------------
/tests/data/S2_2020-01-04/S2_B02.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/S2_2020-01-04/S2_B02.tif
--------------------------------------------------------------------------------
/tests/data/S2_2020-01-04/S2_B03.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/S2_2020-01-04/S2_B03.tif
--------------------------------------------------------------------------------
/tests/data/S2_2020-01-04/S2_B04.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/S2_2020-01-04/S2_B04.tif
--------------------------------------------------------------------------------
/tests/data/S2_2020-01-05/S2_2020-01-05.tif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/semiautomaticgit/remotior_sensus/HEAD/tests/data/S2_2020-01-05/S2_2020-01-05.tif
--------------------------------------------------------------------------------
/docs/source/api.rst:
--------------------------------------------------------------------------------
1 | API Reference
2 | ===========================================
3 |
4 |
5 | .. toctree::
6 | :maxdepth: 1
7 |
8 | remotior_sensus.rst
9 |
--------------------------------------------------------------------------------
/environment.yml:
--------------------------------------------------------------------------------
1 | name: remotior_sensus
2 | channels:
3 | - conda-forge
4 | - defaults
5 | dependencies:
6 | - python=3.10
7 | - numpy
8 | - scipy
9 | - scikit-learn
10 | - gdal
11 | - pytorch
--------------------------------------------------------------------------------
/docs/source/api_core.rst:
--------------------------------------------------------------------------------
1 | Core Modules
2 | ===========================================
3 |
4 | The following are the core modules.
5 |
6 | .. toctree::
7 | :maxdepth: 3
8 |
9 | remotior_sensus.core.rst
10 |
--------------------------------------------------------------------------------
/docs/source/api_tools.rst:
--------------------------------------------------------------------------------
1 | Tools
2 | ===========================================
3 |
4 | The following are the available tools.
5 |
6 | .. toctree::
7 | :maxdepth: 3
8 |
9 | remotior_sensus.tools.rst
10 |
--------------------------------------------------------------------------------
/environment_readthedocs.yml:
--------------------------------------------------------------------------------
1 | name: remotior_sensus
2 | channels:
3 | - conda-forge
4 | - defaults
5 | dependencies:
6 | - python=3.10
7 | - numpy
8 | - scipy
9 | - gdal
10 | - sphinx_rtd_theme
11 |
--------------------------------------------------------------------------------
/tests/data/files/file1.csv:
--------------------------------------------------------------------------------
1 | id,main,field1,field2,field3,name
2 | 1,101,0,0,1281,a
3 | 2,101,0,1,811,a
4 | 3,101,0,2,181,a
5 | 4,102,1,0,26,c
6 | 5,102,1,1,110,c
7 | 6,102,1,2,170,c
8 | 7,103,2,0,843,b
9 | 9,105,2,0,843,t
--------------------------------------------------------------------------------
/tests/data/files/file2.csv:
--------------------------------------------------------------------------------
1 | id,value,field1,field2,field3,name
2 | 1,101,0,0,100,d
3 | 2,101,0,1,400,d
4 | 3,101,0,2,600,e
5 | 4,102,1,0,200,d
6 | 5,102,1,1,100,d
7 | 6,102,1,2,200,e
8 | 7,103,2,0,300,e
9 | 8,105,2,0,300,f
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.core.log.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.core.log module
2 | ================================
3 |
4 | .. automodule:: remotior_sensus.core.log
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.core.session.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.core.session module
2 | ====================================
3 |
4 | .. automodule:: remotior_sensus.core.session
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.tools.mosaic.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.tools.mosaic module
2 | ====================================
3 |
4 | .. automodule:: remotior_sensus.tools.mosaic
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.core.messages.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.core.messages module
2 | =====================================
3 |
4 | .. automodule:: remotior_sensus.core.messages
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.core.progress.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.core.progress module
2 | =====================================
3 |
4 | .. automodule:: remotior_sensus.core.progress
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.core.processor.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.core.processor module
2 | ======================================
3 |
4 | .. automodule:: remotior_sensus.core.processor
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.core.temporary.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.core.temporary module
2 | ======================================
3 |
4 | .. automodule:: remotior_sensus.core.temporary
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.tools.band_pca.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.tools.band\_pca module
2 | =======================================
3 |
4 | .. automodule:: remotior_sensus.tools.band_pca
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/tutorials.rst:
--------------------------------------------------------------------------------
1 | Tutorials
2 | ===========================================
3 |
4 | The following tutorials are available.
5 |
6 |
7 | .. toctree::
8 | :maxdepth: 1
9 | :titlesonly:
10 |
11 | tutorial_create_sentinel2_jpg.rst
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.tools.band_calc.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.tools.band\_calc module
2 | ========================================
3 |
4 | .. automodule:: remotior_sensus.tools.band_calc
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.tools.band_clip.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.tools.band\_clip module
2 | ========================================
3 |
4 | .. automodule:: remotior_sensus.tools.band_clip
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.tools.band_mask.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.tools.band\_mask module
2 | ========================================
3 |
4 | .. automodule:: remotior_sensus.tools.band_mask
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.util.plot_tools.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.util.plot\_tools module
2 | ========================================
3 |
4 | .. automodule:: remotior_sensus.util.plot_tools
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.tools.band_sieve.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.tools.band\_sieve module
2 | =========================================
3 |
4 | .. automodule:: remotior_sensus.tools.band_sieve
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.tools.band_stack.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.tools.band\_stack module
2 | =========================================
3 |
4 | .. automodule:: remotior_sensus.tools.band_stack
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.util.dates_times.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.util.dates\_times module
2 | =========================================
3 |
4 | .. automodule:: remotior_sensus.util.dates_times
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.util.shared_tools.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.util.shared\_tools module
2 | ==========================================
3 |
4 | .. automodule:: remotior_sensus.util.shared_tools
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.util.system_tools.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.util.system\_tools module
2 | ==========================================
3 |
4 | .. automodule:: remotior_sensus.util.system_tools
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.core.table_manager.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.core.table\_manager module
2 | ===========================================
3 |
4 | .. automodule:: remotior_sensus.core.table_manager
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.tools.band_erosion.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.tools.band\_erosion module
2 | ===========================================
3 |
4 | .. automodule:: remotior_sensus.tools.band_erosion
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.tools.raster_label.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.tools.raster\_label module
2 | ===========================================
3 |
4 | .. automodule:: remotior_sensus.tools.raster_label
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.tools.raster_split.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.tools.raster\_split module
2 | ===========================================
3 |
4 | .. automodule:: remotior_sensus.tools.raster_split
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.util.pytorch_tools.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.util.pytorch\_tools module
2 | ===========================================
3 |
4 | .. automodule:: remotior_sensus.util.pytorch_tools
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.util.raster_vector.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.util.raster\_vector module
2 | ===========================================
3 |
4 | .. automodule:: remotior_sensus.util.raster_vector
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.core.configurations.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.core.configurations module
2 | ===========================================
3 |
4 | .. automodule:: remotior_sensus.core.configurations
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.core.output_manager.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.core.output\_manager module
2 | ============================================
3 |
4 | .. automodule:: remotior_sensus.core.output_manager
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.tools.band_dilation.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.tools.band\_dilation module
2 | ============================================
3 |
4 | .. automodule:: remotior_sensus.tools.band_dilation
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.tools.band_resample.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.tools.band\_resample module
2 | ============================================
3 |
4 | .. automodule:: remotior_sensus.tools.band_resample
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.tools.raster_report.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.tools.raster\_report module
2 | ============================================
3 |
4 | .. automodule:: remotior_sensus.tools.raster_report
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.util.download_tools.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.util.download\_tools module
2 | ============================================
3 |
4 | .. automodule:: remotior_sensus.util.download_tools
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.core.bandset_catalog.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.core.bandset\_catalog module
2 | =============================================
3 |
4 | .. automodule:: remotior_sensus.core.bandset_catalog
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.tools.raster_edit.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.tools.raster\_edit module
2 | ======================================================
3 |
4 | .. automodule:: remotior_sensus.tools.raster_edit
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.tools.band_clustering.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.tools.band\_clustering module
2 | ==============================================
3 |
4 | .. automodule:: remotior_sensus.tools.band_clustering
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.tools.band_combination.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.tools.band\_combination module
2 | ===============================================
3 |
4 | .. automodule:: remotior_sensus.tools.band_combination
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.util.files_directories.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.util.files\_directories module
2 | ===============================================
3 |
4 | .. automodule:: remotior_sensus.util.files_directories
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.util.read_write_files.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.util.read\_write\_files module
2 | ===============================================
3 |
4 | .. automodule:: remotior_sensus.util.read_write_files
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.tools.download_products.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.tools.download\_products module
2 | ================================================
3 |
4 | .. automodule:: remotior_sensus.tools.download_products
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.tools.raster_to_vector.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.tools.raster\_to\_vector module
2 | ================================================
3 |
4 | .. automodule:: remotior_sensus.tools.raster_to_vector
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.tools.vector_to_raster.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.tools.vector\_to\_raster module
2 | ================================================
3 |
4 | .. automodule:: remotior_sensus.tools.vector_to_raster
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.core.processor_functions.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.core.processor\_functions module
2 | =================================================
3 |
4 | .. automodule:: remotior_sensus.core.processor_functions
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.core.spectral_signatures.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.core.spectral\_signatures module
2 | =================================================
3 |
4 | .. automodule:: remotior_sensus.core.spectral_signatures
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.core.multiprocess_manager.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.core.multiprocess\_manager module
2 | ==================================================
3 |
4 | .. automodule:: remotior_sensus.core.multiprocess_manager
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.tools.band_classification.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.tools.band\_classification module
2 | ==================================================
3 |
4 | .. automodule:: remotior_sensus.tools.band_classification
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.tools.preprocess_products.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.tools.preprocess\_products module
2 | ==================================================
3 |
4 | .. automodule:: remotior_sensus.tools.preprocess_products
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.tools.raster_zonal_stats.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.tools.raster\_zonal\_stats module
2 | ===================================================
3 |
4 | .. automodule:: remotior_sensus.tools.raster_zonal_stats
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/basic_tutorials.rst:
--------------------------------------------------------------------------------
1 | Basic Tutorials
2 | ===========================================
3 |
4 | The following tutorials are available.
5 |
6 |
7 | .. toctree::
8 | :maxdepth: 1
9 | :titlesonly:
10 |
11 | quickstart.rst
12 | tutorial_ndvi.rst
13 | tutorial_random_forest.rst
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.tools.band_neighbor_pixels.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.tools.band\_neighbor\_pixels module
2 | ====================================================
3 |
4 | .. automodule:: remotior_sensus.tools.band_neighbor_pixels
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.tools.cross_classification.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.tools.cross\_classification module
2 | ===================================================
3 |
4 | .. automodule:: remotior_sensus.tools.cross_classification
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.tools.band_spectral_distance.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.tools.band\_spectral\_distance module
2 | =======================================================
3 |
4 | .. automodule:: remotior_sensus.tools.band_spectral_distance
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.tools.raster_reclassification.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.tools.raster\_reclassification module
2 | ======================================================
3 |
4 | .. automodule:: remotior_sensus.tools.raster_reclassification
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/.readthedocs.yaml:
--------------------------------------------------------------------------------
1 | version: 2
2 |
3 | build:
4 | os: ubuntu-22.04
5 | tools:
6 | python: "mambaforge-22.9"
7 |
8 | sphinx:
9 | configuration: docs/source/conf.py
10 |
11 | conda:
12 | environment: environment_readthedocs.yml
13 |
14 | formats:
15 | - pdf
16 |
17 | python:
18 | install:
19 | - requirements: requirements_readthedocs.txt
20 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus package
2 | ========================
3 |
4 | Subpackages
5 | -----------
6 |
7 | .. toctree::
8 | :maxdepth: 4
9 |
10 | remotior_sensus.core
11 | remotior_sensus.tools
12 |
13 |
14 | Module contents
15 | ---------------
16 |
17 | .. automodule:: remotior_sensus
18 | :members:
19 | :undoc-members:
20 | :show-inheritance:
21 |
--------------------------------------------------------------------------------
/docs/source/tutorial_create_sentinel2_jpg.rst:
--------------------------------------------------------------------------------
1 | Create Sentinel-2 jpg file
2 | ===========================================
3 |
4 | .. raw:: html
5 |
6 |
7 |
8 | Link to the guide:
9 | https://colab.research.google.com/gist/semiautomaticgit/0eb0a3e0e9794b66f162a46455b8a00d/create_sentinel2_jpg.ipynb
--------------------------------------------------------------------------------
/docs/source/tutorial_ndvi.rst:
--------------------------------------------------------------------------------
1 | Download Sentinel-2 Data and Calculate NDVI
2 | ===========================================
3 |
4 | .. raw:: html
5 |
6 |
7 |
8 | Link to the guide:
9 | https://colab.research.google.com/gist/semiautomaticgit/e20479e1cbfbf76f078bfb4f211f23fa/download_sentinel-2_data_and_calculate_ndvi.ipynb
10 |
--------------------------------------------------------------------------------
/tests/test_log.py:
--------------------------------------------------------------------------------
1 | from unittest import TestCase
2 |
3 | import remotior_sensus
4 |
5 |
6 | class TestLog(TestCase):
7 |
8 | def test_create(self):
9 | rs = remotior_sensus.Session(
10 | n_processes=2, available_ram=1000, log_level=10
11 | )
12 | cfg = rs.configurations
13 | cfg.logger.log.debug('>>> test logger file path')
14 | self.assertTrue(rs.files_directories.is_file(cfg.logger.file_path))
15 |
16 | # clear temporary directory
17 | rs.close()
18 |
--------------------------------------------------------------------------------
/tests/test_temporary.py:
--------------------------------------------------------------------------------
1 | from unittest import TestCase
2 |
3 | import remotior_sensus
4 |
5 |
6 | class TestTemporary(TestCase):
7 |
8 | def test_create_root_temporary_directory(self):
9 | rs = remotior_sensus.Session(
10 | n_processes=2, available_ram=1000, log_level=10
11 | )
12 | cfg = rs.configurations
13 | cfg.logger.log.debug('>>> test temp directory')
14 | self.assertTrue(rs.files_directories.is_directory(cfg.temp.dir))
15 |
16 | # clear temporary directory
17 | rs.close()
18 |
--------------------------------------------------------------------------------
/docs/source/quickstart.rst:
--------------------------------------------------------------------------------
1 | Quickstart
2 | ===========================================
3 |
4 | Following the video of the tutorial.
5 |
6 | https://www.youtube.com/watch?v=uv264j_oclU
7 |
8 | .. raw:: html
9 |
10 |
11 |
12 |
13 | .. raw:: html
14 |
15 |
16 |
17 | Link to the guide:
18 | https://colab.research.google.com/gist/semiautomaticgit/0fdb7c2c5c0b3b990cf342d226b8ee43/quickstart.ipynb
19 |
--------------------------------------------------------------------------------
/docs/source/tutorial_random_forest.rst:
--------------------------------------------------------------------------------
1 | Random Forest Classification
2 | ===========================================
3 |
4 | Following the video of the tutorial.
5 |
6 | https://www.youtube.com/watch?v=Rc61lSWOgt4
7 |
8 | .. raw:: html
9 |
10 |
11 |
12 |
13 | .. raw:: html
14 |
15 |
16 |
17 | Link to the guide:
18 | https://colab.research.google.com/gist/semiautomaticgit/5b3c6dca89b3764a69cf083cf3d0674f/random_forest_classification.ipynb
19 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (C) 2022-2025 Luca Congedo.
2 |
3 | Remotior Sensus is free software: you can redistribute it and/or modify it
4 | under the terms of the GNU General Public License as published by
5 | the Free Software Foundation, either version 3 of the License,
6 | or (at your option) any later version.
7 | Remotior Sensus is distributed in the hope that it will be useful,
8 | but WITHOUT ANY WARRANTY; without even the implied warranty
9 | of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10 | See the GNU General Public License for more details.
11 | You should have received a copy of the GNU General Public License
12 | along with Remotior Sensus. If not, see .
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line, and also
5 | # from the environment for the first two.
6 | SPHINXOPTS ?=
7 | SPHINXBUILD ?= sphinx-build
8 | SOURCEDIR = source
9 | BUILDDIR = build
10 |
11 | # Put it first so that "make" without argument is like "make help".
12 | help:
13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14 |
15 | .PHONY: help Makefile
16 |
17 | # Catch-all target: route all unknown targets to Sphinx using the new
18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19 | %: Makefile
20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
21 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.util.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.util package
2 | =============================
3 |
4 | Submodules
5 | ----------
6 |
7 | .. toctree::
8 | :maxdepth: 4
9 |
10 | remotior_sensus.util.dates_times
11 | remotior_sensus.util.download_tools
12 | remotior_sensus.util.files_directories
13 | remotior_sensus.util.plot_tools
14 | remotior_sensus.util.pytorch_tools
15 | remotior_sensus.util.raster_vector
16 | remotior_sensus.util.read_write_files
17 | remotior_sensus.util.shared_tools
18 | remotior_sensus.util.system_tools
19 |
20 | Module contents
21 | ---------------
22 |
23 | .. automodule:: remotior_sensus.util
24 | :members:
25 | :undoc-members:
26 | :show-inheritance:
27 |
--------------------------------------------------------------------------------
/tests/test_plot_tools.py:
--------------------------------------------------------------------------------
1 | from unittest import TestCase
2 |
3 | from remotior_sensus.util import plot_tools
4 |
5 |
6 | class TestPlotTools(TestCase):
7 |
8 | def test_plot(self):
9 | pass
10 | """
11 | ax = plot_tools.prepare_plot()
12 | plots, plot_names, x_ticks, y_ticks, v_lines = (
13 | plot_tools.add_lines_to_plot(
14 | name_list=['test1', 'test2'],
15 | wavelength_list=[[0.4, 0.5, 0.6], [0.3, 0.5, 0.7]],
16 | value_list=[[0.7, 0.4, 0.9], [1.1, 1.3, 1.2]],
17 | color_list=['red', 'blue'])
18 | )
19 | plot_tools.create_plot(
20 | ax=ax, plots=plots, plot_names=plot_names, x_ticks=x_ticks,
21 | y_ticks=y_ticks, v_lines=v_lines
22 | )
23 | """
24 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.core.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.core package
2 | =============================
3 |
4 | Submodules
5 | ----------
6 |
7 | .. toctree::
8 | :maxdepth: 4
9 |
10 | remotior_sensus.core.bandset_catalog
11 | remotior_sensus.core.configurations
12 | remotior_sensus.core.log
13 | remotior_sensus.core.messages
14 | remotior_sensus.core.multiprocess_manager
15 | remotior_sensus.core.output_manager
16 | remotior_sensus.core.processor
17 | remotior_sensus.core.processor_functions
18 | remotior_sensus.core.progress
19 | remotior_sensus.core.session
20 | remotior_sensus.core.spectral_signatures
21 | remotior_sensus.core.table_manager
22 | remotior_sensus.core.temporary
23 |
24 | Module contents
25 | ---------------
26 |
27 | .. automodule:: remotior_sensus.core
28 | :members:
29 | :undoc-members:
30 | :show-inheritance:
31 |
--------------------------------------------------------------------------------
/tests/test_files_directories.py:
--------------------------------------------------------------------------------
1 | from unittest import TestCase
2 |
3 | import remotior_sensus
4 |
5 |
6 | class TestFilesDirectories(TestCase):
7 |
8 | def test_files_directories(self):
9 | rs = remotior_sensus.Session(
10 | n_processes=2, available_ram=1000, log_level=10
11 | )
12 | cfg = rs.configurations
13 | cfg.logger.log.debug('>>> test files directories')
14 | path = '/home/user/file.tif'
15 | root = '/home/user/'
16 | relative_path = rs.files_directories.absolute_to_relative_path(
17 | path=path, root=root
18 | )
19 | absolute_path = rs.files_directories.relative_to_absolute_path(
20 | path=relative_path, root=root
21 | )
22 | self.assertEqual(absolute_path, path)
23 |
24 | # clear temporary directory
25 | rs.close()
26 |
--------------------------------------------------------------------------------
/tests/test_raster_label.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 | from unittest import TestCase
3 |
4 | import remotior_sensus
5 |
6 |
7 | class TestRasterLabel(TestCase):
8 |
9 | def test_raster_label(self):
10 | rs = remotior_sensus.Session(
11 | n_processes=2, available_ram=1000, log_level=10
12 | )
13 | cfg = rs.configurations
14 | data_path = Path(__file__).parent / 'data'
15 | p = str(data_path / 'S2_2020-01-02' / 'S2_B02.tif')
16 | cfg.logger.log.debug('>>> test raster label')
17 | temp = cfg.temp.temporary_file_path(name_suffix=cfg.vrt_suffix)
18 | label = rs.raster_label(raster_path=p, output_path=temp,
19 | virtual_output=True)
20 | self.assertTrue(rs.files_directories.is_file(label.path))
21 |
22 | # clear temporary directory
23 | rs.close()
24 |
--------------------------------------------------------------------------------
/docs/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=sphinx-build
9 | )
10 | set SOURCEDIR=source
11 | set BUILDDIR=build
12 |
13 | if "%1" == "" goto help
14 |
15 | %SPHINXBUILD% >NUL 2>NUL
16 | if errorlevel 9009 (
17 | echo.
18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
19 | echo.installed, then set the SPHINXBUILD environment variable to point
20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
21 | echo.may add the Sphinx directory to PATH.
22 | echo.
23 | echo.If you don't have Sphinx installed, grab it from
24 | echo.http://sphinx-doc.org/
25 | exit /b 1
26 | )
27 |
28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
29 | goto end
30 |
31 | :help
32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
33 |
34 | :end
35 | popd
36 |
--------------------------------------------------------------------------------
/tests/test_band_erosion.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 | from unittest import TestCase
3 |
4 | import remotior_sensus
5 |
6 |
7 | class TestBandErosion(TestCase):
8 |
9 | def test_band_erosion(self):
10 | rs = remotior_sensus.Session(
11 | n_processes=2, available_ram=1000, log_level=10
12 | )
13 | cfg = rs.configurations
14 | data_path = Path(__file__).parent / 'data'
15 | file_list = [
16 | str(data_path / 'S2_2020-01-01' / 'S2_B02.tif'),
17 | str(data_path / 'S2_2020-01-01' / 'S2_B03.tif')
18 | ]
19 | cfg.logger.log.debug('>>> test band_erosion')
20 | erosion = rs.band_erosion(
21 | input_bands=file_list, output_path=cfg.temp.dir,
22 | value_list=[1, 425], size=1, circular_structure=True,
23 | prefix='erosion_'
24 | )
25 | self.assertTrue(rs.files_directories.is_file(erosion.paths[0]))
26 |
27 | # clear temporary directory
28 | rs.close()
29 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [build-system]
2 | requires = ["hatchling"]
3 | build-backend = "hatchling.build"
4 |
5 | [project]
6 | name = "remotior_sensus"
7 | dynamic = ["version"]
8 | authors = [
9 | { name="Luca Congedo", email="ing.congedoluca@gmail.com" },
10 | ]
11 | description = "Remotior Sensus is software to process remote sensing and GIS data"
12 | readme = "README.rst"
13 | requires-python = ">=3.8"
14 | classifiers = [
15 | "Programming Language :: Python :: 3",
16 | "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
17 | "Operating System :: OS Independent",
18 | "Topic :: Scientific/Engineering :: GIS",
19 | "Topic :: Scientific/Engineering :: Image Processing",
20 | ]
21 |
22 | [project.urls]
23 | "Homepage" = "https://github.com/semiautomaticgit/remotior_sensus"
24 | "Bug Tracker" = "https://github.com/semiautomaticgit/remotior_sensus/issues"
25 |
26 | [tool.hatch.version]
27 | path = "src/remotior_sensus/__init__.py"
28 |
29 | [tool.hatch.build]
30 | exclude = [
31 | "*.idea",
32 | "*.git",
33 | "*build",
34 | ]
--------------------------------------------------------------------------------
/tests/test_output_manager.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 | from unittest import TestCase
3 |
4 | import remotior_sensus
5 |
6 |
7 | class TestOutputManager(TestCase):
8 |
9 | def test_output_manager(self):
10 | rs = remotior_sensus.Session(
11 | n_processes=2, available_ram=1000, log_level=10
12 | )
13 | cfg = rs.configurations
14 | data_path = Path(__file__).parent / 'data'
15 | path = str(data_path / 'S2_2020-01-01' / 'S2_B02.tif')
16 | cfg.logger.log.debug('>>> test output manager')
17 | output = rs.output_manager(path=path)
18 | self.assertEqual(output.path, path)
19 | # create BandSet Catalog
20 | catalog = rs.bandset_catalog()
21 | cfg.logger.log.debug('>>> test add to bandset')
22 | # add to BandSet 1
23 | output.add_to_bandset(
24 | bandset_catalog=catalog, bandset_number=1, band_number=1
25 | )
26 | self.assertEqual(catalog.get_bandset(1).get_band(1).path, path)
27 |
28 | # clear temporary directory
29 | rs.close()
30 |
--------------------------------------------------------------------------------
/tests/test_raster_to_vector.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 | from unittest import TestCase
3 |
4 | import remotior_sensus
5 |
6 |
7 | class TestRasterToVector(TestCase):
8 |
9 | def test_raster_to_vector(self):
10 | rs = remotior_sensus.Session(
11 | n_processes=2, available_ram=1000, log_level=10
12 | )
13 | cfg = rs.configurations
14 | data_path = Path(__file__).parent / 'data'
15 | p = str(data_path / 'S2_2020-01-01' / 'S2_B02.tif')
16 | temp = cfg.temp.temporary_file_path(name_suffix=cfg.gpkg_suffix)
17 | cfg.logger.log.debug('>>> test raster_to_vector')
18 | vector = rs.raster_to_vector(p, temp)
19 | self.assertTrue(rs.files_directories.is_file(vector.path))
20 | temp = cfg.temp.temporary_file_path(name_suffix=cfg.gpkg_suffix)
21 | cfg.logger.log.debug('>>> test raster_to_vector dissolve')
22 | vector = rs.raster_to_vector(p, temp, dissolve=True)
23 | self.assertTrue(rs.files_directories.is_file(vector.path))
24 |
25 | # clear temporary directory
26 | rs.close()
27 |
--------------------------------------------------------------------------------
/.github/workflows/publish-to-pypi.yml:
--------------------------------------------------------------------------------
1 | name: Publish Python distribution to PyPI
2 |
3 | on: push
4 |
5 | jobs:
6 | build-n-publish:
7 | name: Build and publish Python distribution to PyPI
8 | runs-on: ubuntu-latest
9 | # Specifying a GitHub environment is optional, but strongly encouraged
10 | environment: release
11 | permissions:
12 | # IMPORTANT: this permission is mandatory for trusted publishing
13 | id-token: write
14 | steps:
15 | - uses: actions/checkout@master
16 | - name: Set up Python 3.10
17 | uses: actions/setup-python@v3
18 | with:
19 | python-version: "3.10"
20 | - name: Install pypa/build
21 | run: >-
22 | python -m
23 | pip install
24 | build
25 | --user
26 | - name: Build a binary wheel and a source tarball
27 | run: >-
28 | python -m
29 | build
30 | --sdist
31 | --wheel
32 | --outdir dist/
33 | .
34 | - name: Publish distribution to PyPI
35 | if: startsWith(github.ref, 'refs/tags')
36 | uses: pypa/gh-action-pypi-publish@release/v1
37 |
--------------------------------------------------------------------------------
/src/remotior_sensus/__init__.py:
--------------------------------------------------------------------------------
1 | # Remotior Sensus , software to process remote sensing and GIS data.
2 | # Copyright (C) 2022-2025 Luca Congedo.
3 | # Author: Luca Congedo
4 | # Email: ing.congedoluca@gmail.com
5 | #
6 | # This file is part of Remotior Sensus.
7 | # Remotior Sensus is free software: you can redistribute it and/or modify it
8 | # under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License,
10 | # or (at your option) any later version.
11 | # Remotior Sensus is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty
13 | # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | # See the GNU General Public License for more details.
15 | # You should have received a copy of the GNU General Public License
16 | # along with Remotior Sensus. If not, see .
17 |
18 | from remotior_sensus.core.session import Session
19 | from remotior_sensus.core import configurations
20 |
21 | __version__ = '0.5.2'
22 |
23 | configurations.version = __version__
24 |
--------------------------------------------------------------------------------
/tests/test_vector_to_raster.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 | from unittest import TestCase
3 |
4 | import remotior_sensus
5 |
6 |
7 | class TestVectorToRaster(TestCase):
8 |
9 | def test_vector_to_raster(self):
10 | rs = remotior_sensus.Session(
11 | n_processes=2, available_ram=1000, log_level=10
12 | )
13 | cfg = rs.configurations
14 | cfg.logger.log.debug('>>> test vector to raster')
15 | data_path = Path(__file__).parent / 'data'
16 | v = str(data_path / 'files' / 'roi.gpkg')
17 | r = str(data_path / 'S2_2020-01-01' / 'S2_B02.tif')
18 | temp = cfg.temp.temporary_file_path(
19 | name='raster', name_suffix=cfg.tif_suffix
20 | )
21 | raster = rs.vector_to_raster(vector_path=v, align_raster=r,
22 | constant=1, output_path=temp)
23 | self.assertTrue(rs.files_directories.is_file(raster.path))
24 | raster = rs.vector_to_raster(vector_path=v, align_raster=r,
25 | method='area_based', vector_field='class')
26 | self.assertTrue(rs.files_directories.is_file(raster.path))
27 |
28 | # clear temporary directory
29 | rs.close()
30 |
--------------------------------------------------------------------------------
/tests/run_tests.py:
--------------------------------------------------------------------------------
1 | # Remotior Sensus , software to process remote sensing and GIS data.
2 | # Copyright (C) 2022-2025 Luca Congedo.
3 | # Author: Luca Congedo
4 | # Email: ing.congedoluca@gmail.com
5 | #
6 | # This file is part of Remotior Sensus.
7 | # Remotior Sensus is free software: you can redistribute it and/or modify it
8 | # under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License,
10 | # or (at your option) any later version.
11 | # Remotior Sensus is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty
13 | # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | # See the GNU General Public License for more details.
15 | # You should have received a copy of the GNU General Public License
16 | # along with Remotior Sensus. If not, see .
17 |
18 | import unittest
19 |
20 | # protect the entry point for multiprocess
21 | if __name__ == '__main__':
22 | testLoader = unittest.TestLoader()
23 | test_dir = '.'
24 | # units to test
25 | pattern = 'test*.py'
26 | d = testLoader.discover(test_dir, pattern=pattern)
27 | textTestRunner = unittest.TextTestRunner(verbosity=2)
28 | textTestRunner.run(d)
29 |
--------------------------------------------------------------------------------
/tests/test_band_sieve.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 | from unittest import TestCase
3 |
4 | import remotior_sensus
5 |
6 |
7 | class TestBandSieve(TestCase):
8 |
9 | def test_band_sieve(self):
10 | rs = remotior_sensus.Session(
11 | n_processes=2, available_ram=1000, log_level=10
12 | )
13 | cfg = rs.configurations
14 | data_path = Path(__file__).parent / 'data'
15 | file_list = [
16 | str(data_path / 'S2_2020-01-01' / 'S2_B02.tif'),
17 | str(data_path / 'S2_2020-01-01' / 'S2_B03.tif')
18 | ]
19 | cfg.logger.log.debug('>>> test band_sieve')
20 | sieve = rs.band_sieve(
21 | input_bands=file_list, output_path=cfg.temp.dir, size=2,
22 | connected=False, prefix='sieve_'
23 | )
24 | self.assertTrue(rs.files_directories.is_file(sieve.paths[0]))
25 |
26 | coordinate_list = [230250, 4674550, 230320, 4674440]
27 | sieve = rs.band_sieve(
28 | input_bands=file_list, output_path=cfg.temp.dir, size=2,
29 | connected=False, prefix='sieve_', extent_list=coordinate_list
30 | )
31 | self.assertTrue(rs.files_directories.is_file(sieve.paths[0]))
32 |
33 | # clear temporary directory
34 | rs.close()
35 |
--------------------------------------------------------------------------------
/tests/test_download_tools.py:
--------------------------------------------------------------------------------
1 | from unittest import TestCase
2 |
3 | import remotior_sensus
4 | from remotior_sensus.util import download_tools, files_directories
5 |
6 |
7 | class TestDownloadTools(TestCase):
8 |
9 | def test_download_tools(self):
10 | rs = remotior_sensus.Session(
11 | n_processes=2, available_ram=1000, log_level=10
12 | )
13 | cfg = rs.configurations
14 | cfg.logger.log.debug('>>> test download')
15 | url = 'https://www.python.org'
16 | temp = cfg.temp.temporary_file_path(name_suffix='.html')
17 | download_tools.download_file(url=url, output_path=temp)
18 | self.assertTrue(files_directories.is_file(temp))
19 | url_2 = ''.join(
20 | ['https://storage.googleapis.com/gcp-public-data-sentinel-2/',
21 | 'L2/tiles/33/S/VB/S2A_MSIL2A_20210104T094411_N0214_R036_T33S',
22 | 'VB_20210104T122314.SAFE/GRANULE/L2A_T33SVB_A028919_20210104',
23 | 'T094407/IMG_DATA/R60m/T33SVB_20210104T094411_B01_60m.jp2']
24 | )
25 | temp_2 = cfg.temp.temporary_file_path(name_suffix='.jp2')
26 | download_tools.download_file(url=url_2, output_path=temp_2)
27 | self.assertTrue(files_directories.is_file(temp_2))
28 |
29 | # clear temporary directory
30 | rs.close()
31 |
--------------------------------------------------------------------------------
/tests/data/files/landsat_5_metadata_mtl.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | L1TP
5 | 02
6 | T1
7 |
8 |
9 | LANDSAT_5
10 | MSS
11 | 2011-01-01
12 | 20.7
13 | 0.98
14 |
15 |
16 | 1.52E-03
17 | 1.31E-03
18 | 1.38E-03
19 | NULL
20 | 0.0026
21 | 0.0040
22 | 0.0107
23 | NULL
24 |
25 |
26 | 607.76
27 | 1260.56
28 |
29 |
30 |
--------------------------------------------------------------------------------
/docs/source/remotior_sensus.tools.rst:
--------------------------------------------------------------------------------
1 | remotior\_sensus.tools package
2 | ==============================
3 |
4 | Submodules
5 | ----------
6 |
7 | .. toctree::
8 | :maxdepth: 4
9 |
10 | remotior_sensus.tools.band_calc
11 | remotior_sensus.tools.band_classification
12 | remotior_sensus.tools.band_clip
13 | remotior_sensus.tools.band_clustering
14 | remotior_sensus.tools.band_combination
15 | remotior_sensus.tools.band_dilation
16 | remotior_sensus.tools.band_erosion
17 | remotior_sensus.tools.band_mask
18 | remotior_sensus.tools.band_neighbor_pixels
19 | remotior_sensus.tools.band_pca
20 | remotior_sensus.tools.band_resample
21 | remotior_sensus.tools.band_sieve
22 | remotior_sensus.tools.band_spectral_distance
23 | remotior_sensus.tools.band_stack
24 | remotior_sensus.tools.cross_classification
25 | remotior_sensus.tools.download_products
26 | remotior_sensus.tools.mosaic
27 | remotior_sensus.tools.preprocess_products
28 | remotior_sensus.tools.raster_edit
29 | remotior_sensus.tools.raster_label
30 | remotior_sensus.tools.raster_reclassification
31 | remotior_sensus.tools.raster_report
32 | remotior_sensus.tools.raster_split
33 | remotior_sensus.tools.raster_zonal_stats
34 | remotior_sensus.tools.raster_to_vector
35 | remotior_sensus.tools.vector_to_raster
36 |
37 | Module contents
38 | ---------------
39 |
40 | .. automodule:: remotior_sensus.tools
41 | :members:
42 | :undoc-members:
43 | :show-inheritance:
44 |
--------------------------------------------------------------------------------
/tests/test_band_neighbor_pixels.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 | from unittest import TestCase
3 |
4 | import remotior_sensus
5 |
6 |
7 | class TestNeighborPixels(TestCase):
8 |
9 | def test_neighbor_pixels(self):
10 | rs = remotior_sensus.Session(
11 | n_processes=2, available_ram=1000, log_level=10
12 | )
13 | cfg = rs.configurations
14 | data_path = Path(__file__).parent / 'data'
15 | file_list = [
16 | str(data_path / 'S2_2020-01-01' / 'S2_B02.tif'),
17 | str(data_path / 'S2_2020-01-01' / 'S2_B03.tif')
18 | ]
19 | cfg.logger.log.debug('>>> test neighbor_pixels')
20 | neighbor = rs.band_neighbor_pixels(
21 | input_bands=file_list, output_path=cfg.temp.dir, size=1,
22 | circular_structure=True, stat_name='Mean', prefix='neighbor_'
23 | )
24 | self.assertTrue(rs.files_directories.is_file(neighbor.paths[0]))
25 | cfg.logger.log.debug('>>> test neighbor_pixels with coordinates')
26 | coordinate_list = [230250, 4674550, 230320, 4674440]
27 | neighbor = rs.band_neighbor_pixels(
28 | input_bands=file_list, output_path=cfg.temp.dir, size=1,
29 | circular_structure=True, stat_name='Mean', prefix='neighbor_',
30 | extent_list=coordinate_list
31 | )
32 | self.assertTrue(rs.files_directories.is_file(neighbor.paths[0]))
33 |
34 | # clear temporary directory
35 | rs.close()
36 |
--------------------------------------------------------------------------------
/tests/test_band_stack_split.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 | from unittest import TestCase
3 |
4 | import remotior_sensus
5 |
6 |
7 | class TestBandStackSplit(TestCase):
8 |
9 | def test_band_stack_split(self):
10 | rs = remotior_sensus.Session(
11 | n_processes=2, available_ram=1000, log_level=10
12 | )
13 | cfg = rs.configurations
14 | cfg.logger.log.debug('>>> test band stack')
15 | catalog = rs.bandset_catalog()
16 | file_list = ['S2_2020-01-01/S2_B02.tif', 'S2_2020-01-01/S2_B03.tif',
17 | 'S2_2020-01-01/S2_B04.tif']
18 | date = '2021-01-01'
19 | data_path = Path(__file__).parent / 'data'
20 | catalog.create_bandset(
21 | file_list, wavelengths=['Sentinel-2'], date=date, bandset_number=1,
22 | root_directory=str(data_path)
23 | )
24 | cfg.logger.log.debug('>>> test band stack')
25 | temp = cfg.temp.temporary_file_path(name_suffix=cfg.tif_suffix)
26 | stack = rs.band_stack(input_bands=1, output_path=temp,
27 | bandset_catalog=catalog)
28 | cfg.logger.log.debug('>>> test raster split')
29 | self.assertTrue(rs.files_directories.is_file(stack.path))
30 | split = rs.raster_split(raster_path=stack.path,
31 | output_path=cfg.temp.dir)
32 | self.assertTrue(rs.files_directories.is_file(split.paths[0]))
33 |
34 | # clear temporary directory
35 | rs.close()
36 |
--------------------------------------------------------------------------------
/tests/test_band_resample.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 | from unittest import TestCase
3 |
4 | import remotior_sensus
5 |
6 |
7 | class TestBandResample(TestCase):
8 |
9 | def test_band_resample(self):
10 | rs = remotior_sensus.Session(
11 | n_processes=2, available_ram=1000, log_level=10
12 | )
13 | cfg = rs.configurations
14 | data_path = Path(__file__).parent / 'data'
15 | file_list = [
16 | str(data_path / 'S2_2020-01-01' / 'S2_B02.tif'),
17 | str(data_path / 'S2_2020-01-01' / 'S2_B03.tif')
18 | ]
19 | cfg.logger.log.debug('>>> test band resample')
20 | resample = rs.band_resample(
21 | input_bands=file_list, output_path=cfg.temp.dir, resampling='mode',
22 | resample_pixel_factor=2, prefix='resample_'
23 | )
24 | self.assertTrue(rs.files_directories.is_file(resample.paths[0]))
25 |
26 | # reproject band set (input files from bandset)
27 | reproject = rs.band_resample(
28 | input_bands=file_list, output_path=cfg.temp.dir,
29 | prefix='reproj_', epsg_code='32632', align_raster=None,
30 | resampling='nearest_neighbour', nodata_value=None,
31 | x_y_resolution=[20.0, 20.0], resample_pixel_factor=None,
32 | output_data_type=None, same_extent=False, virtual_output=False,
33 | compress=True, compress_format='LZW'
34 | )
35 | self.assertTrue(rs.files_directories.is_file(reproject.paths[0]))
36 |
37 | # clear temporary directory
38 | rs.close()
39 |
--------------------------------------------------------------------------------
/src/remotior_sensus/util/system_tools.py:
--------------------------------------------------------------------------------
1 | # Remotior Sensus , software to process remote sensing and GIS data.
2 | # Copyright (C) 2022-2025 Luca Congedo.
3 | # Author: Luca Congedo
4 | # Email: ing.congedoluca@gmail.com
5 | #
6 | # This file is part of Remotior Sensus.
7 | # Remotior Sensus is free software: you can redistribute it and/or modify it
8 | # under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License,
10 | # or (at your option) any later version.
11 | # Remotior Sensus is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty
13 | # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | # See the GNU General Public License for more details.
15 | # You should have received a copy of the GNU General Public License
16 | # along with Remotior Sensus. If not, see .
17 |
18 | """
19 | Tools to manage operating systems
20 | """
21 |
22 | from platform import system
23 | import sys
24 |
25 | from remotior_sensus.core import configurations as cfg
26 |
27 |
28 | # get system information
29 | def get_system_info():
30 | if sys.maxsize > 2 ** 32:
31 | cfg.sys_64bit = True
32 | else:
33 | cfg.sys_64bit = False
34 | # file system encoding
35 | cfg.file_sys_encoding = sys.getfilesystemencoding()
36 | # system information
37 | cfg.sys_name = system()
38 | cfg.logger.log.info(
39 | 'version:%s; system: %s; 64bit: %s; n_processes: %s; ram: %s; '
40 | 'temp.dir: %s'
41 | % (cfg.version, cfg.sys_name, cfg.sys_64bit, cfg.n_processes,
42 | cfg.available_ram, cfg.temp.dir)
43 | )
44 |
--------------------------------------------------------------------------------
/tests/test_raster_report.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 | from unittest import TestCase
3 |
4 | import remotior_sensus
5 | from remotior_sensus.util import read_write_files
6 |
7 |
8 | class TestRasterReport(TestCase):
9 |
10 | def test_report(self):
11 | rs = remotior_sensus.Session(
12 | n_processes=2, available_ram=1000, log_level=10
13 | )
14 | cfg = rs.configurations
15 | data_path = Path(__file__).parent / 'data'
16 | p = str(data_path / 'S2_2020-01-01' / 'S2_B02.tif')
17 | cfg.logger.log.debug('>>> test raster_report')
18 | report = rs.raster_report(p)
19 | table = read_write_files.open_text_file(report.path)
20 | table_f = read_write_files.format_csv_new_delimiter(
21 | table, cfg.tab_delimiter
22 | )
23 | self.assertGreater(len(table_f), 0)
24 | table_html = read_write_files.format_csv_text_html(table)
25 | self.assertGreater(len(table_html), 0)
26 | table_split = table.split(cfg.new_line)
27 | self.assertGreater(int(table_split[1][0]), 0)
28 | coordinate_list = [230250, 4674550, 230320, 4674440]
29 | report = rs.raster_report(p, extent_list=coordinate_list)
30 | table = read_write_files.open_text_file(report.path)
31 | table_f = read_write_files.format_csv_new_delimiter(
32 | table, cfg.tab_delimiter
33 | )
34 | self.assertGreater(len(table_f), 0)
35 | table_html = read_write_files.format_csv_text_html(table)
36 | self.assertGreater(len(table_html), 0)
37 | table_split = table.split(cfg.new_line)
38 | self.assertGreater(int(table_split[1][0]), 0)
39 |
40 | # clear temporary directory
41 | rs.close()
42 |
--------------------------------------------------------------------------------
/tests/test_band_dilation.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 | from unittest import TestCase
3 |
4 | import remotior_sensus
5 |
6 |
7 | class TestBandDilation(TestCase):
8 |
9 | def test_band_dilation(self):
10 | rs = remotior_sensus.Session(
11 | n_processes=2, available_ram=1000, log_level=10
12 | )
13 | cfg = rs.configurations
14 | data_path = Path(__file__).parent / 'data'
15 | file_list = [
16 | str(data_path / 'S2_2020-01-01' / 'S2_B02.tif'),
17 | str(data_path / 'S2_2020-01-01' / 'S2_B03.tif')
18 | ]
19 | cfg.logger.log.debug('>>> test band_dilation')
20 | dilation = rs.band_dilation(
21 | input_bands=file_list, output_path=cfg.temp.dir,
22 | value_list=[1, 425], size=3, circular_structure=True,
23 | prefix='dilation_'
24 | )
25 | self.assertTrue(rs.files_directories.is_file(dilation.paths[0]))
26 | cfg.logger.log.debug('>>> test band_dilation without output')
27 | dilation = rs.band_dilation(
28 | input_bands=file_list, value_list=[1, 425], size=3,
29 | circular_structure=True, prefix='dilation_'
30 | )
31 | self.assertTrue(rs.files_directories.is_file(dilation.paths[0]))
32 | cfg.logger.log.debug('>>> test band_dilation with coordinate list')
33 | coordinate_list = [230250, 4674550, 230320, 4674440]
34 | dilation = rs.band_dilation(
35 | input_bands=file_list, value_list=[1, 425], size=3,
36 | circular_structure=True, prefix='dilation_',
37 | extent_list=coordinate_list
38 | )
39 | self.assertTrue(rs.files_directories.is_file(dilation.paths[0]))
40 |
41 | # clear temporary directory
42 | rs.close()
43 |
--------------------------------------------------------------------------------
/tests/test_band_clustering.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 | from unittest import TestCase
3 |
4 | import remotior_sensus
5 |
6 |
7 | class TestBandClassification(TestCase):
8 |
9 | def test_band_classification(self):
10 | rs = remotior_sensus.Session(
11 | n_processes=2, available_ram=1000, log_level=10
12 | )
13 | cfg = rs.configurations
14 | cfg.logger.log.debug('>>> test semiautomatic classification')
15 | # create BandSet
16 | catalog = rs.bandset_catalog()
17 | file_list = ['L8_2020-01-01/L8_B2.tif', 'L8_2020-01-01/L8_B3.tif',
18 | 'L8_2020-01-01/L8_B4.tif', 'L8_2020-01-01/L8_B5.tif',
19 | 'L8_2020-01-01/L8_B6.tif', 'L8_2020-01-01/L8_B7.tif']
20 | data_path = Path(__file__).parent / 'data'
21 | catalog.create_bandset(file_list, root_directory=str(data_path))
22 | temp = cfg.temp.temporary_file_path(
23 | name='class', name_suffix=cfg.tif_suffix
24 | )
25 | rs.band_clustering(
26 | input_bands=catalog.get(1), output_raster_path=temp,
27 | algorithm_name=cfg.minimum_distance, class_number=3,
28 | max_iter=2, seed_signatures=cfg.random_pixel
29 | )
30 | temp = cfg.temp.temporary_file_path(
31 | name='class', name_suffix=cfg.tif_suffix
32 | )
33 | clustering = rs.band_clustering(
34 | input_bands=catalog.get(1), output_raster_path=temp,
35 | algorithm_name=cfg.minimum_distance, class_number=3,
36 | max_iter=2, seed_signatures=cfg.band_mean
37 | )
38 | self.assertTrue(rs.files_directories.is_file(clustering.path))
39 | self.assertTrue(
40 | rs.files_directories.is_file(clustering.extra['signature_path'])
41 | )
42 |
43 | # clear temporary directory
44 | rs.close()
45 |
--------------------------------------------------------------------------------
/tests/test_raster_edit.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 | from unittest import TestCase
3 |
4 | import remotior_sensus
5 |
6 |
7 | class TestRasterEdit(TestCase):
8 |
9 | def test_raster_edit(self):
10 | rs = remotior_sensus.Session(
11 | n_processes=2, available_ram=1000, log_level=10
12 | )
13 | cfg = rs.configurations
14 | data_path = Path(__file__).parent / 'data'
15 | p = str(data_path / 'S2_2020-01-01' / 'S2_B02.tif')
16 | v = str(data_path / 'files' / 'roi.gpkg')
17 | cfg.logger.log.debug('>>> test raster edit')
18 | temp = cfg.temp.temporary_file_path(name_suffix=cfg.tif_suffix)
19 | rs.files_directories.copy_file(in_path=p, out_path=temp)
20 | edit = rs.raster_edit(
21 | raster_path=temp, vector_path=v, constant_value=10
22 | )
23 | self.assertTrue(edit.extra['column_start'] > 0)
24 | cfg.logger.log.debug('>>> test undo raster edit')
25 | edit_2 = rs.raster_edit(
26 | raster_path=temp, column_start=edit.extra['column_start'],
27 | row_start=edit.extra['row_start'],
28 | old_array=edit.extra['old_array']
29 | )
30 | self.assertTrue(edit_2.extra['column_start'] is None)
31 | cfg.logger.log.debug('>>> test raster edit with expression')
32 | temp_3 = cfg.temp.temporary_file_path(name_suffix=cfg.tif_suffix)
33 | rs.files_directories.copy_file(in_path=p, out_path=temp_3)
34 | expression = 'where(%s%s%s > 500, 10, %s%s%s)' % (
35 | cfg.variable_band_quotes, cfg.variable_raster_name,
36 | cfg.variable_band_quotes, cfg.variable_band_quotes,
37 | cfg.variable_raster_name, cfg.variable_band_quotes
38 | )
39 | edit_3 = rs.raster_edit(
40 | raster_path=temp_3, vector_path=v, expression=expression
41 | )
42 | self.assertTrue(edit_3.extra['column_start'] > 0)
43 |
44 | # clear temporary directory
45 | rs.close()
46 |
--------------------------------------------------------------------------------
/tests/test_band_mask.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 | from unittest import TestCase
3 |
4 | import remotior_sensus
5 |
6 |
7 | class TestBandMask(TestCase):
8 |
9 | def test_band_mask(self):
10 | rs = remotior_sensus.Session(
11 | n_processes=2, available_ram=1000, log_level=10
12 | )
13 | cfg = rs.configurations
14 | cfg.logger.log.debug('>>> test band mask')
15 | catalog = rs.bandset_catalog()
16 | file_list = ['S2_2020-01-01/S2_B02.tif', 'S2_2020-01-01/S2_B03.tif',
17 | 'S2_2020-01-01/S2_B04.tif']
18 | data_path = Path(__file__).parent / 'data'
19 | catalog.create_bandset(
20 | file_list, wavelengths=['Sentinel-2'], bandset_number=1,
21 | root_directory=str(data_path)
22 | )
23 | cfg.logger.log.debug('>>> test band mask')
24 | v = str(data_path / 'files' / 'roi.gpkg')
25 | output = rs.band_mask(input_bands=1, input_mask=v,
26 | bandset_catalog=catalog,
27 | output_path=cfg.temp.dir)
28 | self.assertTrue(output.check)
29 | self.assertTrue(rs.files_directories.is_file(output.paths[0]))
30 | files = [
31 | str(data_path / 'S2_2020-01-01' / 'S2_B02.tif'),
32 | str(data_path / 'S2_2020-01-01' / 'S2_B03.tif'),
33 | str(data_path / 'S2_2020-01-01' / 'S2_B04.tif')
34 | ]
35 | mask_path = str(data_path / 'S2_2020-01-01' / 'S2_B02.tif')
36 | output = rs.band_mask(input_bands=files,
37 | input_mask=mask_path,
38 | prefix='mask_', buffer=1, mask_values=[1, 425],
39 | nodata_value=-32768, virtual_output=True,
40 | output_path=cfg.temp.dir)
41 | self.assertTrue(output.check)
42 | self.assertTrue(rs.files_directories.is_file(output.paths[0]))
43 |
44 | # clear temporary directory
45 | rs.close()
46 |
--------------------------------------------------------------------------------
/tests/data/files/sentinel_2_metadata_test_l2a.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 2020-01-01T01:00:00.000Z
4 | Level-2A
5 | Sentinel-2A
6 | 10000
7 | -1000
8 | -1000
9 | -1000
10 | -1000
11 | -1000
12 | -1000
13 | -1000
14 | -1000
15 | -1000
16 | -1000
17 | -1000
18 | -1000
19 | -1000
20 | 1884.1
21 | 1959
22 | 1823
23 | 1512
24 | 1424
25 | 1287.6
26 | 1162.1
27 | 1041
28 | 955
29 | 812
30 | 367
31 | 245
32 | 85
33 |
34 |
--------------------------------------------------------------------------------
/tests/data/files/sentinel_2_metadata_test_l1c.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 2020-01-01T01:00:00.000Z
4 | Level-1C
5 | Sentinel-2A
6 | 10000
7 | -1000
8 | -1000
9 | -1000
10 | -1000
11 | -1000
12 | -1000
13 | -1000
14 | -1000
15 | -1000
16 | -1000
17 | -1000
18 | -1000
19 | -1000
20 | 1884.1
21 | 1959
22 | 1823
23 | 1512
24 | 1424
25 | 1287.6
26 | 1162.1
27 | 1041
28 | 955
29 | 812
30 | 367
31 | 245
32 | 85
33 |
34 |
--------------------------------------------------------------------------------
/src/remotior_sensus/core/messages.py:
--------------------------------------------------------------------------------
1 | # Remotior Sensus , software to process remote sensing and GIS data.
2 | # Copyright (C) 2022-2025 Luca Congedo.
3 | # Author: Luca Congedo
4 | # Email: ing.congedoluca@gmail.com
5 | #
6 | # This file is part of Remotior Sensus.
7 | # Remotior Sensus is free software: you can redistribute it and/or modify it
8 | # under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License,
10 | # or (at your option) any later version.
11 | # Remotior Sensus is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty
13 | # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | # See the GNU General Public License for more details.
15 | # You should have received a copy of the GNU General Public License
16 | # along with Remotior Sensus. If not, see .
17 |
18 | """Manager of messages.
19 |
20 | Console messages during processes.
21 |
22 | Typical usage example:
23 |
24 | >>> # display a warning message
25 | >>> warning('warning message')
26 | """
27 |
28 |
29 | def warning(message: str):
30 | """Warning message.
31 |
32 | Prints a warning message.
33 |
34 | Args:
35 | message: message.
36 |
37 | Examples:
38 | Display a message
39 | >>> warning('warning message')
40 | """
41 | print('⚠ warning: %s' % message)
42 |
43 |
44 | def error(message: str):
45 | """Error message.
46 |
47 | Prints an error message.
48 |
49 | Args:
50 | message: message.
51 |
52 | Examples:
53 | Display a message
54 | >>> error('error message')
55 | """
56 | print('▲ error: %s' % message)
57 |
58 |
59 | def info(message: str):
60 | """Info message.
61 |
62 | Prints an info message.
63 |
64 | Args:
65 | message: message.
66 |
67 | Examples:
68 | Display a message
69 | >>> info('error message')
70 | """
71 | print('info: %s' % message)
72 |
--------------------------------------------------------------------------------
/tests/test_raster_zonal_stats.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 | from unittest import TestCase
3 |
4 | import remotior_sensus
5 |
6 |
7 | class TestRasterZonalStats(TestCase):
8 |
9 | def test_raster_zonal_stats(self):
10 | rs = remotior_sensus.Session(
11 | n_processes=2, available_ram=1000, log_level=10
12 | )
13 | cfg = rs.configurations
14 | data_path = Path(__file__).parent / 'data'
15 | v = str(data_path / 'files' / 'roi.gpkg')
16 | r = str(data_path / 'S2_2020-01-01' / 'S2_B02.tif')
17 | temp = cfg.temp.temporary_file_path(name_suffix=cfg.csv_suffix)
18 | cfg.logger.log.debug('>>> test raster_zonal_stats')
19 | stats = rs.raster_zonal_stats(
20 | raster_path=r, reference_path=v, vector_field='class',
21 | stat_names=['Sum', 'Mean'], output_path=temp,
22 | )
23 | self.assertTrue(rs.files_directories.is_file(stats.path))
24 | self.assertTrue(stats.extra['table'] is not None)
25 | temp = cfg.temp.temporary_file_path(name_suffix=cfg.csv_suffix)
26 | cfg.logger.log.debug('>>> test raster_zonal_stats percentile')
27 | stats2 = rs.raster_zonal_stats(
28 | raster_path=r, reference_path=v, vector_field='class',
29 | stat_names=['Percentile', 'Max', 'Min'], stat_percentile=[1, 99],
30 | output_path=temp,
31 | )
32 | self.assertTrue(rs.files_directories.is_file(stats2.path))
33 | self.assertTrue(stats2.extra['table'] is not None)
34 |
35 | cfg.logger.log.debug('>>> test raster_zonal_stats raster')
36 | raster = rs.vector_to_raster(vector_path=v, align_raster=r,
37 | vector_field='class')
38 | temp_2 = cfg.temp.temporary_file_path(name_suffix=cfg.csv_suffix)
39 | stats = rs.raster_zonal_stats(
40 | raster_path=r, reference_path=raster.path,
41 | stat_names=['Sum', 'Mean'], output_path=temp_2,
42 | )
43 | self.assertTrue(rs.files_directories.is_file(stats.path))
44 | self.assertTrue(stats.extra['table'] is not None)
45 |
46 | # clear temporary directory
47 | rs.close()
48 |
--------------------------------------------------------------------------------
/tests/test_band_pca.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 | from unittest import TestCase
3 |
4 | import remotior_sensus
5 |
6 |
7 | class TestBandPCA(TestCase):
8 |
9 | def test_band_pca(self):
10 | rs = remotior_sensus.Session(
11 | n_processes=2, available_ram=1000, log_level=10
12 | )
13 | cfg = rs.configurations
14 | cfg.logger.log.debug('>>> test band pca')
15 | catalog = rs.bandset_catalog()
16 | file_list = ['S2_2020-01-01/S2_B02.tif', 'S2_2020-01-01/S2_B03.tif',
17 | 'S2_2020-01-01/S2_B04.tif']
18 | data_path = Path(__file__).parent / 'data'
19 | catalog.create_bandset(
20 | file_list, wavelengths=['Sentinel-2'], bandset_number=1,
21 | root_directory=str(data_path)
22 | )
23 | cfg.logger.log.debug('>>> test band PCA input BandSet')
24 | temp = cfg.temp.temporary_file_path(name_suffix=cfg.tif_suffix)
25 | output = rs.band_pca(input_bands=catalog.get_bandset(1),
26 | output_path=temp)
27 | self.assertTrue(output.check)
28 | self.assertTrue(rs.files_directories.is_file(output.paths[0]))
29 | cfg.logger.log.debug('>>> test band PCA input BandSet with coordinate')
30 | coordinate_list = [230250, 4674550, 230320, 4674440]
31 | temp = cfg.temp.temporary_file_path(name_suffix=cfg.tif_suffix)
32 | output = rs.band_pca(input_bands=catalog.get_bandset(1),
33 | output_path=temp,
34 | extent_list=coordinate_list)
35 | self.assertTrue(output.check)
36 | self.assertTrue(rs.files_directories.is_file(output.paths[0]))
37 | cfg.logger.log.debug('>>> test band PCA input BandSet with coordinate')
38 | bs = catalog.get_bandset(1)
39 | bs.box_coordinate_list = [230250, 4674550, 230320, 4674440]
40 | output = rs.band_pca(input_bands=catalog.get_bandset(1),
41 | extent_list=coordinate_list)
42 | self.assertTrue(output.check)
43 | self.assertTrue(rs.files_directories.is_file(output.paths[0]))
44 |
45 | # clear temporary directory
46 | rs.close()
47 |
--------------------------------------------------------------------------------
/docs/source/installation.rst:
--------------------------------------------------------------------------------
1 | Installation
2 | ===============
3 |
4 | This section describes Remotior Sensus installation along with
5 | the required dependencies.
6 |
7 |
8 | Dependencies
9 | ____________
10 |
11 | Remotior Sensus requires `GDAL`, `NumPy` and `SciPy` for most functionalities.
12 | Optionally, `scikit-learn` and `PyTorch` are required for machine learning.
13 | Python >= 3.10 is recommended.
14 |
15 | .. _Installation with Conda:
16 |
17 | Installation with Conda
18 | _______________________
19 |
20 | Before installing Remotior Sensus please install the dependencies using
21 | a `Conda` environment (if you don't know `Conda` please read
22 | https://conda-forge.org/docs).
23 | For instance, you can use
24 | `Miniforge `_
25 | to create a `Conda` environment.
26 |
27 | .. code-block:: console
28 |
29 | $ conda create -c conda-forge --name environment python=3.10
30 | Proceed ([y]/n)? y
31 | $ conda activate environment
32 |
33 | Install Remotior Sensus using `Conda` (the fundamental dependencies are also installed):
34 |
35 | .. code-block:: console
36 |
37 | $ conda install -c conda-forge remotior-sensus
38 |
39 | For machine learning functionalities run:
40 |
41 | .. code-block:: console
42 |
43 | $ conda install -c conda-forge remotior-sensus scikit-learn pytorch
44 |
45 |
46 | Installation in Linux
47 | _______________________
48 |
49 | The suggested way to install Remotior Sensus is using `Conda` (see
50 | `Installation with Conda`_).
51 |
52 | Depending on the system, one could install the required dependencies as:
53 |
54 | .. code-block:: console
55 |
56 | $ sudo apt-get install python3-numpy python3-scipy gdal-bin
57 |
58 | For Remotior Sensus package installation use `pip`:
59 |
60 | .. code-block:: console
61 |
62 | $ pip install -U remotior-sensus
63 |
64 | Installation in OS X
65 | ____________________
66 |
67 | The suggested way to install Remotior Sensus is using `Conda` (see
68 | `Installation with Conda`_).
69 |
70 |
71 | Installation in Windows
72 | _______________________
73 |
74 | The suggested way to install Remotior Sensus is using `Conda` (see
75 | `Installation with Conda`_).
76 |
77 |
78 | Package installation
79 | ____________________
80 |
81 | Given that dependencies are installed, for Remotior Sensus package
82 | installation use `pip`:
83 |
84 | .. code-block:: console
85 |
86 | $ pip install -U remotior-sensus
87 |
--------------------------------------------------------------------------------
/docs/source/index.rst:
--------------------------------------------------------------------------------
1 | Remotior Sensus
2 | ===============
3 |
4 | .. image:: https://img.shields.io/badge/Website-darkgreen
5 | :target: https://fromgistors.blogspot.com/p/remotior-sensus.html
6 |
7 | .. image:: https://img.shields.io/badge/Documentation-blue
8 | :target: https://remotior-sensus.readthedocs.io
9 |
10 | .. image:: https://img.shields.io/badge/Bug%20reports-red
11 | :target: https://github.com/semiautomaticgit/remotior_sensus/issues
12 |
13 | .. image:: https://img.shields.io/pypi/v/remotior-sensus?label=PyPI%20version
14 | :target: https://pypi.org/project/remotior-sensus
15 |
16 | .. image:: https://img.shields.io/pypi/dm/remotior-sensus?label=PyPI%20downloads
17 | :target: https://pypi.org/project/remotior-sensus
18 |
19 | .. image:: https://img.shields.io/conda/v/conda-forge/remotior-sensus?label=Conda%20version
20 | :target: https://anaconda.org/conda-forge/remotior-sensus
21 |
22 | .. image:: https://img.shields.io/conda/d/conda-forge/remotior-sensus?label=Conda%20downloads
23 | :target: https://anaconda.org/conda-forge/remotior-sensus
24 |
25 | .. image:: https://img.shields.io/conda/l/conda-forge/remotior-sensus
26 | :target: https://www.gnu.org/licenses/
27 |
28 | .. image:: https://zenodo.org/badge/DOI/10.5281/zenodo.10038132.svg
29 | :target: https://doi.org/10.5281/zenodo.10038132
30 |
31 | .. image:: https://colab.research.google.com/assets/colab-badge.svg
32 | :target: https://remotior-sensus.readthedocs.io/en/latest/quickstart.html
33 |
34 | .. image:: _static/logo.png
35 | :width: 60pt
36 | :align: center
37 |
38 |
39 | Remotior Sensus (which is Latin for "a more remote sense")
40 | is a Python package that allows for the processing
41 | of remote sensing images and GIS data.
42 |
43 | **Source code:** https://github.com/semiautomaticgit/remotior_sensus
44 |
45 | **Bug reports:** https://github.com/semiautomaticgit/remotior_sensus/issues
46 |
47 |
48 |
49 | Documentation
50 | _____________
51 |
52 |
53 | .. toctree::
54 | :maxdepth: 3
55 | :titlesonly:
56 |
57 | introduction.rst
58 | installation.rst
59 | quickstart.rst
60 | basic_tutorials.rst
61 | tutorials.rst
62 | api_tools.rst
63 | api_core.rst
64 | api.rst
65 | changelog.rst
66 |
67 | `Except where otherwise noted, content of this work is licensed under a`
68 | `Creative Commons Attribution-ShareAlike 4.0 International License
69 | `_.
70 |
--------------------------------------------------------------------------------
/tests/test_raster_reclassification.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 | from unittest import TestCase
3 |
4 | import remotior_sensus
5 | # noinspection PyProtectedMember
6 | from remotior_sensus.tools.raster_reclassification import (
7 | unique_values_table, _import_reclassification_table
8 | )
9 |
10 |
11 | class TestRasterReclassification(TestCase):
12 |
13 | def test_reclassification(self):
14 | rs = remotior_sensus.Session(
15 | n_processes=2, available_ram=1000, log_level=10
16 | )
17 | cfg = rs.configurations
18 | data_path = Path(__file__).parent / 'data'
19 | p = str(data_path / 'S2_2020-01-01' / 'S2_B02.tif')
20 | cfg.logger.log.debug('>>> test unique values list')
21 | unique_list = unique_values_table(raster_path=p)
22 | self.assertGreater(len(unique_list), 0)
23 | unique_list = unique_values_table(raster_path=p, incremental=True)
24 | self.assertGreater(len(unique_list), 0)
25 | reclass_file = str(data_path / 'files' / 'reclass.csv')
26 | unique_list = _import_reclassification_table(csv_path=reclass_file)
27 | self.assertGreater(len(unique_list.extra['table']), 0)
28 | temp = cfg.temp.temporary_file_path(name_suffix=cfg.tif_suffix)
29 | reclassification_2 = rs.raster_reclassification(
30 | raster_path=p, output_path=temp,
31 | reclassification_table=unique_list.extra['table']
32 | )
33 | self.assertTrue(rs.files_directories.is_file(reclassification_2.path))
34 | temp = cfg.temp.temporary_file_path(name_suffix=cfg.tif_suffix)
35 | reclassification = rs.raster_reclassification(
36 | raster_path=reclassification_2.path, output_path=temp,
37 | reclassification_table=[[1, -10], ['nan', 6000]]
38 | )
39 | self.assertTrue(rs.files_directories.is_file(reclassification.path))
40 | temp = cfg.temp.temporary_file_path(name_suffix=cfg.tif_suffix)
41 | coordinate_list = [230250, 4674550, 230320, 4674440]
42 | reclassification = rs.raster_reclassification(
43 | raster_path=p, output_path=temp, extent_list=coordinate_list,
44 | reclassification_table=[['raster <= 3000', 1], ['raster > 500', 2]]
45 | )
46 | self.assertTrue(rs.files_directories.is_file(reclassification.path))
47 |
48 | # clear temporary directory
49 | rs.close()
50 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | pip-wheel-metadata/
24 | share/python-wheels/
25 | *.egg-info/
26 | .installed.cfg
27 | *.egg
28 | MANIFEST
29 |
30 | # PyInstaller
31 | # Usually these files are written by a python script from a template
32 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
33 | *.manifest
34 | *.spec
35 |
36 | # Installer logs
37 | pip-log.txt
38 | pip-delete-this-directory.txt
39 |
40 | # Unit test / coverage reports
41 | htmlcov/
42 | .tox/
43 | .nox/
44 | .coverage
45 | .coverage.*
46 | .cache
47 | nosetests.xml
48 | coverage.xml
49 | *.cover
50 | *.py,cover
51 | .hypothesis/
52 | .pytest_cache/
53 |
54 | # Translations
55 | *.mo
56 | *.pot
57 |
58 | # Django stuff:
59 | *.log
60 | local_settings.py
61 | db.sqlite3
62 | db.sqlite3-journal
63 |
64 | # Flask stuff:
65 | instance/
66 | .webassets-cache
67 |
68 | # Scrapy stuff:
69 | .scrapy
70 |
71 | # Sphinx documentation
72 | docs/_build/
73 |
74 | # PyBuilder
75 | target/
76 |
77 | # Jupyter Notebook
78 | .ipynb_checkpoints
79 |
80 | # IPython
81 | profile_default/
82 | ipython_config.py
83 |
84 | # pyenv
85 | .python-version
86 |
87 | # pipenv
88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
91 | # install all needed dependencies.
92 | #Pipfile.lock
93 |
94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
95 | __pypackages__/
96 |
97 | # Celery stuff
98 | celerybeat-schedule
99 | celerybeat.pid
100 |
101 | # SageMath parsed files
102 | *.sage.py
103 |
104 | # Environments
105 | .env
106 | .venv
107 | env/
108 | venv/
109 | ENV/
110 | env.bak/
111 | venv.bak/
112 |
113 | # Spyder project settings
114 | .spyderproject
115 | .spyproject
116 |
117 | # Rope project settings
118 | .ropeproject
119 |
120 | # mkdocs documentation
121 | /site
122 |
123 | # mypy
124 | .mypy_cache/
125 | .dmypy.json
126 | dmypy.json
127 |
128 | # Pyre type checker
129 | .pyre/
--------------------------------------------------------------------------------
/tests/test_raster_vector.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 | from unittest import TestCase
3 |
4 | import remotior_sensus
5 | from remotior_sensus.util import raster_vector, files_directories
6 |
7 |
8 | class TestRasterVector(TestCase):
9 |
10 | def test_raster_vector(self):
11 | rs = remotior_sensus.Session(
12 | n_processes=2, available_ram=1000, log_level=10
13 | )
14 | cfg = rs.configurations
15 | data_path = Path(__file__).parent / 'data'
16 | p = str(data_path / 'S2_2020-01-01' / 'S2_B02.tif')
17 | crs = raster_vector.get_crs(p)
18 | self.assertGreater(len(crs), 0)
19 | raster_list = [
20 | str(data_path / 'S2_2020-01-01' / 'S2_B02.tif'),
21 | str(data_path / 'S2_2020-01-03' / 'S2_B02.tif')
22 | ]
23 | temp = cfg.temp.temporary_file_path(name_suffix=cfg.vrt_suffix)
24 | cfg.logger.log.debug('>>> test create_virtual_raster')
25 | raster_vector.create_virtual_raster(
26 | input_raster_list=raster_list, output=temp, relative_to_vrt=False
27 | )
28 | self.assertTrue(files_directories.is_file(temp))
29 | temp = cfg.temp.temporary_file_path(name_suffix=cfg.vrt_suffix)
30 | cfg.logger.log.debug('>>> test create_virtual_raster_2_mosaic')
31 | raster_vector.create_virtual_raster_2_mosaic(
32 | input_raster_list=raster_list, output=temp
33 | )
34 | self.assertTrue(files_directories.is_file(temp))
35 | p = str(data_path / 'S2_2020-01-01' / 'S2_B02.tif')
36 | cfg.logger.log.debug('>>> test read raster')
37 | n = raster_vector.get_number_bands(p)
38 | self.assertEqual(n, 1)
39 | # virtual raster of BandSet
40 | cfg.logger.log.debug('>>> test create_virtual_raster BandSet')
41 | # box coordinate list
42 | catalog = rs.bandset_catalog()
43 | file_list = ['S2_2020-01-01/S2_B02.tif', 'S2_2020-01-01/S2_B03.tif',
44 | 'S2_2020-01-01/S2_B04.tif']
45 | coordinate_list = [230250, 4674550, 230320, 4674440]
46 | catalog.create_bandset(
47 | file_list, wavelengths=['Sentinel-2'],
48 | root_directory=str(data_path), box_coordinate_list=coordinate_list
49 | )
50 | temp_2 = cfg.temp.temporary_file_path(name_suffix=cfg.vrt_suffix)
51 | raster_vector.create_virtual_raster(
52 | bandset=catalog.get(1), output=temp_2
53 | )
54 | self.assertTrue(files_directories.is_file(temp_2))
55 |
56 | # clear temporary directory
57 | rs.close()
58 |
--------------------------------------------------------------------------------
/tests/test_progress.py:
--------------------------------------------------------------------------------
1 | from unittest import TestCase
2 |
3 | import remotior_sensus
4 | import time
5 |
6 |
7 | class TestProgress(TestCase):
8 |
9 | def test_create(self):
10 | rs = remotior_sensus.Session(
11 | n_processes=2, available_ram=1000, log_level=10
12 | )
13 | cfg = rs.configurations
14 | cfg.logger.log.debug('>>> test progress')
15 |
16 | cfg.progress.update(
17 | process=__name__.split('.')[-1].replace('_', ' '),
18 | message='starting', start=True
19 | )
20 | for e in range(0, 100):
21 | time.sleep(0.02)
22 | cfg.progress.update(
23 | message='test message',
24 | step=int(100 * (e + 1) / 100),
25 | percentage=int(100 * (e + 1) / 100)
26 | )
27 | cfg.progress.update(end=True)
28 |
29 | cfg.logger.log.debug('>>> test progress callback')
30 | rs.set(progress_callback=cfg.progress.print_progress)
31 | cfg.progress.update(
32 | process=__name__.split('.')[-1].replace('_', ' '),
33 | message='starting', start=True
34 | )
35 | for e in range(0, 100):
36 | time.sleep(0.02)
37 | cfg.progress.update(
38 | message='test message',
39 | step=int(100 * (e + 1) / 100),
40 | percentage=int(100 * (e + 1) / 100)
41 | )
42 | cfg.progress.update(end=True)
43 |
44 | cfg.logger.log.debug('>>> test progress smtp')
45 | smtp_user = None
46 | smtp_password = None
47 | smtp_server = None
48 | smtp_recipients = None
49 | rs.set(smtp_user=smtp_user, smtp_password=smtp_password,
50 | smtp_server=smtp_server, smtp_recipients=smtp_recipients,
51 | smtp_notification=True)
52 | cfg.progress.update(
53 | process=__name__.split('.')[-1].replace('_', ' '),
54 | message='starting', start=True
55 | )
56 | for e in range(0, 100):
57 | time.sleep(0.02)
58 | cfg.progress.update(
59 | message='test message',
60 | step=int(100 * (e + 1) / 100),
61 | percentage=int(100 * (e + 1) / 100)
62 | )
63 | cfg.progress.update(end=True)
64 | self.assertTrue(smtp_user is None)
65 | self.assertTrue(smtp_password is None)
66 | self.assertTrue(smtp_server is None)
67 | self.assertTrue(smtp_recipients is None)
68 |
69 | # clear temporary directory
70 | rs.close()
71 |
--------------------------------------------------------------------------------
/src/remotior_sensus/util/dates_times.py:
--------------------------------------------------------------------------------
1 | # Remotior Sensus , software to process remote sensing and GIS data.
2 | # Copyright (C) 2022-2025 Luca Congedo.
3 | # Author: Luca Congedo
4 | # Email: ing.congedoluca@gmail.com
5 | #
6 | # This file is part of Remotior Sensus.
7 | # Remotior Sensus is free software: you can redistribute it and/or modify it
8 | # under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License,
10 | # or (at your option) any later version.
11 | # Remotior Sensus is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty
13 | # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | # See the GNU General Public License for more details.
15 | # You should have received a copy of the GNU General Public License
16 | # along with Remotior Sensus. If not, see .
17 |
18 | """
19 | Tools to manage dates and times
20 | """
21 |
22 | from datetime import datetime
23 | from remotior_sensus.core import configurations as cfg
24 |
25 |
26 | # get date string from name
27 | def date_string_from_directory_name(directory_name):
28 | date = False
29 | # format YYYY-MM-DD
30 | try:
31 | datetime.strptime(directory_name[-10:], '%Y-%m-%d')
32 | date = directory_name[-10:]
33 | except Exception as err:
34 | str(err)
35 | # format YYYYMMDD
36 | try:
37 | dir_part = directory_name.split('_')
38 | for d_p in dir_part:
39 | d_p_part = d_p.lower().split('t')[0]
40 | try:
41 | date_string = datetime.strptime(d_p_part,
42 | '%Y%m%d')
43 | d_p_part_string = date_string.strftime('%Y-%m-%d')
44 | date = d_p_part_string
45 | break
46 | except Exception as err:
47 | str(err)
48 | except Exception as err:
49 | str(err)
50 | cfg.logger.log.debug('date: %s' % date)
51 | return date
52 |
53 |
54 | # get time
55 | def get_time_string():
56 | time = datetime.now().strftime('%Y%m%d_%H%M%S%f')
57 | return time
58 |
59 |
60 | # get date
61 | def get_date_string():
62 | time = datetime.now().strftime('%m%d')
63 | return time
64 |
65 |
66 | # create date
67 | def create_date(string: str):
68 | # format YYYY-MM-DD
69 | try:
70 | date = datetime.strptime(string, '%Y-%m-%d')
71 | except Exception as err:
72 | cfg.logger.log.error(str(err))
73 | date = None
74 | return date
75 |
--------------------------------------------------------------------------------
/docs/source/conf.py:
--------------------------------------------------------------------------------
1 | # Configuration file for the Sphinx documentation builder.
2 |
3 | # -- Path setup --------------------------------------------------------------
4 |
5 | import os
6 | import sys
7 |
8 | sys.path.insert(0, os.path.abspath('../../src/'))
9 |
10 | # -- Project information -----------------------------------------------------
11 |
12 | project = 'Remotior Sensus'
13 | copyright = '2022-2025, Luca Congedo'
14 | author = 'Luca Congedo'
15 | release = '0.5.2'
16 | version = '0.5.2.1'
17 |
18 | # -- General configuration ---------------------------------------------------
19 |
20 | master_doc = 'index'
21 | locale_dirs = ['locale/']
22 | gettext_compact = False
23 | extensions = ['sphinx.ext.napoleon', 'sphinx.ext.doctest']
24 | templates_path = ['_templates']
25 | exclude_patterns = ['modules.rst', 'remotior_sensus.util.*']
26 | autodoc_default_options = {
27 | 'special-members': '__init__',
28 | }
29 | pygments_style = 'sphinx'
30 |
31 | # -- Options for HTML output -------------------------------------------------
32 |
33 | html_theme = 'sphinx_rtd_theme'
34 | html_show_sourcelink = False
35 | html_static_path = ['_static']
36 | html_favicon = "_static/favicon.ico"
37 | html_show_sphinx = False
38 | html_css_files = ['html_css.css']
39 |
40 | # -- Options for LaTeX output ---------------------------------------------
41 |
42 | latex_documents = [
43 | ('index', 'Remotior_Sensus.tex', 'Remotior Sensus Documentation',
44 | 'Luca Congedo', 'manual'),
45 | ]
46 | latex_logo = '_static/logo.png'
47 | latex_use_parts = True
48 | latex_show_pagerefs = True
49 | latex_elements = {
50 | 'papersize': 'a4paper',
51 | 'sphinxsetup': """
52 | pre_box-shadow=2pt 2pt,
53 | pre_background-TeXcolor={named}{white},
54 | pre_box-shadow-TeXcolor={named}{black}
55 | """
56 | }
57 | # -- Options for manual page output ---------------------------------------
58 |
59 | man_pages = [
60 | ('index', 'remotior_sensus', 'Remotior Sensus Documentation',
61 | ['Luca Congedo'], 1)
62 | ]
63 |
64 | # -- Options for Texinfo output -------------------------------------------
65 |
66 | texinfo_documents = [
67 | ('index', 'Remotior_Sensus', 'Remotior Sensus Documentation',
68 | 'Luca Congedo', 'Remotior_Sensus',
69 | 'Software to process remote sensing and GIS data.',
70 | 'GIS and Remote Sensing'),
71 | ]
72 |
73 | # Napoleon settings
74 | napoleon_google_docstring = True
75 | napoleon_numpy_docstring = False
76 | napoleon_include_init_with_doc = False
77 | napoleon_include_private_with_doc = False
78 | napoleon_include_special_with_doc = True
79 | napoleon_use_admonition_for_examples = True
80 | napoleon_use_admonition_for_notes = False
81 | napoleon_use_admonition_for_references = False
82 | napoleon_use_ivar = False
83 | napoleon_use_param = True
84 | napoleon_use_rtype = True
85 | napoleon_preprocess_types = False
86 | napoleon_type_aliases = None
87 | napoleon_attr_annotations = True
88 |
--------------------------------------------------------------------------------
/tests/test_band_spectral_distance.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 | from unittest import TestCase
3 |
4 | import remotior_sensus
5 |
6 |
7 | class TestBandSpectralDistance(TestCase):
8 |
9 | def test_band_spectral_distance(self):
10 | rs = remotior_sensus.Session(
11 | n_processes=2, available_ram=1000, log_level=10
12 | )
13 | cfg = rs.configurations
14 | catalog = rs.bandset_catalog()
15 | data_path = Path(__file__).parent / 'data'
16 | file_list_1 = ['S2_2020-01-03/S2_B02.tif', 'S2_2020-01-03/S2_B03.tif',
17 | 'S2_2020-01-03/S2_B04.tif']
18 | file_list_2 = ['S2_2020-01-04/S2_B02.tif', 'S2_2020-01-04/S2_B03.tif',
19 | 'S2_2020-01-04/S2_B04.tif']
20 | catalog.create_bandset(
21 | file_list_1, wavelengths=['Sentinel-2'], bandset_number=1,
22 | root_directory=str(data_path)
23 | )
24 | catalog.create_bandset(
25 | file_list_2, wavelengths=['Sentinel-2'], bandset_number=2,
26 | root_directory=str(data_path)
27 | )
28 | bandset_list = [catalog.get_bandset(1), catalog.get_bandset(2)]
29 | cfg.logger.log.debug('>>> test spectral distance')
30 | temp = cfg.temp.temporary_file_path(name_suffix=cfg.tif_suffix)
31 | distance = rs.band_spectral_distance(
32 | input_bandsets=bandset_list, output_path=temp
33 | )
34 | self.assertTrue(rs.files_directories.is_file(distance.path))
35 | self.assertTrue(distance.check)
36 | cfg.logger.log.debug('>>> test spectral distance with catalog')
37 | temp = cfg.temp.temporary_file_path(name_suffix=cfg.tif_suffix)
38 | distance = rs.band_spectral_distance(
39 | input_bandsets=[1, 2], output_path=temp, bandset_catalog=catalog
40 | )
41 | self.assertTrue(rs.files_directories.is_file(distance.path))
42 | self.assertTrue(distance.check)
43 | cfg.logger.log.debug('>>> test spectral distance using spectral angle')
44 | temp = cfg.temp.temporary_file_path(name_suffix=cfg.tif_suffix)
45 | distance = rs.band_spectral_distance(
46 | input_bandsets=bandset_list, output_path=temp,
47 | algorithm_name=cfg.spectral_angle_mapping_a
48 | )
49 | self.assertTrue(rs.files_directories.is_file(distance.path))
50 | self.assertTrue(distance.check)
51 | cfg.logger.log.debug('>>> test spectral distance with threshold')
52 | temp = cfg.temp.temporary_file_path(name_suffix=cfg.tif_suffix)
53 | distance = rs.band_spectral_distance(
54 | input_bandsets=bandset_list, output_path=temp, threshold=1000
55 | )
56 | self.assertTrue(rs.files_directories.is_file(distance.path))
57 | self.assertTrue(distance.check)
58 |
59 | # clear temporary directory
60 | rs.close()
61 |
--------------------------------------------------------------------------------
/tests/test_cross_classification.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 | from unittest import TestCase
3 |
4 | import remotior_sensus
5 | from remotior_sensus.util import read_write_files, files_directories
6 |
7 |
8 | class TestCrossClassification(TestCase):
9 |
10 | def test_cross_classification(self):
11 | rs = remotior_sensus.Session(
12 | n_processes=2, available_ram=1000, log_level=10
13 | )
14 | cfg = rs.configurations
15 | data_path = Path(__file__).parent / 'data'
16 | p1 = str(data_path / 'S2_2020-01-01' / 'S2_B04.tif')
17 | p2 = str(data_path / 'S2_2020-01-01' / 'S2_B02.tif')
18 | v = str(data_path / 'files' / 'roi.gpkg')
19 | cfg.logger.log.debug('>>> test cross_classification')
20 | coordinate_list = [230250, 4674550, 230320, 4674440]
21 | cross = rs.cross_classification(
22 | classification_path=p1, reference_path=v, vector_field='class',
23 | extent_list=coordinate_list
24 | )
25 | self.assertTrue(files_directories.is_file(cross.paths[0]))
26 | cross = rs.cross_classification(
27 | classification_path=p1, reference_path=p2, cross_matrix=True
28 | )
29 | raster, text = cross.paths
30 | table = read_write_files.open_text_file(text)
31 | table_f = read_write_files.format_csv_new_delimiter(
32 | table, cfg.tab_delimiter
33 | )
34 | self.assertGreater(len(table_f), 0)
35 | table_split = table.split(cfg.new_line)
36 | self.assertGreater(int(table_split[1][0]), 0)
37 | cfg.logger.log.debug('>>> test cross_classification accuracy matrix')
38 | cross = rs.cross_classification(
39 | classification_path=p1, reference_path=p2, error_matrix=True
40 | )
41 | raster, text = cross.paths
42 | table = read_write_files.open_text_file(text)
43 | table_f = read_write_files.format_csv_new_delimiter(
44 | table, cfg.tab_delimiter
45 | )
46 | self.assertGreater(len(table_f), 0)
47 | table_split = table.split(cfg.new_line)
48 | self.assertGreater(int(table_split[1][0]), 0)
49 | cfg.logger.log.debug('>>> test cross_classification regression')
50 | temp2 = cfg.temp.temporary_file_path(name_suffix=cfg.tif_suffix)
51 | cross = rs.cross_classification(
52 | classification_path=p1, reference_path=p2, output_path=temp2,
53 | regression_raster=True
54 | )
55 | raster, text = cross.paths
56 | table = read_write_files.open_text_file(text)
57 | table_f = read_write_files.format_csv_new_delimiter(
58 | table, cfg.tab_delimiter
59 | )
60 | self.assertGreater(len(table_f), 0)
61 | table_split = table.split(cfg.new_line)
62 | self.assertGreater(int(table_split[1][0]), 0)
63 |
64 | # clear temporary directory
65 | rs.close()
66 |
--------------------------------------------------------------------------------
/tests/data/files/landsat_8_metadata_mtl.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | L2SP
5 | 02
6 | T1
7 |
8 |
9 | LANDSAT_8
10 | OLI_TIRS
11 | 2021-01-01
12 | 20.7
13 | 0.98
14 |
15 |
16 | 2.75e-05
17 | 2.75e-05
18 | 2.75e-05
19 | 2.75e-05
20 | 2.75e-05
21 | 2.75e-05
22 | 2.75e-05
23 | -0.2
24 | -0.2
25 | -0.2
26 | -0.2
27 | -0.2
28 | -0.2
29 | -0.2
30 |
31 |
32 | 0.003418
33 | 149.0
34 |
35 |
36 | 1.2160E-02
37 | 1.2490E-02
38 | 1.1476E-02
39 | 9.7271E-03
40 | 5.9677E-03
41 | 1.4908E-03
42 | 5.0339E-04
43 | 1.1011E-02
44 | 2.4756E-03
45 | 3.8000E-04
46 | 3.4900E-04
47 | -60.80157
48 | -62.44802
49 | -57.38151
50 | -48.63534
51 | -29.83850
52 | -7.45416
53 | -2.51696
54 | -55.05358
55 | -12.37815
56 | 0.10000
57 | 0.10000
58 |
59 |
60 |
--------------------------------------------------------------------------------
/tests/test_band_clip.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 | from unittest import TestCase
3 |
4 | import remotior_sensus
5 |
6 |
7 | class TestBandClip(TestCase):
8 |
9 | def test_band_clip(self):
10 | rs = remotior_sensus.Session(
11 | n_processes=2, available_ram=1000, log_level=10
12 | )
13 | cfg = rs.configurations
14 | cfg.logger.log.debug('>>> test band clip')
15 | catalog = rs.bandset_catalog()
16 | file_list = ['S2_2020-01-01/S2_B02.tif', 'S2_2020-01-01/S2_B03.tif',
17 | 'S2_2020-01-01/S2_B04.tif']
18 | data_path = Path(__file__).parent / 'data'
19 | catalog.create_bandset(
20 | file_list, wavelengths=['Sentinel-2'], bandset_number=1,
21 | root_directory=str(data_path)
22 | )
23 | cfg.logger.log.debug('>>> test band clip input BandSet')
24 | # box coordinate list
25 | extent_list = [230250, 4674510, 230320, 4674440]
26 | output = rs.band_clip(input_bands=1,
27 | output_path=cfg.temp.dir, prefix='clip_',
28 | extent_list=extent_list, bandset_catalog=catalog)
29 | self.assertTrue(output.check)
30 | # box coordinate list
31 | extent_list = [230250, 4674510, 230320, 4674440]
32 | output = rs.band_clip(input_bands=catalog.get_bandset(1),
33 | output_path=cfg.temp.dir, prefix='clip3_',
34 | extent_list=extent_list)
35 | self.assertTrue(output.check)
36 | cfg.logger.log.debug('>>> test band clip input BandSet multiband')
37 | catalog.create_bandset(
38 | [str(data_path / 'S2_2020-01-05' / 'S2_2020-01-05.tif')],
39 | wavelengths=['Sentinel-2'], bandset_number=2
40 | )
41 | output = rs.band_clip(input_bands=catalog.get_bandset(2),
42 | output_path=cfg.temp.dir, prefix='clip_b_',
43 | extent_list=extent_list)
44 | self.assertTrue(output.check)
45 | # box coordinate list
46 | extent_list = [230250, 4674510, 230320, 4674440]
47 | output = rs.band_clip(input_bands=catalog.get_bandset(1),
48 | output_path=cfg.temp.dir, prefix='clip2_',
49 | extent_list=extent_list, virtual_output=True)
50 | self.assertTrue(output.check)
51 | self.assertTrue(rs.files_directories.is_file(output.paths[0]))
52 |
53 | v = str(data_path / 'files' / 'roi.gpkg')
54 | output = rs.band_clip(input_bands=catalog.get_bandset(1),
55 | output_path=cfg.temp.dir, prefix='clip3_',
56 | vector_path=v)
57 | self.assertTrue(output.check)
58 | self.assertTrue(rs.files_directories.is_file(output.paths[0]))
59 | v = str(data_path / 'files' / 'roi.gpkg')
60 | output = rs.band_clip(input_bands=catalog.get_bandset(1),
61 | output_path=cfg.temp.dir, prefix='clip4_',
62 | vector_path=v, vector_field='class')
63 | self.assertTrue(output.check)
64 | self.assertTrue(rs.files_directories.is_file(output.paths[0]))
65 |
66 | # clear temporary directory
67 | rs.close()
68 |
--------------------------------------------------------------------------------
/src/remotior_sensus/util/read_write_files.py:
--------------------------------------------------------------------------------
1 | # Remotior Sensus , software to process remote sensing and GIS data.
2 | # Copyright (C) 2022-2025 Luca Congedo.
3 | # Author: Luca Congedo
4 | # Email: ing.congedoluca@gmail.com
5 | #
6 | # This file is part of Remotior Sensus.
7 | # Remotior Sensus is free software: you can redistribute it and/or modify it
8 | # under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License,
10 | # or (at your option) any later version.
11 | # Remotior Sensus is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty
13 | # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | # See the GNU General Public License for more details.
15 | # You should have received a copy of the GNU General Public License
16 | # along with Remotior Sensus. If not, see .
17 |
18 | """
19 | Tools to manage text files
20 | """
21 |
22 | from remotior_sensus.core import configurations as cfg
23 | from remotior_sensus.util.files_directories import (
24 | create_parent_directory as file_create_parent_directory
25 | )
26 |
27 |
28 | # write file
29 | def write_file(data, output_path, create_parent_directory=True, mode='w'):
30 | cfg.logger.log.debug('output_path: %s' % output_path)
31 | if create_parent_directory:
32 | file_create_parent_directory(output_path)
33 | # save combination to table
34 | with open(output_path, mode) as output_file:
35 | output_file.write(data)
36 | return output_path
37 |
38 |
39 | # open text file
40 | def open_text_file(input_path):
41 | with open(input_path, 'r') as f:
42 | text = f.read()
43 | cfg.logger.log.debug('input_path: %s' % str(input_path))
44 | return text
45 |
46 |
47 | # format csv file to new delimiter
48 | def format_csv_new_delimiter(table, delimiter):
49 | table_f = table.replace(cfg.comma_delimiter, delimiter)
50 | return table_f
51 |
52 |
53 | # format csv file to html table
54 | def format_csv_text_html(table):
55 | text = ['', cfg.new_line, '', cfg.new_line,
56 | '', '''
57 | ''', cfg.new_line, '', cfg.new_line, '', cfg.new_line,
66 | cfg.tab_delimiter, '', cfg.new_line]
67 | count = 0
68 | for line in table.split(cfg.new_line):
69 | if count == 0:
70 | text.append(cfg.tab_delimiter)
71 | text.append('')
72 | for record in line.split(cfg.comma_delimiter):
73 | text.append('| %s | ' % record)
74 | text.append('
%s%s' % (cfg.new_line, cfg.tab_delimiter))
75 | elif len(line) > 0:
76 | text.append('')
77 | for record in line.split(cfg.comma_delimiter):
78 | text.append('| %s | ' % record)
79 | text.append('
%s%s' % (cfg.new_line, cfg.tab_delimiter))
80 | count += 1
81 | text.append('
')
82 | text.append(cfg.new_line)
83 | text.append('')
84 | text.append(cfg.new_line)
85 | text.append('')
86 | html = ''.join(text)
87 | return html
88 |
--------------------------------------------------------------------------------
/tests/test_band_mosaic.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 | from unittest import TestCase
3 |
4 | import remotior_sensus
5 |
6 |
7 | class TestMosaicBands(TestCase):
8 |
9 | def test_mosaic_bands(self):
10 | rs = remotior_sensus.Session(
11 | n_processes=2, available_ram=1000, log_level=10
12 | )
13 | cfg = rs.configurations
14 | catalog = rs.bandset_catalog()
15 | data_path = Path(__file__).parent / 'data'
16 | file_list = [
17 | str(data_path / 'S2_2020-01-01' / 'S2_B02.tif'),
18 | str(data_path / 'S2_2020-01-02' / 'S2_B02.tif')
19 | ]
20 | temp = cfg.temp.dir
21 | cfg.logger.log.debug('>>> test mosaic')
22 | mosaic = rs.mosaic(file_list, temp)
23 | self.assertTrue(rs.files_directories.is_file(mosaic.paths[0]))
24 | self.assertTrue(mosaic.check)
25 | file_list_1 = ['S2_2020-01-01/S2_B02.tif', 'S2_2020-01-01/S2_B03.tif',
26 | 'S2_2020-01-01/S2_B04.tif']
27 | file_list_2 = ['S2_2020-01-02/S2_B02.tif', 'S2_2020-01-02/S2_B03.tif',
28 | 'S2_2020-01-02/S2_B04.tif']
29 | file_list_3 = ['S2_2020-01-03/S2_B02.tif', 'S2_2020-01-03/S2_B03.tif',
30 | 'S2_2020-01-03/S2_B04.tif']
31 | catalog.create_bandset(
32 | file_list_1, wavelengths=['Sentinel-2'], bandset_number=1,
33 | root_directory=str(data_path)
34 | )
35 | catalog.create_bandset(
36 | file_list_2, wavelengths=['Sentinel-2'], bandset_number=2,
37 | root_directory=str(data_path)
38 | )
39 | catalog.create_bandset(
40 | file_list_3, wavelengths=['Sentinel-2'], bandset_number=3,
41 | root_directory=str(data_path)
42 | )
43 | bandset_list = [catalog.get_bandset(1), catalog.get_bandset(2),
44 | catalog.get_bandset(3)]
45 | cfg.logger.log.debug('>>> test mosaic BandSet')
46 | mosaic = rs.mosaic(bandset_list, temp)
47 | self.assertTrue(rs.files_directories.is_file(mosaic.paths[0]))
48 | self.assertTrue(mosaic.check)
49 | bandset_list = [1, 2]
50 | mosaic = rs.mosaic(
51 | bandset_list, output_path=temp, bandset_catalog=catalog
52 | )
53 | self.assertTrue(rs.files_directories.is_file(mosaic.paths[0]))
54 | self.assertTrue(mosaic.check)
55 |
56 | band_list_1 = [
57 | str(data_path / 'S2_2020-01-01' / 'S2_B02.tif'),
58 | str(data_path / 'S2_2020-01-02' / 'S2_B02.tif'),
59 | str(data_path / 'S2_2020-01-02' / 'S2_B02.tif')
60 | ]
61 | band_list_2 = [
62 | str(data_path / 'S2_2020-01-01' / 'S2_B03.tif'),
63 | str(data_path / 'S2_2020-01-02' / 'S2_B03.tif'),
64 | str(data_path / 'S2_2020-01-02' / 'S2_B03.tif')
65 | ]
66 | band_list_3 = [
67 | str(data_path / 'S2_2020-01-01' / 'S2_B04.tif'),
68 | str(data_path / 'S2_2020-01-02' / 'S2_B04.tif'),
69 | str(data_path / 'S2_2020-01-02' / 'S2_B04.tif')
70 | ]
71 | band_list = [band_list_1, band_list_2, band_list_3]
72 | mosaic = rs.mosaic(
73 | band_list, output_path=temp, bandset_catalog=catalog,
74 | prefix='prefix', output_name='output_name'
75 | )
76 | self.assertTrue(rs.files_directories.is_file(mosaic.paths[0]))
77 | self.assertTrue(mosaic.check)
78 |
79 | # clear temporary directory
80 | rs.close()
81 |
--------------------------------------------------------------------------------
/tests/test_preprocess_products.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 | from unittest import TestCase
3 |
4 | import remotior_sensus
5 |
6 |
7 | class TestPreprocessProducts(TestCase):
8 |
9 | def test_preprocess_products(self):
10 | rs = remotior_sensus.Session(
11 | n_processes=2, available_ram=1000, log_level=10
12 | )
13 | cfg = rs.configurations
14 | # test Sentinel-2
15 | cfg.logger.log.debug('>>> test sentinel-2')
16 | data_path = Path(__file__).parent / 'data'
17 | files_path = data_path / 'files'
18 | table = rs.preprocess_products.create_product_table(
19 | input_path=str(data_path / 'S2_2020-01-01'),
20 | metadata_file_path=str(
21 | files_path / 'sentinel_2_metadata_test_l1c.xml'
22 | ),
23 | nodata_value=102
24 | )
25 | out_1 = rs.preprocess_products.perform_preprocess(
26 | product_table=table, output_path=cfg.temp.dir + '/test_1',
27 | dos1_correction=False
28 | )
29 | self.assertTrue(out_1.check)
30 | # test DOS1
31 | cfg.logger.log.debug('>>> test DOS1')
32 | out_2 = rs.preprocess_products.perform_preprocess(
33 | product_table=table, output_path=cfg.temp.dir + '/test_2',
34 | dos1_correction=True
35 | )
36 | self.assertTrue(out_2.check)
37 | # test Landsat
38 | cfg.logger.log.debug('>>> test Landsat')
39 | table2 = rs.preprocess_products.create_product_table(
40 | input_path=str(data_path / 'L8_2020-01-01'),
41 | metadata_file_path=str(files_path / 'landsat_8_metadata_mtl.xml')
42 | )
43 | out_3 = rs.preprocess_products.perform_preprocess(
44 | product_table=table2, output_path=cfg.temp.dir + '/test_3'
45 | )
46 | self.assertTrue(out_3.check)
47 |
48 | table3 = rs.preprocess_products.create_product_table(
49 | input_path=str(data_path / 'L8_2020-01-01'),
50 | metadata_file_path=str(files_path / 'landsat_5_metadata_mtl.xml')
51 | )
52 | out_4 = rs.preprocess_products.perform_preprocess(
53 | product_table=table3, output_path=cfg.temp.dir + '/test_4',
54 | dos1_correction=True
55 | )
56 | self.assertTrue(out_4.check)
57 | # create BandSet Catalog
58 | catalog = rs.bandset_catalog()
59 | out_5 = rs.preprocess_products.preprocess(
60 | input_path=str(data_path / 'L5_2020-01-01'),
61 | output_path=cfg.temp.dir + '/test_5',
62 | metadata_file_path=str(files_path / 'landsat_5_metadata_mtl.xml'),
63 | dos1_correction=True, add_bandset=True, bandset_catalog=catalog
64 | )
65 | self.assertTrue(out_5.check)
66 | self.assertEqual(catalog.get_bandset_count(), 2)
67 | self.assertEqual(catalog.get_bandset(2).get_band_count(), 3)
68 | # create BandSet Catalog
69 | catalog2 = rs.bandset_catalog()
70 | out_6 = rs.preprocess_products.preprocess(
71 | input_path=str(data_path / 'L5_2020-01-01'),
72 | output_path=cfg.temp.dir + '/test_5',
73 | metadata_file_path=str(files_path / 'landsat_5_metadata_mtl.xml'),
74 | dos1_correction=True, add_bandset=False, bandset_catalog=catalog2
75 | )
76 | self.assertTrue(out_6.check)
77 | self.assertEqual(catalog.get_bandset_count(), 2)
78 | self.assertEqual(catalog.get_bandset(2).get_band_count(), 3)
79 |
80 | # clear temporary directory
81 | rs.close()
82 |
--------------------------------------------------------------------------------
/src/remotior_sensus/core/temporary.py:
--------------------------------------------------------------------------------
1 | # Remotior Sensus , software to process remote sensing and GIS data.
2 | # Copyright (C) 2022-2025 Luca Congedo.
3 | # Author: Luca Congedo
4 | # Email: ing.congedoluca@gmail.com
5 | #
6 | # This file is part of Remotior Sensus.
7 | # Remotior Sensus is free software: you can redistribute it and/or modify it
8 | # under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License,
10 | # or (at your option) any later version.
11 | # Remotior Sensus is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty
13 | # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | # See the GNU General Public License for more details.
15 | # You should have received a copy of the GNU General Public License
16 | # along with Remotior Sensus. If not, see .
17 |
18 | import random
19 | import tempfile
20 |
21 | from remotior_sensus.core import configurations as cfg
22 | from remotior_sensus.util import files_directories, dates_times, shared_tools
23 |
24 |
25 | class Temporary(object):
26 |
27 | def __init__(self, temp_dir=None):
28 | self.dir = temp_dir
29 |
30 | # create root temporary directory
31 | @classmethod
32 | def create_root_temporary_directory(cls, prefix=None, directory=None):
33 | times = dates_times.get_date_string()
34 | t_dir = tempfile.mkdtemp(
35 | prefix='{}_{}'.format(prefix, times), dir=directory
36 | )
37 | return cls(t_dir)
38 |
39 | # clear root temporary directory
40 | def clear(self):
41 | if self.dir is not None:
42 | remove_root_temporary_directory(self.dir)
43 | self.dir = None
44 | return self.dir
45 |
46 | # create temporary directory
47 | def create_temporary_directory(self):
48 | times = dates_times.get_time_string()
49 | directory = shared_tools.join_path(
50 | self.dir, '{}{}'.format('t', times)
51 | ).replace('\\', '/')
52 | files_directories.create_directory(directory)
53 | return directory
54 |
55 | # create temporary file path
56 | def temporary_file_path(self, name_suffix=None, name_prefix=None,
57 | name=None, directory=None):
58 | times = dates_times.get_time_string()
59 | if name is None:
60 | r = str(random.randint(0, 10000))
61 | name = 't{}_{}'.format(times, r)
62 | else:
63 | directory = shared_tools.join_path(
64 | self.dir, '{}{}'.format('t', times)
65 | ).replace('\\', '/')
66 | files_directories.create_directory(directory)
67 | if name_suffix is not None:
68 | name = '%s%s' % (name, name_suffix)
69 | if name_prefix is not None:
70 | name = '%s%s' % (name_prefix, name)
71 | if directory is None:
72 | directory = self.dir
73 | path = shared_tools.join_path(directory, name).replace('\\', '/')
74 | return path
75 |
76 | # create temporary raster file path
77 | def temporary_raster_path(
78 | self, name=None, name_suffix=None, name_prefix=None,
79 | extension='.tif'
80 | ):
81 | file_path = self.temporary_file_path(
82 | name_suffix=name_suffix, name_prefix=name_prefix, name=name
83 | )
84 | path = '%s%s' % (file_path, extension)
85 | return path
86 |
87 |
88 | # remove root temporary directory
89 | def remove_root_temporary_directory(directory):
90 | # close log handlers
91 | try:
92 | for h in cfg.logger.log.handlers:
93 | h.close()
94 | except Exception as err:
95 | str(err)
96 | try:
97 | cfg.logger.log.handlers = []
98 | except Exception as err:
99 | str(err)
100 | files_directories.remove_directory(directory)
101 | return directory
102 |
--------------------------------------------------------------------------------
/docs/source/changelog.rst:
--------------------------------------------------------------------------------
1 | Changelog
2 | ===============
3 |
4 | v0.5.2
5 | ________
6 |
7 | * Performance improvement for the tool "Vector to raster" with the method
8 | area_based.
9 | * Improvement of the multiprocess iterator.
10 | * Minor fixes
11 |
12 | v0.5.1
13 | ________
14 |
15 | * Fixed issue with the tool "Vector to raster" where a few polygons were
16 | randomly skipped using the method area_based.
17 | * Minor fixes
18 |
19 | v0.5.0
20 | ________
21 |
22 | * New tool "Raster label" for calculating the area of contiguous
23 | patches in a raster. The output is a raster where each pixel value represents
24 | the pixel count of the patch thereof.
25 | * Performance improvement for the tool "Vector to raster" with the method
26 | area_based.
27 | * Minor fixes
28 |
29 | v0.4.4
30 | ________
31 |
32 | * Changed raster_zonal_stats to accept raster input as reference_path
33 | * Fixed handling nan value as nodata
34 |
35 | v0.4.3
36 | ________
37 |
38 | * First experimental implementation of Pytorch for band_calc
39 | * Minor fixes
40 |
41 | v0.4.2
42 | ________
43 |
44 | * Minor fixes
45 |
46 | v0.4.1
47 | ________
48 |
49 | * Fixed preprocessing calculation
50 | * Minor fixes
51 |
52 | v0.4.0
53 | ________
54 |
55 | * Added tool "Band clustering" for unsupervised K-means classification of
56 | bandset
57 | * Added tool "Raster edit" for direct editing of pixel values based on vector
58 | * Added tool "Raster zonal stats" for calculating statistics of a raster
59 | intersecting a vector.
60 | * Improved the NoData handling for multiprocess calculation
61 | * In "Band clip", "Band dilation", "Band erosion", "Band sieve",
62 | "Band neighbor", "Band resample" added the option multiple_resolution to
63 | keep original resolution of individual rasters, or use the resolution of the
64 | first raster for all the bands
65 | * In "Cross classification" fixed area based accuracy and added kappa hat
66 | metric
67 | * In "Band combination" added option no_raster_output to avoid the creation of
68 | output raster, producing only the table of combinations
69 | * In "Band calc" replaced nanpercentile with optimized calculation function
70 | * Improved extraction of ROIs in "Band classification"
71 | * Minor bug fixing and removed Requests dependency
72 |
73 | v0.3.5
74 | ________
75 |
76 | * Fixed Copernicus access token error
77 | * Fixed automatic band wavelength definition in BandSet
78 |
79 | v0.3.04
80 | ________
81 |
82 | * Fixed Jupyter interface
83 |
84 | v0.3.03
85 | ________
86 |
87 | * Fixed Jupyter interface
88 |
89 | v0.3.02
90 | ________
91 |
92 | * Fixed Jupyter interface
93 |
94 | v0.3.01
95 | ________
96 |
97 | * Added functions for interactive interface in Jupyter environment
98 | * Fixed Sentinel-2 band 8A identification in preprocess products
99 |
100 | v0.2.01
101 | ________
102 |
103 | * In Download Products added the functions to search and download Collections
104 | from Microsoft Planetary Computer: Sentinel-2, Landsat, ASTER,
105 | MODIS Surface Reflectance 8-Day, and Copernicus DEM
106 |
107 |
108 | v0.1.24
109 | ________
110 |
111 | * Fixed band calc calculation with multiband raster as bandset
112 | * Fixed preview path for Copernicus products
113 |
114 | v0.1.23
115 | ________
116 |
117 | * Minor fixes
118 |
119 | v0.1.22
120 | ________
121 |
122 | * Fixed prepare input function
123 | * Fixed logger for multiprocess
124 |
125 |
126 | v0.1.21
127 | ________
128 |
129 | * Fixed requirements
130 |
131 |
132 | v0.1.20
133 | ________
134 |
135 | * Fixed Copernicus search and download service
136 |
137 |
138 | v0.1.19
139 | ________
140 |
141 | * Fixed Copernicus search and download service
142 |
143 | v0.1.18
144 | ________
145 |
146 | * Added Copernicus download service from
147 | https://catalogue.dataspace.copernicus.eu
148 | if copernicus_user and copernicus_password are provided.
149 |
150 | v0.1.17
151 | ________
152 |
153 | * Fixed spectral signature calculation for multiband raster
154 | * Fixed closing multiprocess at exit
155 |
156 | v0.1.16
157 | ________
158 |
159 | * Fixed issue in block size calculation for multiprocess in case of large
160 | input raster and low RAM;
161 | * Fixed management of bandsets using multiband rasters;
162 | * Minor fixes to multiprocess download;
--------------------------------------------------------------------------------
/tests/test_processor.py:
--------------------------------------------------------------------------------
1 | from unittest import TestCase
2 | import numpy as np
3 | from pathlib import Path
4 | import multiprocessing
5 | from remotior_sensus.core import processor
6 | import remotior_sensus
7 | # noinspection PyProtectedMember
8 | from remotior_sensus.core.multiprocess_manager import (
9 | _calculate_block_size, _compute_raster_pieces
10 | )
11 | from remotior_sensus.core.processor_functions import (
12 | reclassify_raster, band_calculation
13 | )
14 |
15 |
16 | class TestProcessor(TestCase):
17 |
18 | def test_processor(self):
19 | rs = remotior_sensus.Session(
20 | n_processes=2, available_ram=1000, log_level=10
21 | )
22 | cfg = rs.configurations
23 | cfg.logger.log.debug('>>> test reclassification')
24 | process_parameters = [
25 | 1, cfg.temp, 500, cfg.gdal_path, multiprocessing.Manager().Queue(),
26 | cfg.refresh_time, cfg.memory_unit_array_12, cfg.log_level,
27 | None, None
28 | ]
29 | data_path = Path(__file__).parent / 'data'
30 | raster_path = str(data_path / 'S2_2020-01-01' / 'S2_B02.tif')
31 | calc_datatype = [np.float32]
32 | input_nodata_as_value = False
33 | use_value_as_nodata = [1]
34 | (raster_x_size, raster_y_size, block_size_x, block_size_y,
35 | list_range_x, list_range_y, tot_blocks,
36 | number_of_bands) = _calculate_block_size(
37 | raster_path, 1, cfg.memory_unit_array_12, 0,
38 | available_ram=100
39 | )
40 | # compute raster pieces
41 | pieces = _compute_raster_pieces(
42 | raster_x_size, raster_y_size, block_size_x, block_size_y,
43 | list_range_y, 1, separate_bands=False,
44 | unique_section=True
45 | )
46 | # use raster files directly (not vrt)
47 | input_parameters = [[[raster_path]], calc_datatype, None,
48 | pieces[0], None, None,
49 | use_value_as_nodata, None,
50 | input_nodata_as_value, None,
51 | 0, None, True]
52 | temp = cfg.temp.temporary_file_path(name_suffix=cfg.tif_suffix)
53 | compress = cfg.raster_compression
54 | compress_format = cfg.raster_compression_format
55 | any_nodata_mask = False
56 | output_nodata_value = -10
57 | keep_output_array = True
58 | keep_output_argument = False
59 | output_parameters = [[temp], [cfg.raster_data_type],
60 | compress, compress_format, any_nodata_mask,
61 | [output_nodata_value], [1],
62 | keep_output_array, keep_output_argument]
63 | dtype_list = [(cfg.old_value, 'U1024'), (cfg.new_value, 'U1024')]
64 | function = reclassify_raster
65 | function_argument = np.array(
66 | ([('1', '2'), ('1110', '3')]), dtype=dtype_list
67 | )
68 | function_variable = cfg.variable_raster_name
69 | (output_array_list, out_files, proc_error,
70 | logger) = processor.function_initiator(
71 | process_parameters, input_parameters, output_parameters,
72 | function, [function_argument], [function_variable],
73 | False, False, False,
74 | False,
75 | )
76 | self.assertEqual(output_array_list[0][0][0, 0], output_nodata_value)
77 | self.assertTrue(rs.files_directories.is_file(out_files[0][0]))
78 | cfg.logger.log.debug('>>> test band calc')
79 | function = band_calculation
80 | function_argument = '_array_function_placeholder * 2'
81 | function_variable = cfg.variable_raster_name
82 | (output_array_list, out_files, proc_error,
83 | logger) = processor.function_initiator(
84 | process_parameters, input_parameters, output_parameters,
85 | function, [function_argument], [function_variable],
86 | False, False, False,
87 | False
88 | )
89 | self.assertEqual(output_array_list[0][0][0, 0], output_nodata_value)
90 | self.assertTrue(rs.files_directories.is_file(out_files[0][0]))
91 |
92 | # clear temporary directory
93 | rs.close()
94 |
--------------------------------------------------------------------------------
/tests/test_band_combination.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 | from unittest import TestCase
3 |
4 | import remotior_sensus
5 | from remotior_sensus.util import read_write_files
6 |
7 |
8 | class TestBandCombination(TestCase):
9 |
10 | def test_band_combination(self):
11 | rs = remotior_sensus.Session(
12 | n_processes=2, available_ram=1000, log_level=10
13 | )
14 | cfg = rs.configurations
15 | cfg.logger.log.debug('>>> test band combination')
16 | catalog = rs.bandset_catalog()
17 | file_list = ['S2_2020-01-01/S2_B02.tif', 'S2_2020-01-01/S2_B03.tif',
18 | 'S2_2020-01-01/S2_B04.tif']
19 | date = '2021-01-01'
20 | data_path = Path(__file__).parent / 'data'
21 | catalog.create_bandset(
22 | file_list, wavelengths=['Sentinel-2'], date=date, bandset_number=1,
23 | root_directory=str(data_path)
24 | )
25 | cfg.logger.log.debug('>>> test band combination input BandSet')
26 | temp = cfg.temp.temporary_file_path(name_suffix=cfg.tif_suffix)
27 | combination = rs.band_combination(
28 | input_bands=catalog.get_bandset(1), output_path=temp
29 | )
30 | raster, text = combination.paths
31 | table = read_write_files.open_text_file(text)
32 | table_f = read_write_files.format_csv_new_delimiter(
33 | table, cfg.tab_delimiter
34 | )
35 | self.assertGreater(len(table_f), 0)
36 | cfg.logger.log.debug('>>> test band combination no_raster_output')
37 | temp = cfg.temp.temporary_file_path(name_suffix=cfg.tif_suffix)
38 | combination = rs.band_combination(
39 | input_bands=catalog.get_bandset(1), output_path=temp,
40 | no_raster_output=True
41 | )
42 | raster, text = combination.paths
43 | table = read_write_files.open_text_file(text)
44 | table_f = read_write_files.format_csv_new_delimiter(
45 | table, cfg.tab_delimiter
46 | )
47 | self.assertGreater(len(table_f), 0)
48 | cfg.logger.log.debug('>>> test band combination input multiband')
49 | catalog.create_bandset(
50 | file_list, wavelengths=['Sentinel-2'], date=date, bandset_number=1,
51 | root_directory=str(data_path)
52 | )
53 | catalog.create_bandset(
54 | [str(data_path / 'S2_2020-01-05' / 'S2_2020-01-05.tif')],
55 | bandset_number=2
56 | )
57 | temp = cfg.temp.temporary_file_path(name_suffix=cfg.tif_suffix)
58 | combination = rs.band_combination(
59 | input_bands=catalog.get_bandset(2), output_path=temp
60 | )
61 | raster, text = combination.paths
62 | table = read_write_files.open_text_file(text)
63 | table_f = read_write_files.format_csv_new_delimiter(
64 | table, cfg.tab_delimiter
65 | )
66 | self.assertGreater(len(table_f), 0)
67 | cfg.logger.log.debug('>>> test band combination input BandSet number')
68 | bs = catalog.get_bandset(1)
69 | bs.box_coordinate_list = [230250, 4674550, 230320, 4674440]
70 | combination = rs.band_combination(
71 | input_bands=1, bandset_catalog=catalog
72 | )
73 | raster, text = combination.paths
74 | table = read_write_files.open_text_file(text)
75 | table_f = read_write_files.format_csv_new_delimiter(
76 | table, cfg.tab_delimiter
77 | )
78 | self.assertGreater(len(table_f), 0)
79 | temp = cfg.temp.temporary_file_path(name_suffix=cfg.tif_suffix)
80 | file_list = [
81 | str(data_path / 'S2_2020-01-01' / 'S2_B02.tif'),
82 | str(data_path / 'S2_2020-01-01' / 'S2_B03.tif'),
83 | str(data_path / 'S2_2020-01-01' / 'S2_B04.tif')
84 | ]
85 | cfg.logger.log.debug('>>> test band combination input file list')
86 | combination = rs.band_combination(input_bands=file_list,
87 | output_path=temp)
88 | raster, text = combination.paths
89 | table = read_write_files.open_text_file(text)
90 | table_f = read_write_files.format_csv_new_delimiter(
91 | table, cfg.tab_delimiter
92 | )
93 | self.assertGreater(len(table_f), 0)
94 | table_split = table.split(cfg.new_line)
95 | self.assertGreater(int(table_split[1][0]), 0)
96 | cfg.logger.log.debug('>>> test band combination without output table')
97 | combination = rs.band_combination(
98 | input_bands=file_list, output_table=False
99 | )
100 | combinations_array = combination.extra['combinations']
101 | self.assertGreater(combinations_array.shape[0], 1)
102 |
103 | # clear temporary directory
104 | rs.close()
105 |
--------------------------------------------------------------------------------
/src/remotior_sensus/util/plot_tools.py:
--------------------------------------------------------------------------------
1 | # Remotior Sensus , software to process remote sensing and GIS data.
2 | # Copyright (C) 2022-2025 Luca Congedo.
3 | # Author: Luca Congedo
4 | # Email: ing.congedoluca@gmail.com
5 | #
6 | # This file is part of Remotior Sensus.
7 | # Remotior Sensus is free software: you can redistribute it and/or modify it
8 | # under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License,
10 | # or (at your option) any later version.
11 | # Remotior Sensus is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty
13 | # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | # See the GNU General Public License for more details.
15 | # You should have received a copy of the GNU General Public License
16 | # along with Remotior Sensus. If not, see .
17 |
18 | """
19 | Tools to manage plots
20 | """
21 |
22 | try:
23 | import matplotlib.pyplot as plt
24 | import matplotlib.pyplot as mpl_plot
25 | except Exception as error:
26 | str(error)
27 |
28 |
29 | # prepare plot
30 | def prepare_plot(x_label=None, y_label=None):
31 | if x_label is None:
32 | x_label = 'Wavelength'
33 | if y_label is None:
34 | y_label = 'Values'
35 | figure, ax = plt.subplots()
36 | # Set empty ticks
37 | ax.set_xticks([])
38 | ax.set_yticks([])
39 | ax.set_aspect('auto')
40 | ax.grid('on')
41 | ax.set_xlabel(x_label)
42 | ax.set_ylabel(y_label)
43 | return ax
44 |
45 |
46 | # prepare plot
47 | def prepare_scatter_plot(x_label=None, y_label=None):
48 | if x_label is None:
49 | x_label = 'Band X'
50 | if y_label is None:
51 | y_label = 'Band Y'
52 | figure, ax = plt.subplots()
53 | # Set empty ticks
54 | ax.set_xticks([])
55 | ax.set_yticks([])
56 | ax.set_aspect('auto')
57 | ax.grid('on')
58 | ax.set_xlabel(x_label)
59 | ax.set_ylabel(y_label)
60 | return ax
61 |
62 |
63 | # add list of values to plot
64 | def add_lines_to_plot(
65 | name_list, wavelength_list, value_list, color_list,
66 | legend_max_chars=15
67 | ):
68 | plots = []
69 | plot_names = []
70 | v_lines = []
71 | wavelength_min = 1000000
72 | wavelength_max = 0
73 | value_min = 10000000
74 | value_max = 0
75 | for _id in range(len(name_list)):
76 | plot, = plt.plot(
77 | wavelength_list[_id], value_list[_id], color_list[_id]
78 | )
79 | v_lines.extend(wavelength_list[_id])
80 | wavelength_min = min(min(wavelength_list[_id]), wavelength_min)
81 | wavelength_max = max(max(wavelength_list[_id]), wavelength_max)
82 | value_min = min(min(value_list[_id]), value_min)
83 | value_max = max(max(value_list[_id]), value_max)
84 | plots.append(plot)
85 | plot_names.append(name_list[_id][:legend_max_chars])
86 | x_min = wavelength_min
87 | x_ticks = [x_min]
88 | for x in range(10):
89 | x_min += (wavelength_max - wavelength_min) / 10
90 | x_ticks.append(x_min)
91 | y_min = value_min
92 | y_ticks = [y_min]
93 | for y in range(10):
94 | y_min += (value_max - value_min) / 10
95 | y_ticks.append(y_min)
96 | return plots, plot_names, x_ticks, y_ticks, set(v_lines)
97 |
98 |
99 | # create plot
100 | def create_plot(
101 | ax, plots, plot_names, x_ticks=None, y_ticks=None, v_lines=None,
102 | return_plot=None
103 | ):
104 | if x_ticks is None:
105 | x_ticks = [0, 1]
106 | if y_ticks is None:
107 | y_ticks = [0, 1]
108 | if v_lines is not None:
109 | for x in v_lines:
110 | ax.axvline(x, color='black', linestyle='dashed')
111 | ax.legend(
112 | plots, plot_names, bbox_to_anchor=(0.0, 0.0, 1.1, 1.0), loc=1,
113 | borderaxespad=0.
114 | ).set_draggable(True)
115 | ax.set_xticks(x_ticks)
116 | ax.set_yticks(y_ticks)
117 | if return_plot is True:
118 | return plt
119 | else:
120 | plt.show()
121 | return True
122 |
123 |
124 | # create plot
125 | def create_scatter_plot(
126 | ax, plots, plot_names, x_ticks=None, y_ticks=None
127 | ):
128 | if x_ticks is None:
129 | x_ticks = [0, 1]
130 | if y_ticks is None:
131 | y_ticks = [0, 1]
132 | ax.legend(
133 | plots, plot_names, bbox_to_anchor=(0.0, 0.0, 1.1, 1.0), loc=1,
134 | borderaxespad=0.
135 | ).set_draggable(True)
136 | ax.set_xticks(x_ticks)
137 | ax.set_yticks(y_ticks)
138 | plt.show()
139 |
140 |
141 | # add values to plot
142 | def add_values_to_scatter_plot(histogram, ax):
143 | pal = mpl_plot.get_cmap('rainbow')
144 | pal.set_under('w', 0.0)
145 | plot = ax.imshow(
146 | histogram[0].T, origin='lower', interpolation='none',
147 | extent=[histogram[1][0], histogram[1][-1], histogram[2][0],
148 | histogram[2][-1]], cmap=pal, vmin=0.001
149 | )
150 | return plot
151 |
--------------------------------------------------------------------------------
/src/remotior_sensus/tools/band_stack.py:
--------------------------------------------------------------------------------
1 | # Remotior Sensus , software to process remote sensing and GIS data.
2 | # Copyright (C) 2022-2025 Luca Congedo.
3 | # Author: Luca Congedo
4 | # Email: ing.congedoluca@gmail.com
5 | #
6 | # This file is part of Remotior Sensus.
7 | # Remotior Sensus is free software: you can redistribute it and/or modify it
8 | # under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License,
10 | # or (at your option) any later version.
11 | # Remotior Sensus is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty
13 | # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | # See the GNU General Public License for more details.
15 | # You should have received a copy of the GNU General Public License
16 | # along with Remotior Sensus. If not, see .
17 | """
18 | Band stack.
19 |
20 | This tool allows for stacking single bands in a multiband raster.
21 |
22 | Typical usage example:
23 |
24 | >>> # import Remotior Sensus and start the session
25 | >>> import remotior_sensus
26 | >>> rs = remotior_sensus.Session()
27 | >>> # start the process
28 | >>> stack = rs.band_stack(input_bands=['path_1', 'path_2'],
29 | ... output_path='output_path')
30 | """ # noqa: E501
31 |
32 | from typing import Union, Optional
33 |
34 | from remotior_sensus.core import configurations as cfg
35 | from remotior_sensus.core.bandset_catalog import BandSet
36 | from remotior_sensus.core.bandset_catalog import BandSetCatalog
37 | from remotior_sensus.core.output_manager import OutputManager
38 | from remotior_sensus.util import (raster_vector, shared_tools)
39 |
40 |
41 | def band_stack(
42 | input_bands: Union[list, int, BandSet],
43 | output_path: Optional[str] = None,
44 | overwrite: Optional[bool] = False,
45 | extent_list: Optional[list] = None,
46 | bandset_catalog: Optional[BandSetCatalog] = None,
47 | n_processes: Optional[int] = None,
48 | virtual_output: Optional[bool] = None,
49 | progress_message: Optional[bool] = True
50 | ) -> OutputManager:
51 | """Stack single bands.
52 |
53 | This tool allows for stacking single bands in a multiband raster.
54 |
55 | Args:
56 | input_bands: list of paths of input rasters, or number of BandSet, or
57 | BandSet object.
58 | output_path: string of output path.
59 | overwrite: if True, output overwrites existing files.
60 | extent_list: list of boundary coordinates left top right bottom.
61 | bandset_catalog: BandSetCatalog object required if input_bands is a
62 | BandSet number.
63 | n_processes: number of parallel processes.
64 | virtual_output: if True (and output_path is directory), save output
65 | as virtual raster.
66 | progress_message: if True then start progress message, if False does
67 | not start the progress message (useful if launched from other tools).
68 |
69 | Returns:
70 | object :func:`~remotior_sensus.core.output_manager.OutputManager` with
71 | - path = output path
72 |
73 | Examples:
74 | Perform band stack
75 | >>> stack = band_stack(input_bands=['path_1', 'path_2'],
76 | ... output_path='output_path')
77 | """ # noqa: E501
78 | cfg.logger.log.info('start')
79 | cfg.progress.update(
80 | process=__name__.split('.')[-1].replace('_', ' '), message='starting',
81 | start=progress_message
82 | )
83 | # prepare process files
84 | prepared = shared_tools.prepare_process_files(
85 | input_bands=input_bands, output_path=output_path, overwrite=overwrite,
86 | n_processes=n_processes, bandset_catalog=bandset_catalog,
87 | box_coordinate_list=extent_list, virtual_output=virtual_output
88 | )
89 | input_raster_list = prepared['input_raster_list']
90 | out_path = prepared['output_path']
91 | if input_bands is BandSet:
92 | bandset_x = input_bands
93 | elif input_bands is int:
94 | bandset_x = bandset_catalog.get(input_bands)
95 | else:
96 | bandset_x = BandSet.create(paths=input_raster_list)
97 | if virtual_output:
98 | virtual_path = out_path
99 | else:
100 | virtual_path = cfg.temp.temporary_file_path(name_suffix=cfg.vrt_suffix)
101 | raster_vector.create_virtual_raster(output=virtual_path, bandset=bandset_x)
102 | cfg.progress.update(message='stack', step=2, steps=2, minimum=1,
103 | maximum=99, percentage=50)
104 | if virtual_output is not True:
105 | raster_vector.gdal_copy_raster(input_raster=virtual_path,
106 | output=out_path)
107 | cfg.progress.update(end=True)
108 | cfg.logger.log.info('end; band stack: %s' % str(out_path))
109 | return OutputManager(path=out_path)
110 |
--------------------------------------------------------------------------------
/src/remotior_sensus/tools/raster_to_vector.py:
--------------------------------------------------------------------------------
1 | # Remotior Sensus , software to process remote sensing and GIS data.
2 | # Copyright (C) 2022-2025 Luca Congedo.
3 | # Author: Luca Congedo
4 | # Email: ing.congedoluca@gmail.com
5 | #
6 | # This file is part of Remotior Sensus.
7 | # Remotior Sensus is free software: you can redistribute it and/or modify it
8 | # under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License,
10 | # or (at your option) any later version.
11 | # Remotior Sensus is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty
13 | # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | # See the GNU General Public License for more details.
15 | # You should have received a copy of the GNU General Public License
16 | # along with Remotior Sensus. If not, see .
17 | """
18 | Raster to vector.
19 |
20 | This tool allows for the conversion from raster to vector.
21 | A new geopackage is created from the raster conversion.
22 |
23 | Typical usage example:
24 |
25 | >>> # import Remotior Sensus and start the session
26 | >>> import remotior_sensus
27 | >>> rs = remotior_sensus.Session()
28 | >>> # start the process
29 | >>> vector = rs.raster_to_vector(raster_path='file.tif',output_path='vector.gpkg')
30 | """ # noqa: E501
31 |
32 | from typing import Optional
33 |
34 | from remotior_sensus.core import configurations as cfg
35 | from remotior_sensus.core.output_manager import OutputManager
36 | from remotior_sensus.util import files_directories, shared_tools
37 |
38 |
39 | def raster_to_vector(
40 | raster_path, output_path: Optional[str] = None,
41 | dissolve: Optional[bool] = None, field_name: Optional[str] = None,
42 | extent_list: Optional[list] = None,
43 | n_processes: Optional[int] = None, available_ram: Optional[int] = None,
44 | progress_message: Optional[bool] = True
45 | ) -> OutputManager:
46 | """Performs the conversion from raster to vector.
47 |
48 | This tool performs the conversion from raster to vector.
49 | Parallel processes are used for the conversion, resulting in a vector output
50 | which is split as many in portions as the process numbers.
51 | The argument dissolve allows for merging these portions,
52 | but it requires additional processing time depending on vector size.
53 |
54 | Args:
55 | raster_path: path of raster used as input.
56 | output_path: string of output path.
57 | dissolve: if True, dissolve adjacent polygons having the same values;
58 | if False, polygons are not dissolved and the process is rapider.
59 | field_name: name of the output vector field to store raster values
60 | (default = DN).
61 | extent_list: list of boundary coordinates left top right bottom.
62 | n_processes: number of parallel processes.
63 | available_ram: number of megabytes of RAM available to processes.
64 | progress_message: if True then start progress message, if False does
65 | not start the progress message (useful if launched from other tools).
66 |
67 | Returns:
68 | object :func:`~remotior_sensus.core.output_manager.OutputManager` with
69 | - path = output path
70 |
71 | Examples:
72 | Perform the conversion to vector of a raster
73 | >>> raster_to_vector(raster_path='file.tif',output_path='vector.gpkg')
74 | """ # noqa: E501
75 | cfg.logger.log.info('start')
76 | cfg.progress.update(
77 | process=__name__.split('.')[-1].replace('_', ' '), message='starting',
78 | start=progress_message
79 | )
80 | raster_path = files_directories.input_path(raster_path)
81 | if extent_list is not None:
82 | # prepare process files
83 | prepared = shared_tools.prepare_process_files(
84 | input_bands=[raster_path], output_path=output_path,
85 | n_processes=n_processes, box_coordinate_list=extent_list
86 | )
87 | input_raster_list = prepared['input_raster_list']
88 | raster_path = input_raster_list[0]
89 | if output_path is None:
90 | output_path = cfg.temp.temporary_file_path(name_suffix=cfg.gpkg_suffix)
91 | output_path = files_directories.output_path(output_path, cfg.gpkg_suffix)
92 | files_directories.create_parent_directory(output_path)
93 | if n_processes is None:
94 | n_processes = cfg.n_processes
95 | # perform conversion
96 | cfg.multiprocess.multiprocess_raster_to_vector(
97 | raster_path=raster_path, output_vector_path=output_path,
98 | field_name=field_name, n_processes=n_processes,
99 | dissolve_output=dissolve, min_progress=1, max_progress=100,
100 | available_ram=available_ram
101 | )
102 | cfg.progress.update(end=True)
103 | cfg.logger.log.info('end; output_path: %s' % output_path)
104 | return OutputManager(path=output_path)
105 |
--------------------------------------------------------------------------------
/docs/source/introduction.rst:
--------------------------------------------------------------------------------
1 |
2 | .. |fromGIStoRS| image:: _static/fromGIStoRS.png
3 | :width: 30pt
4 |
5 | .. |logo| image:: _static/logo.png
6 | :width: 32pt
7 |
8 |
9 | .. |br| raw:: html
10 |
11 |
12 |
13 |
14 | Introduction
15 | ===========================================
16 |
17 | |logo| Remotior Sensus, developed by Luca Congedo, is a Python package that allows
18 | for the processing of remote sensing images and GIS data.
19 |
20 | The main objective is to simplify the processing of remote sensing data
21 | through practical and integrated APIs that span from the download and
22 | preprocessing of satellite images to the postprocessing of classifications
23 | and GIS data.
24 | Basic dependencies are `NumPy `_,
25 | `SciPy `_ for calculations, and `GDAL `_
26 | for managing spatial data.
27 |
28 | The main features are:
29 |
30 | - **Search and Download** of remote sensing data such as Landsat and Sentinel-2.
31 | - **Preprocessing** of several products such as Landsat and Sentinel-2 images.
32 | - **Processing and postprocessing** tools to perform image classification through machine learning, manage GIS data and perform spatial analyses.
33 | - **Parallel processing** available for most processing tools.
34 |
35 |
36 | ``WARNING: Remotior Sensus is still in early development;
37 | new tools are going to be added, tools and APIs may change,
38 | and one may encounter issues and bugs using Remotior Sensus.``
39 |
40 | Management of Raster Bands
41 | __________________________
42 |
43 | Most tools accept raster bands as input, defined through the file path.
44 |
45 | In addition, raster bands can be managed through a catalog of BandSets
46 | (see :meth:`~remotior\_sensus.core.bandset\_catalog`),
47 | where each BandSet is an object that includes information about single bands
48 | (from the file path to the spatial and spectral characteristics).
49 | Bands in a BandSet can be referenced by the properties thereof,
50 | such as order number or center wavelength.
51 |
52 | .. image:: _static/bandset.jpg
53 | :align: center
54 |
55 | Multiple BandSets can be defined and identified by their reference number.
56 | Therefore, BandSets can be used as input for operations on multiple bands
57 | such as Principal Components Analysis, classification, mosaic,
58 | or band calculation.
59 |
60 | In band calculations (see :meth:`~remotior_sensus.tools.band_calc`)
61 | name alias of bands based on center wavelength (e.g. blue, red) can be used
62 | to simplify the structure of calculation expression.
63 |
64 |
65 | Performance
66 | ___________
67 |
68 | Most tools are designed to run in parallel processes, through a simple
69 | and effective parallelization approach based on dividing the raster input
70 | in sections that are distributed to available threads, maximizing the use
71 | of available RAM.
72 | This allows even complex algorithms to run in parallel.
73 | Optionally, the output file can be a virtual raster collecting the output
74 | rasters (corresponding to the sections) written independently by parallel
75 | processes; this avoids the time required to produce a unique raster output.
76 | Most tools allow for on the fly reprojection of input data.
77 |
78 | .. image:: _static/processing.jpg
79 | :align: center
80 |
81 |
82 | Machine Learning
83 | ________________
84 |
85 | Remotior Sensus optional dependencies are `PyTorch `_
86 | and `scikit-learn `_, which are
87 | integrated in the tool :meth:`~remotior\_sensus.tools.band\_classification`
88 | to allow for land cover classification through machine learning.
89 | The aim is to simplify the training process and development of the model.
90 |
91 | Source Code
92 | ___________
93 |
94 | The source code of Remotior Sensus is available
95 | at https://github.com/semiautomaticgit/remotior_sensus .
96 |
97 | To report issues please visit
98 | https://github.com/semiautomaticgit/remotior_sensus/issues .
99 |
100 | License of Remotior Sensus
101 | ''''''''''''''''''''''''''
102 | Remotior Sensus is free software: you can redistribute it and/or modify it
103 | under the terms of the GNU General Public License as published by
104 | the Free Software Foundation, either version 3 of the License,
105 | or (at your option) any later version.
106 | Remotior Sensus is distributed in the hope that it will be useful,
107 | but WITHOUT ANY WARRANTY; without even the implied warranty
108 | of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
109 | See the GNU General Public License for more details.
110 | You should have received a copy of the GNU General Public License
111 | along with Remotior Sensus. If not, see https://www.gnu.org/licenses/.
112 |
113 | How to cite
114 | __________________________
115 |
116 | Congedo, Luca, (2023). Remotior Sensus. https://github.com/semiautomaticgit/remotior_sensus
117 |
118 | Official site
119 | _____________
120 |
121 | For more information and tutorials visit the official site
122 |
123 | |fromGIStoRS| `From GIS to Remote Sensing
124 | `_
125 |
126 |
127 |
--------------------------------------------------------------------------------
/src/remotior_sensus/tools/raster_split.py:
--------------------------------------------------------------------------------
1 | # Remotior Sensus , software to process remote sensing and GIS data.
2 | # Copyright (C) 2022-2025 Luca Congedo.
3 | # Author: Luca Congedo
4 | # Email: ing.congedoluca@gmail.com
5 | #
6 | # This file is part of Remotior Sensus.
7 | # Remotior Sensus is free software: you can redistribute it and/or modify it
8 | # under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License,
10 | # or (at your option) any later version.
11 | # Remotior Sensus is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty
13 | # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | # See the GNU General Public License for more details.
15 | # You should have received a copy of the GNU General Public License
16 | # along with Remotior Sensus. If not, see .
17 | """
18 | Raster split.
19 |
20 | This tool allows for splitting a raster to single bands.
21 |
22 | Typical usage example:
23 |
24 | >>> # import Remotior Sensus and start the session
25 | >>> import remotior_sensus
26 | >>> rs = remotior_sensus.Session()
27 | >>> # start the process
28 | >>> split = rs.raster_split(raster_path='input_path',
29 | ... output_path='output_path')
30 | """ # noqa: E501
31 |
32 | from typing import Optional
33 |
34 | from remotior_sensus.core import configurations as cfg
35 | from remotior_sensus.core.output_manager import OutputManager
36 | from remotior_sensus.util import (
37 | files_directories, raster_vector, shared_tools
38 | )
39 |
40 |
41 | def raster_split(
42 | raster_path: str, output_path: str = None,
43 | prefix: Optional[str] = None, extent_list: Optional[list] = None,
44 | n_processes: Optional[int] = None,
45 | virtual_output: Optional[bool] = None,
46 | progress_message: Optional[bool] = True
47 | ) -> OutputManager:
48 | """Split a multiband raster to single bands.
49 |
50 | This tool allows for splitting a multiband raster to single bands.
51 |
52 | Args:
53 | raster_path: path of raster used as input.
54 | output_path: string of output directory path.
55 | prefix: optional string for output name prefix.
56 | extent_list: list of boundary coordinates left top right bottom.
57 | n_processes: number of parallel processes.
58 | virtual_output: if True (and output_path is directory), save output
59 | as virtual raster.
60 | progress_message: if True then start progress message, if False does
61 | not start the progress message (useful if launched from other tools).
62 |
63 | Returns:
64 | object :func:`~remotior_sensus.core.output_manager.OutputManager` with
65 | - path = output path
66 |
67 | Examples:
68 | Perform the split of a raster
69 | >>> split = raster_split(raster_path='input_path',
70 | ... output_path='output_path')
71 | """ # noqa: E501
72 | cfg.logger.log.info('start')
73 | cfg.progress.update(
74 | process=__name__.split('.')[-1].replace('_', ' '), message='starting',
75 | start=progress_message
76 | )
77 | raster_path = files_directories.input_path(raster_path)
78 | # prepare process files
79 | prepared = shared_tools.prepare_process_files(
80 | input_bands=[raster_path], output_path=output_path,
81 | n_processes=n_processes, box_coordinate_list=extent_list
82 | )
83 | raster_info = prepared['raster_info']
84 | output_list = []
85 | bands = raster_info[0][5]
86 | output_path = output_path.replace('\\', '/').replace('//', '/')
87 | if output_path.endswith('/'):
88 | output_path = output_path[:-1]
89 | if prefix is None:
90 | prefix = 'band'
91 | for band in range(bands):
92 | files_directories.create_parent_directory(output_path)
93 | out_path = '%s/%s%s' % (output_path, prefix, str(band + 1))
94 | if virtual_output is True:
95 | virtual_path = files_directories.output_path(out_path,
96 | cfg.vrt_suffix)
97 | output = virtual_path
98 | else:
99 | virtual_path = cfg.temp.temporary_file_path(
100 | name_suffix=cfg.vrt_suffix)
101 | output = files_directories.output_path(out_path,
102 | cfg.tif_suffix)
103 | raster_vector.create_virtual_raster(
104 | input_raster_list=[raster_path], output=virtual_path,
105 | band_number_list=[[band + 1]], box_coordinate_list=extent_list,
106 | relative_to_vrt=False
107 | )
108 | if virtual_output is not True:
109 | raster_vector.gdal_copy_raster(
110 | input_raster=virtual_path, output=output
111 | )
112 | output_list.append(output)
113 | cfg.progress.update(
114 | message='splitting', step=band, steps=bands, minimum=1,
115 | maximum=99, percentage=int(100 * band / bands)
116 | )
117 | cfg.progress.update(end=True)
118 | cfg.logger.log.info('end; raster split: %s' % str(output_list))
119 | return OutputManager(paths=output_list)
120 |
--------------------------------------------------------------------------------
/src/remotior_sensus/core/output_manager.py:
--------------------------------------------------------------------------------
1 | # Remotior Sensus , software to process remote sensing and GIS data.
2 | # Copyright (C) 2022-2025 Luca Congedo.
3 | # Author: Luca Congedo
4 | # Email: ing.congedoluca@gmail.com
5 | #
6 | # This file is part of Remotior Sensus.
7 | # Remotior Sensus is free software: you can redistribute it and/or modify it
8 | # under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License,
10 | # or (at your option) any later version.
11 | # Remotior Sensus is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty
13 | # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | # See the GNU General Public License for more details.
15 | # You should have received a copy of the GNU General Public License
16 | # along with Remotior Sensus. If not, see .
17 | """Output manager.
18 |
19 | Core class that manages several types of output, mainly intended for tools
20 | that have several outputs.
21 |
22 | Typical usage example:
23 |
24 | >>> # process output is checked
25 | >>> OutputManager()
26 | """
27 |
28 | from remotior_sensus.core.bandset_catalog import BandSetCatalog
29 |
30 |
31 | class OutputManager(object):
32 | """Manages output.
33 |
34 | This class manages several types of output, mainly intended for tools
35 | that have several outputs.
36 | Check argument is False if output failed.
37 | Single output raster or multiple file paths can be defined as arguments.
38 | Additional output files or tables are managed with an extra argument.
39 | The type of the extra argument can be flexible depending on the process
40 | output.
41 |
42 | Attributes:
43 | check: True if output is as expected, False if process failed.
44 | path: path of the first output.
45 | paths: list of output paths in case of multiple outputs.
46 | extra: additional output elements depending on the process.
47 |
48 | Examples:
49 | Output failed
50 | >>> OutputManager(check=False)
51 |
52 | Output is checked and file path is provided
53 | >>> OutputManager(path='file.tif')
54 | """ # noqa: E501
55 |
56 | def __init__(
57 | self, check: bool = True, path: str = None, paths: list = None,
58 | extra=None
59 | ):
60 | """Initializes an Output.
61 |
62 | Initializes an Output.
63 |
64 | Args:
65 | check: True if output is as expected, False if process failed.
66 | path: path of the first output.
67 | paths: list of output paths in case of multiple outputs.
68 | extra: additional output elements depending on the process.
69 |
70 | Examples:
71 | Create an object with a single file path
72 | >>> OutputManager(path='file.tif')
73 |
74 | Create an object with several output file paths in a list and an extra argument for a dictionary
75 | >>> OutputManager(
76 | ... paths=['file1.tif', 'file2.tif'],
77 | ... extra={'additional_output': 'file.csv'}
78 | ... )
79 | )
80 | """ # noqa: E501
81 | self.check = check
82 | self.paths = paths
83 | if path is None:
84 | if paths is None:
85 | self.path = None
86 | elif len(paths) == 0:
87 | self.path = None
88 | else:
89 | self.path = paths[0]
90 | else:
91 | self.path = path
92 | self.extra = extra
93 |
94 | def add_to_bandset(
95 | self, bandset_catalog: BandSetCatalog, bandset_number=None,
96 | band_number=None, raster_band=None, band_name=None, date=None,
97 | unit=None, root_directory=None, multiplicative_factor=None,
98 | additive_factor=None, wavelength=None
99 | ):
100 | """Adds output to BandSet.
101 |
102 | Adds the OutputManager.path as a band to a BandSet in a BandSetCatalog.
103 |
104 | Args:
105 | bandset_catalog: BandSetCatalog object.
106 | band_name: raster name used for identifying the bands.
107 | wavelength: center wavelengths of band.
108 | unit: wavelength unit as string
109 | multiplicative_factor: multiplicative factor for bands during calculations.
110 | additive_factor: additive factors for band during calculations.
111 | date: date string (format YYYY-MM-DD).
112 | bandset_number: number of the BandSet; if None, the band is added to the current BandSet.
113 | root_directory: root directory for relative path.
114 | raster_band: raster band number.
115 | band_number: number of band in BandSet.
116 |
117 | Examples:
118 | Add the output to BandSet 1 as band 1.
119 | >>> catalog = BandSetCatalog()
120 | >>> OutputManager.add_to_bandset(
121 | ... bandset_catalog=catalog, bandset_number=1, band_number=1
122 | ... )
123 | """ # noqa: E501
124 | if type(bandset_catalog) is BandSetCatalog:
125 | bandset_catalog.add_band_to_bandset(
126 | path=self.path, bandset_number=bandset_number,
127 | band_number=band_number, raster_band=raster_band,
128 | band_name=band_name, date=date, unit=unit,
129 | root_directory=root_directory,
130 | multiplicative_factor=multiplicative_factor,
131 | additive_factor=additive_factor, wavelength=wavelength
132 | )
133 | else:
134 | raise Exception('bandset catalog not found')
135 |
--------------------------------------------------------------------------------
/src/remotior_sensus/core/log.py:
--------------------------------------------------------------------------------
1 | # Remotior Sensus , software to process remote sensing and GIS data.
2 | # Copyright (C) 2022-2025 Luca Congedo.
3 | # Author: Luca Congedo
4 | # Email: ing.congedoluca@gmail.com
5 | #
6 | # This file is part of Remotior Sensus.
7 | # Remotior Sensus is free software: you can redistribute it and/or modify it
8 | # under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License,
10 | # or (at your option) any later version.
11 | # Remotior Sensus is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty
13 | # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | # See the GNU General Public License for more details.
15 | # You should have received a copy of the GNU General Public License
16 | # along with Remotior Sensus. If not, see .
17 | """Logging manger.
18 |
19 | Core class that manages logs during processes.
20 |
21 | Typical usage example:
22 |
23 | >>> # create a log file in a directory
24 | >>> Log(directory='directory_path', level=10)
25 | """
26 |
27 | import io
28 | import logging
29 | from typing import Union, Optional
30 |
31 | from remotior_sensus.core import configurations as cfg
32 |
33 |
34 | class Log(object):
35 | log = None
36 |
37 | def __init__(
38 | self, file_path: Optional[str] = None,
39 | directory: Optional[str] = None, level: Union[int, str] = None,
40 | multiprocess=False, time=True, stream_handler=True
41 | ):
42 | """Manages logs.
43 |
44 | This module allows for managing logs of processes.
45 |
46 | Attributes:
47 | file_path: path of a log file.
48 | directory: directory path where a log file is created if file_path is None.
49 | level: level of logging (10 for DEBUG, 20 for INFO).
50 | multiprocess: if True, sets logging for parallel processes.
51 | time: if True, time is saved in log file.
52 | stream_handler: if True, create stream handler.
53 |
54 | Examples:
55 | Create a log file and starts logging.
56 | >>> Log(file_path='file.txt', level=20)
57 | """ # noqa: E501
58 | if file_path is None:
59 | if directory is None:
60 | raise Exception('file path or directory missing')
61 | else:
62 | file_path = '{}/{}.log'.format(directory, cfg.root_name)
63 | # create logger
64 | logger = logging.getLogger(__name__)
65 | logging.basicConfig(level=logging.DEBUG)
66 | if level is None:
67 | level = logging.DEBUG
68 | if not multiprocess:
69 | # create file handler
70 | fh = logging.FileHandler(file_path)
71 | fh.setLevel(level)
72 | fhf = logging.Formatter(
73 | '%(levelname)s|%(asctime)s.%(msecs)03d|%(module)s|%(funcName)s'
74 | '|%(lineno)s|%(message)s', '%Y-%m-%dT%H:%M:%S'
75 | )
76 | fh.setFormatter(fhf)
77 | if logger.hasHandlers():
78 | # try to close handlers
79 | try:
80 | for fh in logger.handlers:
81 | fh.close()
82 | except Exception as err:
83 | str(err)
84 | logger.handlers.clear()
85 | logger.addHandler(fh)
86 | # create console handler
87 | if stream_handler:
88 | ch = logging.StreamHandler()
89 | ch.setLevel(level)
90 | if time:
91 | chf = logging.Formatter(
92 | '%(levelname)s[%(asctime)s.%(msecs)03d] '
93 | '%(module)s.%(funcName)s[%(lineno)s] %(message)s',
94 | '%Y-%m-%dT%H:%M:%S'
95 | )
96 | else:
97 | chf = logging.Formatter(
98 | '%(levelname)s %(module)s.%(funcName)s[%(lineno)s] '
99 | '%(message)s'
100 | )
101 | ch.setFormatter(chf)
102 | logger.addHandler(ch)
103 | logger.propagate = False
104 | self.log = logger
105 | self.file_path = file_path
106 | self.stream = None
107 | self.level = level
108 | # multiprocess number
109 | else:
110 | # create stream handler
111 | stream = io.StringIO()
112 | ch = logging.StreamHandler(stream)
113 | ch.setLevel(level)
114 | if time:
115 | chf = logging.Formatter(
116 | '%(levelname)s_p{}|%(asctime)s.%(msecs)03d|%(module)s'
117 | '|%(funcName)s|%(lineno)s|%(message)s'.format(
118 | multiprocess
119 | ), '%Y-%m-%dT%H:%M:%S'
120 | )
121 | else:
122 | chf = logging.Formatter(
123 | '%(levelname)s_p{}|%(module)s|%(funcName)s|%(lineno)s'
124 | '|%(message)s'.format(multiprocess)
125 | )
126 | ch.setFormatter(chf)
127 | if logger.hasHandlers():
128 | # try to close handlers
129 | try:
130 | for fh in logger.handlers:
131 | fh.close()
132 | except Exception as err:
133 | str(err)
134 | logger.handlers.clear()
135 | logger.addHandler(ch)
136 | logger.propagate = False
137 | self.log = logger
138 | self.stream = stream
139 | self.file_path = None
140 | self.level = level
141 |
142 | def set_level(self, level):
143 | for h in self.log.handlers:
144 | h.setLevel(level)
145 |
--------------------------------------------------------------------------------
/README.rst:
--------------------------------------------------------------------------------
1 | .. image:: https://img.shields.io/badge/Website-darkgreen
2 | :target: https://fromgistors.blogspot.com/p/remotior-sensus.html
3 |
4 | .. image:: https://img.shields.io/badge/Documentation-blue
5 | :target: https://remotior-sensus.readthedocs.io
6 |
7 | .. image:: https://img.shields.io/badge/Bug%20reports-red
8 | :target: https://github.com/semiautomaticgit/remotior_sensus/issues
9 |
10 | .. image:: https://img.shields.io/pypi/v/remotior-sensus?label=PyPI%20version
11 | :target: https://pypi.org/project/remotior-sensus
12 |
13 | .. image:: https://img.shields.io/pypi/dm/remotior-sensus?label=PyPI%20downloads
14 | :target: https://pypi.org/project/remotior-sensus
15 |
16 | .. image:: https://img.shields.io/conda/v/conda-forge/remotior-sensus?label=Conda%20version
17 | :target: https://anaconda.org/conda-forge/remotior-sensus
18 |
19 | .. image:: https://img.shields.io/conda/d/conda-forge/remotior-sensus?label=Conda%20downloads
20 | :target: https://anaconda.org/conda-forge/remotior-sensus
21 |
22 | .. image:: https://img.shields.io/conda/l/conda-forge/remotior-sensus
23 | :target: https://www.gnu.org/licenses/
24 |
25 | .. image:: https://zenodo.org/badge/DOI/10.5281/zenodo.10038132.svg
26 | :target: https://doi.org/10.5281/zenodo.10038132
27 |
28 | .. image:: https://colab.research.google.com/assets/colab-badge.svg
29 | :target: https://remotior-sensus.readthedocs.io/en/latest/quickstart.html
30 |
31 |
32 |
33 |
34 | Introduction
35 | ===========================================
36 |
37 | Remotior Sensus (which is Latin for "a more remote sense") is a Python package
38 | that allows for the processing of remote sensing images and GIS data.
39 |
40 | Remotior Sensus is developed by Luca Congedo.
41 |
42 | - **Website:** https://fromgistors.blogspot.com/p/remotior-sensus.html
43 | - **Documentation:** https://remotior-sensus.readthedocs.io
44 | - **Source code:** https://github.com/semiautomaticgit/remotior_sensus
45 | - **Bug reports:** https://github.com/semiautomaticgit/remotior_sensus/issues
46 |
47 | The main objective is to simplify the processing of remote sensing data
48 | through practical and integrated APIs that span from the download and
49 | preprocessing of satellite images to the postprocessing of classifications
50 | and GIS data.
51 | Basic dependencies are `NumPy `_,
52 | `SciPy `_ for calculations, and `GDAL `_
53 | for managing spatial data.
54 | Optionally, `Matplotlib` is used to display spectral signature plots.
55 |
56 | The main features are:
57 |
58 | - **Search and Download** of remote sensing data such as Landsat and Sentinel-2.
59 | - **Preprocessing** of several products such as Landsat and Sentinel-2 images.
60 | - **Processing and postprocessing** tools to perform image classification through machine learning, manage GIS data and perform spatial analyses.
61 | - **Parallel processing** available for most processing tools.
62 |
63 | ``WARNING: Remotior Sensus is still in early development;
64 | new tools are going to be added, tools and APIs may change,
65 | and one may encounter issues and bugs using Remotior Sensus.``
66 |
67 | Management of Raster Bands
68 | __________________________
69 |
70 | Most tools accept raster bands as input, defined through the file path.
71 |
72 | In addition, raster bands can be managed through a catalog of BandSets,
73 | where each BandSet is an object that includes information about single bands
74 | (from the file path to the spatial and spectral characteristics).
75 | Bands in a BandSet can be referenced by the properties thereof,
76 | such as order number or center wavelength.
77 |
78 | Multimple BandSets can be defined and identified by their reference number.
79 | Therefore, BandSets can be used as input for operations on multiple bands
80 | such as Principal Components Analysis, classification, mosaic,
81 | or band calculation.
82 |
83 | In band calculations, alias name of bands based on center wavelength
84 | (e.g. blue, red) can be used to simplify the structure of calculation expression.
85 |
86 | Performance
87 | ___________
88 |
89 | Most tools are designed to run in parallel processes, through a simple
90 | and effective parallelization approach based on dividing the raster input
91 | in sections that are distributed to available threads, maximizing the use
92 | of available RAM.
93 | This allows even complex algorithms to run in parallel.
94 | Optionally, the output file can be a virtual raster collecting the output
95 | rasters (corresponding to the sections) written independently by parallel
96 | processes; this avoids the time required to produce a unique raster output.
97 | Most tools allow for on the fly reprojection of input data.
98 |
99 | Machine Learning
100 | ________________
101 |
102 | Remotior Sensus optional dependencies are `PyTorch `_
103 | and `scikit-learn `_, which are
104 | integrated in the classification tool.
105 | to allow for land cover classification through machine learning.
106 | The aim is to simplify the training process and development of the model.
107 |
108 | Installation
109 | ______________
110 |
111 | Remotior Sensus requires `GDAL`, `NumPy` and `SciPy` for most functionalities.
112 | Also, `scikit-learn` and `PyTorch` are optional but required for machine learning.
113 | Optionally, `Matplotlib` is used to display spectral signature plots.
114 |
115 | It is recommended to install Remotior Sensus using a `Conda` environment.
116 |
117 | .. code-block:: console
118 |
119 | $ conda install -c conda-forge remotior-sensus scikit-learn pytorch
120 |
121 |
122 |
123 | License of Remotior Sensus
124 | ''''''''''''''''''''''''''
125 | Remotior Sensus is free software: you can redistribute it and/or modify it
126 | under the terms of the GNU General Public License as published by
127 | the Free Software Foundation, either version 3 of the License,
128 | or (at your option) any later version.
129 | Remotior Sensus is distributed in the hope that it will be useful,
130 | but WITHOUT ANY WARRANTY; without even the implied warranty
131 | of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
132 | See the GNU General Public License for more details.
133 | You should have received a copy of the GNU General Public License
134 | along with Remotior Sensus. If not, see https://www.gnu.org/licenses/.
135 |
136 |
137 | Official site
138 | _____________
139 |
140 | For more information and tutorials visit the official site
141 |
142 | `From GIS to Remote Sensing
143 | `_
144 |
--------------------------------------------------------------------------------
/src/remotior_sensus/tools/band_sieve.py:
--------------------------------------------------------------------------------
1 | # Remotior Sensus , software to process remote sensing and GIS data.
2 | # Copyright (C) 2022-2025 Luca Congedo.
3 | # Author: Luca Congedo
4 | # Email: ing.congedoluca@gmail.com
5 | #
6 | # This file is part of Remotior Sensus.
7 | # Remotior Sensus is free software: you can redistribute it and/or modify it
8 | # under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License,
10 | # or (at your option) any later version.
11 | # Remotior Sensus is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty
13 | # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | # See the GNU General Public License for more details.
15 | # You should have received a copy of the GNU General Public License
16 | # along with Remotior Sensus. If not, see .
17 | """Band sieve.
18 |
19 | This tool allows for performing the sieve of raster bands removing
20 | patches having size lower than a threshold (i.e. number of pixels).
21 |
22 | Typical usage example:
23 |
24 | >>> # import Remotior Sensus and start the session
25 | >>> import remotior_sensus
26 | >>> rs = remotior_sensus.Session()
27 | >>> # start the process
28 | >>> sieve = rs.band_sieve(
29 | ... input_bands=['file1.tif', 'file2.tif'],size=2,
30 | ... output_path='directory_path', connected=False,prefix='sieve_'
31 | ... )
32 | """
33 |
34 | from typing import Union, Optional
35 |
36 | from remotior_sensus.core import configurations as cfg
37 | from remotior_sensus.core.bandset_catalog import BandSet
38 | from remotior_sensus.core.bandset_catalog import BandSetCatalog
39 | from remotior_sensus.core.output_manager import OutputManager
40 | from remotior_sensus.util import shared_tools
41 |
42 |
43 | def band_sieve(
44 | input_bands: Union[list, int, BandSet], size: int,
45 | output_path: Union[list, str] = None, connected: Optional[bool] = None,
46 | overwrite: Optional[bool] = False,
47 | prefix: Optional[str] = '', extent_list: Optional[list] = None,
48 | multiple_resolution: Optional[bool] = True,
49 | n_processes: Optional[int] = None,
50 | available_ram: Optional[int] = None,
51 | bandset_catalog: Optional[BandSetCatalog] = None,
52 | virtual_output: Optional[bool] = None,
53 | progress_message: Optional[bool] = True
54 | ) -> OutputManager:
55 | """Perform band sieve.
56 |
57 | This tool allows for performing the sieve of raster bands removing
58 | patches having size lower than a threshold (i.e. number of pixels).
59 |
60 | Args:
61 | input_bands: input of type BandSet or list of paths or integer
62 | number of BandSet.
63 | output_path: string of output path directory or list of paths.
64 | overwrite: if True, output overwrites existing files.
65 | size: size of dilation in pixels.
66 | virtual_output: if True (and output_path is directory), save output
67 | as virtual raster of multiprocess parts
68 | connected: if True, consider 8 pixel connection; if False, consider 4
69 | pixel connection.
70 | prefix: optional string for output name prefix.
71 | extent_list: list of boundary coordinates left top right bottom.
72 | multiple_resolution: if True, keep the original resolution of
73 | individual raster;
74 | if False, use the resolution of the first raster for all the bands.
75 | n_processes: number of parallel processes.
76 | available_ram: number of megabytes of RAM available to processes.
77 | bandset_catalog: optional type BandSetCatalog for BandSet number.
78 | progress_message: if True then start progress message, if False does
79 | not start the progress message (useful if launched from other tools).
80 |
81 | Returns:
82 | Object :func:`~remotior_sensus.core.output_manager.OutputManager` with
83 | - paths = output list
84 |
85 | Examples:
86 | Perform the sieve of size 3 with connected pixel (8 connection)
87 | >>> sieve = band_sieve(
88 | ... input_bands=['file1.tif', 'file2.tif'], size=3,
89 | ... output_path='directory_path', connected=True, prefix='sieve_'
90 | ... )
91 | """ # noqa: E501
92 | cfg.logger.log.info('start')
93 | cfg.progress.update(
94 | process=__name__.split('.')[-1].replace('_', ' '), message='starting',
95 | start=progress_message
96 | )
97 | # prepare process files
98 | prepared = shared_tools.prepare_process_files(
99 | input_bands=input_bands, output_path=output_path, overwrite=overwrite,
100 | n_processes=n_processes, bandset_catalog=bandset_catalog,
101 | box_coordinate_list=extent_list,
102 | prefix=prefix, multiple_output=True, multiple_input=True,
103 | multiple_resolution=multiple_resolution,
104 | virtual_output=virtual_output
105 | )
106 | input_raster_list = prepared['input_raster_list']
107 | raster_info = prepared['raster_info']
108 | n_processes = prepared['n_processes']
109 | nodata_list = prepared['nodata_list']
110 | output_list = prepared['output_list']
111 | # 4 connected pixels
112 | if connected:
113 | connected = 8
114 | elif not connected:
115 | connected = 4
116 | else:
117 | connected = 4
118 | # process calculation
119 | n = 0
120 | min_p = 1
121 | max_p = int((99 - 1) / len(input_raster_list))
122 | for i in input_raster_list:
123 | cfg.progress.update(message='processing raster %s' % (n + 1))
124 | out = output_list[n]
125 | nd = nodata_list[n]
126 | data_type = raster_info[n][8]
127 | # perform sieve
128 | cfg.multiprocess.multiprocess_raster_sieve(
129 | raster_path=i, n_processes=n_processes,
130 | available_ram=available_ram, sieve_size=size,
131 | connected=connected, output_nodata_value=nd, output=out,
132 | output_data_type=data_type, compress=cfg.raster_compression,
133 | min_progress=min_p + max_p * n,
134 | max_progress=min_p + max_p * (n + 1)
135 | )
136 | n += 1
137 | cfg.progress.update(end=True)
138 | cfg.logger.log.info('end; band sieve: %s' % output_list)
139 | return OutputManager(paths=output_list)
140 |
--------------------------------------------------------------------------------
/src/remotior_sensus/tools/band_dilation.py:
--------------------------------------------------------------------------------
1 | # Remotior Sensus , software to process remote sensing and GIS data.
2 | # Copyright (C) 2022-2025 Luca Congedo.
3 | # Author: Luca Congedo
4 | # Email: ing.congedoluca@gmail.com
5 | #
6 | # This file is part of Remotior Sensus.
7 | # Remotior Sensus is free software: you can redistribute it and/or modify it
8 | # under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License,
10 | # or (at your option) any later version.
11 | # Remotior Sensus is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty
13 | # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | # See the GNU General Public License for more details.
15 | # You should have received a copy of the GNU General Public License
16 | # along with Remotior Sensus. If not, see .
17 | """Band dilation.
18 |
19 | This tool allows for the spatial dilation, through a moving window,
20 | of band pixels selected by values.
21 |
22 | Typical usage example:
23 |
24 | >>> # import Remotior Sensus and start the session
25 | >>> import remotior_sensus
26 | >>> rs = remotior_sensus.Session()
27 | >>> # start the process
28 | >>> dilation = rs.band_dilation(input_bands=['file1.tif', 'file2.tif'],
29 | ... value_list=[1], size=3, output_path='directory_path',
30 | ... circular_structure=True, prefix='dilation_')
31 | """
32 |
33 | from typing import Union, Optional
34 |
35 | from remotior_sensus.core import configurations as cfg
36 | from remotior_sensus.core.bandset_catalog import BandSet
37 | from remotior_sensus.core.bandset_catalog import BandSetCatalog
38 | from remotior_sensus.core.output_manager import OutputManager
39 | from remotior_sensus.core.processor_functions import raster_dilation
40 | from remotior_sensus.util import shared_tools
41 |
42 |
43 | def band_dilation(
44 | input_bands: Union[list, int, BandSet], value_list: list, size: int,
45 | output_path: Union[list, str] = None,
46 | overwrite: Optional[bool] = False,
47 | circular_structure: Optional[bool] = None,
48 | prefix: Optional[str] = '', extent_list: Optional[list] = None,
49 | multiple_resolution: Optional[bool] = True,
50 | n_processes: Optional[int] = None,
51 | available_ram: Optional[int] = None,
52 | bandset_catalog: Optional[BandSetCatalog] = None,
53 | virtual_output: Optional[bool] = None,
54 | progress_message: Optional[bool] = True
55 | ) -> OutputManager:
56 | """Perform dilation of band pixels.
57 |
58 | This tool performs the dilation of pixels identified by a list of values.
59 | A new raster is created for each input band.
60 |
61 | Args:
62 | input_bands: input of type BandSet or list of paths or integer
63 | number of BandSet.
64 | output_path: string of output path directory or list of paths.
65 | overwrite: if True, output overwrites existing files.
66 | value_list: list of values for dilation.
67 | size: size of dilation in pixels.
68 | virtual_output: if True (and output_path is directory), save output
69 | as virtual raster of multiprocess parts
70 | circular_structure: if True, use circular structure; if False, square
71 | structure.
72 | prefix: optional string for output name prefix.
73 | extent_list: list of boundary coordinates left top right bottom.
74 | multiple_resolution: if True, keep the original resolution of
75 | individual raster;
76 | if False, use the resolution of the first raster for all the bands.
77 | n_processes: number of parallel processes.
78 | available_ram: number of megabytes of RAM available to processes.
79 | bandset_catalog: optional type BandSetCatalog for BandSet number.
80 | progress_message: if True then start progress message, if False does
81 | not start the progress message (useful if launched from other tools).
82 |
83 | Returns:
84 | Object :func:`~remotior_sensus.core.output_manager.OutputManager` with
85 | - paths = output list
86 |
87 | Examples:
88 | Perform the dilation of size 5 for value 1 and 2
89 | >>> dilation = band_dilation(input_bands=['path_1', 'path_2'],value_list=[1, 2],size=5,output_path='directory_path',circular_structure=True)
90 | """ # noqa: E501
91 | cfg.logger.log.info('start')
92 | cfg.progress.update(
93 | process=__name__.split('.')[-1].replace('_', ' '), message='starting',
94 | start=progress_message
95 | )
96 | # prepare process files
97 | prepared = shared_tools.prepare_process_files(
98 | input_bands=input_bands, output_path=output_path, overwrite=overwrite,
99 | n_processes=n_processes, box_coordinate_list=extent_list,
100 | bandset_catalog=bandset_catalog, prefix=prefix,
101 | multiple_output=True, multiple_input=True,
102 | multiple_resolution=multiple_resolution,
103 | virtual_output=virtual_output
104 | )
105 | input_raster_list = prepared['input_raster_list']
106 | raster_info = prepared['raster_info']
107 | n_processes = prepared['n_processes']
108 | nodata_list = prepared['nodata_list']
109 | output_list = prepared['output_list']
110 | vrt_list = prepared['vrt_list']
111 | if not circular_structure:
112 | structure = shared_tools.create_base_structure(size * 2 + 1)
113 | else:
114 | structure = shared_tools.create_circular_structure(size)
115 | # process calculation
116 | n = 0
117 | min_p = 1
118 | max_p = int((99 - 1) / len(input_raster_list))
119 | # dummy bands for memory calculation as the number of values
120 | dummy_bands = len(value_list) + 4
121 | for i in input_raster_list:
122 | out = output_list[n]
123 | nd = nodata_list[n]
124 | data_type = raster_info[n][8]
125 | cfg.multiprocess.run(
126 | raster_path=i, function=raster_dilation,
127 | function_argument=structure, n_processes=n_processes,
128 | available_ram=available_ram,
129 | function_variable=value_list, output_raster_path=out,
130 | output_data_type=data_type, output_nodata_value=nd,
131 | compress=cfg.raster_compression, dummy_bands=dummy_bands,
132 | boundary_size=structure.shape[0] + 1, virtual_raster=vrt_list[n],
133 | progress_message='processing raster %s' % (n + 1),
134 | min_progress=min_p + max_p * n,
135 | max_progress=min_p + max_p * (n + 1)
136 | )
137 | n += 1
138 | cfg.progress.update(end=True)
139 | cfg.logger.log.info('end; band dilation: %s' % output_list)
140 | return OutputManager(paths=output_list)
141 |
--------------------------------------------------------------------------------
/src/remotior_sensus/tools/band_erosion.py:
--------------------------------------------------------------------------------
1 | # Remotior Sensus , software to process remote sensing and GIS data.
2 | # Copyright (C) 2022-2025 Luca Congedo.
3 | # Author: Luca Congedo
4 | # Email: ing.congedoluca@gmail.com
5 | #
6 | # This file is part of Remotior Sensus.
7 | # Remotior Sensus is free software: you can redistribute it and/or modify it
8 | # under the terms of the GNU General Public License as published by
9 | # the Free Software Foundation, either version 3 of the License,
10 | # or (at your option) any later version.
11 | # Remotior Sensus is distributed in the hope that it will be useful,
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty
13 | # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 | # See the GNU General Public License for more details.
15 | # You should have received a copy of the GNU General Public License
16 | # along with Remotior Sensus. If not, see .
17 | """Band erosion.
18 |
19 | This tool allows for the spatial erosion, through a moving window,
20 | of band pixels selected by values.
21 |
22 | Typical usage example:
23 |
24 | >>> # import Remotior Sensus and start the session
25 | >>> import remotior_sensus
26 | >>> rs = remotior_sensus.Session()
27 | >>> # start the process
28 | >>> erosion = rs.band_erosion(input_bands=['file1.tif', 'file2.tif'],
29 | ... value_list=[1], size=1, output_path='directory_path',
30 | ... circular_structure=True,prefix='erosion_')
31 | """
32 |
33 | from typing import Union, Optional
34 |
35 | from remotior_sensus.core import configurations as cfg
36 | from remotior_sensus.core.bandset_catalog import BandSet
37 | from remotior_sensus.core.bandset_catalog import BandSetCatalog
38 | from remotior_sensus.core.output_manager import OutputManager
39 | from remotior_sensus.core.processor_functions import raster_erosion
40 | from remotior_sensus.util import shared_tools
41 |
42 |
43 | def band_erosion(
44 | input_bands: Union[list, int, BandSet], value_list: list, size: int,
45 | output_path: Union[list, str] = None,
46 | overwrite: Optional[bool] = False,
47 | circular_structure: Optional[bool] = None,
48 | prefix: Optional[str] = '', extent_list: Optional[list] = None,
49 | multiple_resolution: Optional[bool] = True,
50 | n_processes: Optional[int] = None,
51 | available_ram: Optional[int] = None,
52 | bandset_catalog: Optional[BandSetCatalog] = None,
53 | virtual_output: Optional[bool] = None,
54 | progress_message: Optional[bool] = True
55 | ) -> OutputManager:
56 | """Perform erosion of band pixels.
57 |
58 | This tool performs the erosion of pixels identified by a list of values.
59 | A new raster is created for each input band.
60 |
61 | Args:
62 | input_bands: input of type BandSet or list of paths or integer
63 | number of BandSet.
64 | output_path: string of output path directory or list of paths.
65 | overwrite: if True, output overwrites existing files.
66 | value_list: list of values for dilation.
67 | size: size of dilation in pixels.
68 | virtual_output: if True (and output_path is directory), save output
69 | as virtual raster of multiprocess parts.
70 | circular_structure: if True, use circular structure; if False, square
71 | structure.
72 | prefix: optional string for output name prefix.
73 | extent_list: list of boundary coordinates left top right bottom.
74 | multiple_resolution: if True, keep the original resolution of
75 | individual raster;
76 | if False, use the resolution of the first raster for all the bands.
77 | n_processes: number of parallel processes.
78 | available_ram: number of megabytes of RAM available to processes.
79 | bandset_catalog: optional type BandSetCatalog for BandSet number.
80 | progress_message: if True then start progress message, if False does
81 | not start the progress message (useful if launched from other tools).
82 |
83 | Returns:
84 | Object :func:`~remotior_sensus.core.output_manager.OutputManager` with
85 | - paths = output list
86 |
87 | Examples:
88 | Perform the erosion of size 1 for value 1 and 2
89 | >>> erosion = band_erosion(
90 | ... input_bands=['path_1', 'path_2'], value_list=[1, 2], size=1,
91 | ... output_path='directory_path', circular_structure=True
92 | ... )
93 | """ # noqa: E501
94 | cfg.logger.log.info('start')
95 | cfg.progress.update(
96 | process=__name__.split('.')[-1].replace('_', ' '), message='starting',
97 | start=progress_message
98 | )
99 | # prepare process files
100 | prepared = shared_tools.prepare_process_files(
101 | input_bands=input_bands, output_path=output_path, overwrite=overwrite,
102 | n_processes=n_processes, bandset_catalog=bandset_catalog,
103 | prefix=prefix, box_coordinate_list=extent_list,
104 | multiple_output=True, multiple_input=True,
105 | multiple_resolution=multiple_resolution,
106 | virtual_output=virtual_output
107 | )
108 | input_raster_list = prepared['input_raster_list']
109 | raster_info = prepared['raster_info']
110 | n_processes = prepared['n_processes']
111 | nodata_list = prepared['nodata_list']
112 | output_list = prepared['output_list']
113 | vrt_list = prepared['vrt_list']
114 | if not circular_structure:
115 | structure = shared_tools.create_base_structure(3)
116 | else:
117 | structure = shared_tools.create_circular_structure(1)
118 | # process calculation
119 | n = 0
120 | min_p = 1
121 | max_p = int((99 - 1) / len(input_raster_list))
122 | for i in input_raster_list:
123 | cfg.progress.update(message='processing raster %s' % (n + 1))
124 | out = output_list[n]
125 | nd = nodata_list[n]
126 | data_type = raster_info[n][8]
127 | # dummy bands for memory calculation
128 | dummy_bands = 7
129 | cfg.multiprocess.run(
130 | raster_path=i, function=raster_erosion,
131 | function_argument=structure, function_variable=[size, value_list],
132 | output_raster_path=out, output_data_type=data_type,
133 | n_processes=n_processes, available_ram=available_ram,
134 | output_nodata_value=nd, compress=cfg.raster_compression,
135 | dummy_bands=dummy_bands, boundary_size=structure.shape[0] + 1,
136 | virtual_raster=vrt_list[n],
137 | progress_message='processing raster %s' % (n + 1),
138 | min_progress=min_p + max_p * n,
139 | max_progress=min_p + max_p * (n + 1)
140 | )
141 | n += 1
142 | cfg.progress.update(end=True)
143 | cfg.logger.log.info('end; band erosion: %s' % output_list)
144 | return OutputManager(paths=output_list)
145 |
--------------------------------------------------------------------------------
/tests/test_table_manager.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 | from unittest import TestCase
3 |
4 | import remotior_sensus
5 |
6 |
7 | class TestTableManager(TestCase):
8 |
9 | def test_table_manager(self):
10 | rs = remotior_sensus.Session(
11 | n_processes=2, available_ram=1000, log_level=10
12 | )
13 | cfg = rs.configurations
14 | data_path = Path(__file__).parent / 'data'
15 | file1 = str(data_path / 'files' / 'file1.csv')
16 | file2 = str(data_path / 'files' / 'file2.csv')
17 | file3 = str(data_path / 'files' / 'file1.dbf')
18 | cfg.logger.log.debug('>>> test open file')
19 | matrix_file = rs.table_manager.open_file(
20 | file1, field_names=['id', 'main', 'field1', 'field2', 'field3',
21 | 'name']
22 | )
23 | self.assertGreater(len(matrix_file[0]), 0)
24 | cfg.logger.log.debug('>>> test open csv')
25 | matrix_file1 = rs.table_manager._open_csv(
26 | file1, field_name_list=['id', 'main', 'field1', 'field2', 'field3',
27 | 'name']
28 | )
29 | self.assertGreater(len(matrix_file1[0]), 0)
30 | self.assertGreater(len(matrix_file1.id), 0)
31 | matrix_file2 = rs.table_manager._open_csv(file2)
32 | self.assertGreater(len(matrix_file2.value), 0)
33 | cfg.logger.log.debug('>>> test open dbf')
34 | matrix_file3 = rs.table_manager._open_dbf(
35 | file3, field_name_list=['id', 'main', 'field1', 'field2', 'field3',
36 | 'name']
37 | )
38 | self.assertGreater(len(matrix_file3[0]), 0)
39 | self.assertGreater(len(matrix_file3.id), 0)
40 | cfg.logger.log.debug('>>> test join matrices')
41 | joined_table = rs.table_manager.join_matrices(
42 | matrix1=matrix_file1, matrix2=matrix_file2, field1_name='main',
43 | field2_name='value', join_type='leftouter', matrix1_postfix='_m1',
44 | matrix2_postfix='_m2'
45 | )
46 | self.assertGreater(len(joined_table.id_m1), 0)
47 | self.assertGreater(len(rs.table_manager.columns(joined_table)), 0)
48 | cfg.logger.log.debug('>>> test join tables')
49 | joined_table2 = rs.table_manager.join_tables(
50 | table1=matrix_file1, table2=matrix_file2, field1_name='main',
51 | field2_name='value', join_type='left'
52 | )
53 | self.assertGreater(len(joined_table2.id2), 0)
54 | self.assertGreater(len(rs.table_manager.columns(joined_table2)), 0)
55 | joined_test_outer = rs.table_manager.join_tables(
56 | table1=matrix_file1, table2=matrix_file2, field1_name='id',
57 | field2_name='id', join_type='outer'
58 | )
59 | self.assertGreater(len(joined_test_outer.id), 0)
60 | self.assertGreater(len(rs.table_manager.columns(joined_test_outer)), 0)
61 | joined_test_inner = rs.table_manager.join_tables(
62 | table1=matrix_file1, table2=matrix_file2, field1_name='main',
63 | field2_name='value', join_type='inner'
64 | )
65 | self.assertGreater(len(joined_test_inner.id2), 0)
66 | self.assertGreater(len(rs.table_manager.columns(joined_test_inner)), 0)
67 | joined_test_right = rs.table_manager.join_tables(
68 | table1=matrix_file1, table2=matrix_file2, field1_name='id',
69 | field2_name='id', join_type='right'
70 | )
71 | self.assertGreater(len(joined_test_right.id), 0)
72 | self.assertGreater(len(rs.table_manager.columns(joined_test_right)), 0)
73 | cfg.logger.log.debug('>>> test pivot_60')
74 | pivot1 = rs.table_manager.pivot_matrix(
75 | joined_table, row_field='value',
76 | column_function_list=[['field3_m1', 'sum']]
77 | )
78 | self.assertGreater(len(pivot1.field3_m1_sum), 0)
79 | cfg.logger.log.debug('>>> test rename field')
80 | renamed_field_pivot1 = rs.table_manager.rename_field(
81 | pivot1, 'field3_m1_sum', 'sum'
82 | )
83 | self.assertTrue(
84 | 'sum' in rs.table_manager.columns(renamed_field_pivot1)
85 | )
86 | cfg.logger.log.debug('>>> test calculate')
87 | calculation = rs.table_manager.calculate(
88 | matrix=matrix_file3, expression_string='field.field3 * 1.5',
89 | output_field_name='calc'
90 | )
91 | self.assertGreater(len(calculation.calc), 0)
92 | calculation_multi = rs.table_manager.calculate_multi(
93 | matrix=matrix_file3,
94 | expression_string_list=['"field1" * 1.5', '"field2" * 3.5'],
95 | output_field_name_list=['calc1', 'calc2']
96 | )
97 | self.assertGreater(len(calculation_multi.calc1), 0)
98 | output = cfg.temp.temporary_file_path(name_suffix=cfg.csv_suffix)
99 | cfg.logger.log.debug('>>> matrix to csv')
100 | rs.table_manager.matrix_to_csv(
101 | matrix=calculation, output_path=output,
102 | fields=['name', 'id', 'calc'], nodata_value=4,
103 | nodata_value_output='nodata', separator=';', decimal_separator=','
104 | )
105 | self.assertTrue(rs.files_directories.is_file(output))
106 | cfg.logger.log.debug('>>> test pivot_60')
107 | pivot2 = rs.table_manager.pivot_matrix(
108 | joined_table, row_field='name_m1',
109 | column_function_list=[['field3_m2', 'sum']]
110 | )
111 | cfg.logger.log.debug('>>> test get values')
112 | values = rs.table_manager.get_values(
113 | matrix=pivot2, value_field='field3_m2_sum',
114 | conditional_string='field.name_m1 == "a"'
115 | )
116 | self.assertGreater(len(values), 0)
117 | values2 = rs.table_manager.get_values(
118 | matrix=pivot2, value_field='name_m1',
119 | conditional_string='field.field3_m2_sum >100'
120 | )
121 | self.assertGreater(len(values2), 0)
122 | cfg.logger.log.debug('>>> test pivot_60')
123 | fields = rs.table_manager.pivot_matrix(
124 | joined_table, row_field='name_m1',
125 | secondary_row_field_list=['name_m2'],
126 | column_function_list=[['field3_m1', 'sum'], ['field3_m2', 'sum']],
127 | filter_string='matrix["field3_m1"] <= 1000', field_names=True
128 | )
129 | self.assertGreater(len(fields), 0)
130 | pivot3 = rs.table_manager.pivot_matrix(
131 | joined_table, row_field='name_m1',
132 | secondary_row_field_list=['name_m2'],
133 | column_function_list=[['field3_m1', 'sum'], ['field3_m2', 'sum']],
134 | filter_string='matrix["field3_m1"] <= 1000'
135 | )
136 | self.assertGreater(len(pivot3.name_m1), 0)
137 | cfg.logger.log.debug('>>> test redefine')
138 | redefined = rs.table_manager.redefine_matrix_columns(
139 | matrix=joined_table,
140 | input_field_names=['name_m1', 'field3_m1', 'name_m2'],
141 | output_field_names=['field1', 'field2', 'field3']
142 | )
143 | self.assertGreater(len(redefined.field1), 0)
144 | appended = rs.table_manager.append_values_to_table(
145 | matrix=redefined, value_list=[1, 2, 3]
146 | )
147 | self.assertGreater(len(appended.field1), 0)
148 |
149 | # clear temporary directory
150 | rs.close()
151 |
--------------------------------------------------------------------------------