├── .bandit ├── .github ├── dependabot.yml └── workflows │ ├── ci.yaml │ └── deploy.yaml ├── .gitignore ├── .pre-commit-config.yaml ├── .readthedocs.yaml ├── AUTHORS.md ├── CHANGELOG.md ├── CMakeLists.txt ├── CONTRIBUTING.rst ├── INSTALLER_README.md ├── LICENSE.txt ├── MANIFEST.in ├── README.md ├── RELEASING.md ├── build_conda_pack.py ├── bundle_scripts ├── README.md ├── SIFT.bat └── SIFT.sh ├── cmake ├── FindConda.cmake └── FindPyInstaller.cmake ├── conda-envs └── sift-devel-minimal.pkgs ├── continuous_integration ├── build_conda_pack.sh ├── environment.yaml ├── linux_full_deps_apt.txt ├── rtd_environment.yaml └── upload_conda_pack.sh ├── doc ├── Makefile ├── make.bat └── source │ ├── PACKAGING-sift.rst │ ├── _static │ └── .gitkeep │ ├── api │ ├── uwsift.control.rst │ ├── uwsift.model.rst │ ├── uwsift.project.rst │ ├── uwsift.rst │ ├── uwsift.ui.rst │ ├── uwsift.util.rst │ ├── uwsift.util.widgets.rst │ ├── uwsift.view.rst │ ├── uwsift.workspace.rst │ └── uwsift.workspace.utils.rst │ ├── auto_update_mode.rst │ ├── conf.py │ ├── configuration │ ├── area_definitions.rst │ ├── catalogue-auto_update_mode.rst │ ├── default_colormaps.rst │ ├── display.rst │ ├── external_satpy.rst │ ├── index.rst │ ├── latlon-grid-resolution.rst │ ├── logging.rst │ ├── points_styles.rst │ ├── readers.rst │ ├── standard_names.rst │ ├── storage.rst │ ├── units.rst │ └── watchdog.rst │ ├── dev_guide │ ├── contributing.rst │ ├── design_overview.rst │ ├── index.rst │ └── writing_tests.rst │ ├── diag │ └── open_file.diag │ ├── fonts │ └── DejaVuSerif.ttf │ ├── index.rst │ ├── installation.rst │ ├── profiling.rst │ └── test.diag ├── pyproject.toml ├── resources ├── bin │ ├── readme.txt │ ├── sift.bat │ └── sift.sh ├── pyinstaller │ ├── Library │ │ └── bin │ │ │ └── dummy.txt │ └── rasterio │ │ └── .libs │ │ └── dummy.txt └── service │ ├── uwsift-watchdog.service │ └── uwsift.service ├── rtd_requirements.txt ├── setup.cfg ├── setup.py ├── sift-pyinstaller-package.spec ├── sift.iss ├── splash.png └── uwsift ├── __init__.py ├── __main__.py ├── common.py ├── control ├── __init__.py ├── auto_update.py ├── qml_utils.py ├── time_matcher.py ├── time_matcher_policies.py ├── time_transformer.py └── time_transformer_policies.py ├── data ├── colormaps │ └── OAX │ │ ├── Cloud Amount Default.cmap │ │ ├── Cloud Top Height.cmap │ │ ├── GOES-R │ │ ├── GOESR-L2 │ │ │ ├── ACTP.cmap │ │ │ ├── ADP.cmap │ │ │ ├── CSM.cmap │ │ │ ├── Dust.cmap │ │ │ ├── FSC.cmap │ │ │ ├── GOES-SST-35.cmap │ │ │ ├── RRQPE.cmap │ │ │ ├── RRQPE1.cmap │ │ │ ├── Smoke.cmap │ │ │ ├── VTRSB.cmap │ │ │ ├── color-cape-10.cmap │ │ │ ├── color-li-10.cmap │ │ │ ├── color-pw10-10.cmap │ │ │ └── color-pw8-10.cmap │ │ ├── IR │ │ │ ├── CIRA (IR Default).cmap │ │ │ ├── IR WV.cmap │ │ │ ├── IR_Color_Clouds_Summer.cmap │ │ │ ├── IR_Color_Clouds_Winter.cmap │ │ │ ├── Rainbow_11_bit.cmap │ │ │ ├── WV_Dry_Yellow.cmap │ │ │ ├── dust_and_moisture_split_window.cmap │ │ │ ├── enhanced-rainbow-11.cmap │ │ │ ├── enhanced-rainbow_warmer_yellow.cmap │ │ │ ├── fire_detection_3.9.cmap │ │ │ ├── fogdiff_blue.cmap │ │ │ ├── ramsdis_IR_12bit.cmap │ │ │ └── ramsdis_WV_12bit.cmap │ │ ├── Lifted Index │ │ │ ├── Lifted Index - New CIMSS Table.cmap │ │ │ └── Lifted Index Default.cmap │ │ ├── Precip │ │ │ ├── Blended Total Precip Water.cmap │ │ │ ├── Percent of Normal TPW.cmap │ │ │ ├── Precip Water - New CIMSS Table.cmap │ │ │ ├── Precip Water - Polar.cmap │ │ │ └── Precip Water Default.cmap │ │ ├── Skin Temp │ │ │ ├── Skin Temp - New CIMSS Table.cmap │ │ │ └── Skin Temp Default.cmap │ │ ├── VIS │ │ │ ├── CA (Low Light Vis).cmap │ │ │ ├── Linear.cmap │ │ │ ├── VIS_gray_sq-root-12.cmap │ │ │ └── ZA (Vis Default).cmap │ │ └── WV │ │ │ ├── Gray Scale Water Vapor.cmap │ │ │ ├── NSSL VAS (WV Alternate).cmap │ │ │ └── SLC WV.cmap │ │ ├── Low Cloud Base.cmap │ │ ├── Rain Rate.cmap │ │ └── prob_severe.cmap ├── fonts │ └── Andale Mono.ttf ├── grib_definitions │ └── grib2 │ │ └── localConcepts │ │ └── kwbc │ │ ├── cfName.def │ │ ├── modelName.def │ │ ├── name.def │ │ ├── paramId.def │ │ ├── shortName.def │ │ └── units.def ├── icons │ └── menu.svg ├── ne_110m_admin_0_countries │ ├── ne_110m_admin_0_countries.README.html │ ├── ne_110m_admin_0_countries.VERSION.txt │ ├── ne_110m_admin_0_countries.dbf │ ├── ne_110m_admin_0_countries.prj │ ├── ne_110m_admin_0_countries.shp │ └── ne_110m_admin_0_countries.shx ├── ne_50m_admin_0_countries │ ├── ne_50m_admin_0_countries.README.html │ ├── ne_50m_admin_0_countries.VERSION.txt │ ├── ne_50m_admin_0_countries.dbf │ ├── ne_50m_admin_0_countries.prj │ ├── ne_50m_admin_0_countries.shp │ └── ne_50m_admin_0_countries.shx ├── ne_50m_admin_1_states_provinces_lakes │ ├── ne_50m_admin_1_states_provinces_lakes.README.html │ ├── ne_50m_admin_1_states_provinces_lakes.VERSION.txt │ ├── ne_50m_admin_1_states_provinces_lakes.dbf │ ├── ne_50m_admin_1_states_provinces_lakes.prj │ ├── ne_50m_admin_1_states_provinces_lakes.shp │ └── ne_50m_admin_1_states_provinces_lakes.shx └── shadedrelief.jpg ├── etc └── SIFT │ └── config │ ├── area_definitions.yaml │ ├── auto_update.yaml │ ├── catalogue.yaml │ ├── default_colormaps.yaml │ ├── default_points_styles.yaml │ ├── default_reader.yaml │ ├── default_standard_names.yaml │ ├── display.yaml │ ├── external_satpy.yaml │ ├── limit_available_readers.yaml │ ├── logging.yaml │ ├── open_file_wizard.yaml │ ├── readers │ ├── abi_l1b.yaml │ ├── avhrr_l1b_eps.yaml │ ├── fci_l1c_nc.yaml │ ├── fci_l2_bufr.yaml │ ├── fci_l2_grib.yaml │ ├── fci_l2_nc.yaml │ ├── gld360_ualf2.yaml │ ├── li_l1b_nc.yaml │ ├── li_l2_nc.yaml │ ├── modis_l1b.yaml │ ├── seviri_l1b_hrit.yaml │ ├── seviri_l1b_native.yaml │ ├── seviri_l2_binary.yaml │ ├── seviri_l2_bufr.yaml │ ├── seviri_l2_grib.yaml │ └── vii_l1b_nc.yaml │ ├── storage.yaml │ ├── units.yaml │ └── watchdog.yaml ├── model ├── __init__.py ├── area_definitions_manager.py ├── catalogue.py ├── composite_recipes.py ├── document.py ├── layer_item.py ├── layer_model.py ├── product_dataset.py ├── shapes.py └── time_manager.py ├── project ├── __init__.py ├── organize_data_bands.py ├── organize_data_topics.py └── project_time_step.sh ├── queue.py ├── satpy_compat.py ├── tests ├── __init__.py ├── conftest.py ├── control │ ├── __init__.py │ └── fill_dir_periodically.py ├── model │ ├── __init__.py │ ├── conftest.py │ ├── interactive_test_globbing_creator.py │ └── test_globbing_creator.py ├── test_satpy_import.py ├── util │ ├── __init__.py │ └── test_common.py ├── view │ ├── __init__.py │ ├── test_custom_widgets.py │ ├── test_export_image.py │ ├── test_file_wizard.py │ ├── test_rgb_config.py │ └── test_tile_calculator.py └── workspace │ ├── __init__.py │ ├── test_algebraic.py │ ├── test_importer.py │ └── test_statistics.py ├── ui ├── TimelineRuler.qml ├── __init__.py ├── build.sh ├── change_colormap_dialog_ui.py ├── custom_widgets.py ├── dataset_statistics_widget.ui ├── dataset_statistics_widget_ui.py ├── export_image_dialog.ui ├── export_image_dialog_ui.py ├── layer_details_widget.ui ├── layer_details_widget_ui.py ├── open_cache_dialog.ui ├── open_cache_dialog_ui.py ├── open_file_wizard.ui ├── open_file_wizard_ui.py ├── pov_main.ui ├── pov_main_ui.py └── timeline.qml ├── util ├── __init__.py ├── common.py ├── default_paths.py ├── disk_management.py ├── heap_analyzer.py ├── heap_profiler.py ├── logger.py ├── ps_analyzer.py ├── ps_profiler.py ├── storage_agent.py ├── watchdog.py └── widgets │ ├── __init__.py │ └── pie_dial.py ├── version.py ├── view ├── __init__.py ├── algebraic_config.py ├── cameras.py ├── colormap.py ├── colormap_editor.py ├── dataset_statistics_pane.py ├── export_image.py ├── layer_details.py ├── layer_tree_view.py ├── open_file_wizard.py ├── probes.py ├── rgb_config.py ├── scene_graph.py ├── test_visuals.py ├── texture_atlas.py ├── tile_calculator.py ├── transform.py └── visuals.py └── workspace ├── __init__.py ├── caching_workspace.py ├── collector.py ├── guidebook.py ├── importer.py ├── metadatabase.py ├── simple_workspace.py ├── statistics.py ├── utils ├── __init__.py └── metadata_utils.py └── workspace.py /.bandit: -------------------------------------------------------------------------------- 1 | [bandit] 2 | skips: B506 3 | exclude: uwsift/tests 4 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "github-actions" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "monthly" 12 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yaml: -------------------------------------------------------------------------------- 1 | name: Deploy 2 | # https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#concurrency 3 | # https://docs.github.com/en/developers/webhooks-and-events/events/github-event-types#pullrequestevent 4 | concurrency: 5 | group: ${{ github.workflow }}-${{ github.event.number }}-${{ github.event.type }} 6 | cancel-in-progress: true 7 | 8 | on: 9 | pull_request: 10 | push: 11 | branches: 12 | - master 13 | release: 14 | types: 15 | - published 16 | 17 | jobs: 18 | sdist: 19 | runs-on: ubuntu-latest 20 | 21 | steps: 22 | - name: Checkout source 23 | uses: actions/checkout@v4 24 | 25 | - name: Create sdist 26 | shell: bash -l {0} 27 | run: python -m pip install --break-system-packages build; python -m build 28 | 29 | - uses: actions/upload-artifact@v4 30 | with: 31 | name: dist 32 | path: dist/*.tar.gz 33 | 34 | bundle: 35 | runs-on: ${{ matrix.os }} 36 | defaults: 37 | run: 38 | shell: "bash -l {0}" 39 | continue-on-error: false 40 | strategy: 41 | fail-fast: true 42 | matrix: 43 | os: ["windows-latest", "ubuntu-latest", "macos-latest"] 44 | python-version: ["3.11"] 45 | 46 | env: 47 | PYTHON_VERSION: ${{ matrix.python-version }} 48 | OS: ${{ matrix.os }} 49 | ACTIONS_ALLOW_UNSECURE_COMMANDS: true 50 | 51 | steps: 52 | - name: Checkout source 53 | uses: actions/checkout@v4 54 | 55 | - name: Install SSH Key 56 | uses: shimataro/ssh-key-action@v2 57 | # only upload on push (currently only master), otherwise SFTP key is not needed 58 | if: github.event_name == 'push' 59 | with: 60 | key: ${{ secrets.SIFT_SFTP_UPLOAD_KEY }} 61 | name: id_rsa_sftp 62 | known_hosts: ${{ secrets.SIFT_SFTP_UPLOAD_KNOWN_HOSTS }} 63 | 64 | - name: Setup Conda Environment 65 | uses: conda-incubator/setup-miniconda@v3 66 | with: 67 | miniforge-version: latest 68 | environment-file: continuous_integration/environment.yaml 69 | activate-environment: test-environment 70 | channels: conda-forge 71 | 72 | - name: Install conda pack 73 | run: | 74 | conda install conda-pack curl 75 | curl -V 76 | 77 | - name: Install uwsift 78 | run: | 79 | pip install --no-deps . 80 | 81 | - name: Build bundle 82 | run: | 83 | continuous_integration/build_conda_pack.sh 84 | 85 | # It would be better to only upload if all platforms had succeeded but 86 | # that would require uploading the bundles as artifacts which would 87 | # quickly hit our temporary storage limits 88 | - name: Upload bundle 89 | # only upload on push (currently only master) 90 | if: github.event_name == 'push' 91 | run: | 92 | continuous_integration/upload_conda_pack.sh 93 | 94 | upload-sdist: 95 | runs-on: ubuntu-latest 96 | needs: [sdist, bundle] # don't deploy unless sdist and bundle building succeeded 97 | steps: 98 | - uses: actions/download-artifact@v4 99 | with: 100 | name: dist 101 | path: dist 102 | - uses: pypa/gh-action-pypi-publish@master 103 | # publish when a GitHub Release is created 104 | if: github.event_name == 'release' && github.event.action == 'published' 105 | with: 106 | user: __token__ 107 | password: ${{ secrets.UWSIFT_PYPI_TOKEN }} 108 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # PyCharm project settings 2 | .idea 3 | 4 | 5 | # Ignore IDE settings and configuration files 6 | .vscode/ 7 | 8 | # OSX DS files 9 | .DS_Store 10 | 11 | # Byte-compiled / optimized / DLL files 12 | __pycache__/ 13 | *.py[cod] 14 | *$py.class 15 | 16 | # C extensions 17 | *.so 18 | 19 | # Distribution / packaging 20 | .Python 21 | build/ 22 | develop-eggs/ 23 | dist/ 24 | downloads/ 25 | eggs/ 26 | .eggs/ 27 | lib/ 28 | lib64/ 29 | parts/ 30 | sdist/ 31 | var/ 32 | wheels/ 33 | *.egg-info/ 34 | .installed.cfg 35 | *.egg 36 | MANIFEST 37 | 38 | # PyInstaller 39 | # Usually these files are written by a python script from a template 40 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 41 | *.manifest 42 | # Usually these are removed, but SIFT's is needed, it includes custom logic 43 | #*.spec 44 | 45 | # Installer logs 46 | pip-log.txt 47 | pip-delete-this-directory.txt 48 | 49 | # Unit test / coverage reports 50 | htmlcov/ 51 | .tox/ 52 | .coverage 53 | .coverage.* 54 | .cache 55 | nosetests.xml 56 | coverage.xml 57 | *.cover 58 | .hypothesis/ 59 | .pytest_cache/ 60 | 61 | # Translations 62 | *.mo 63 | *.pot 64 | 65 | # Django stuff: 66 | *.log 67 | local_settings.py 68 | db.sqlite3 69 | 70 | # Flask stuff: 71 | instance/ 72 | .webassets-cache 73 | 74 | # Scrapy stuff: 75 | .scrapy 76 | 77 | # Sphinx documentation 78 | doc/build/ 79 | 80 | # PyBuilder 81 | target/ 82 | 83 | # Jupyter Notebook 84 | .ipynb_checkpoints 85 | 86 | # pyenv 87 | .python-version 88 | 89 | # celery beat schedule file 90 | celerybeat-schedule 91 | 92 | # SageMath parsed files 93 | *.sage.py 94 | 95 | # Environments 96 | .env 97 | .venv 98 | env/ 99 | venv/ 100 | ENV/ 101 | env.bak/ 102 | venv.bak/ 103 | 104 | # Spyder project settings 105 | .spyderproject 106 | .spyproject 107 | 108 | # Rope project settings 109 | .ropeproject 110 | 111 | # mkdocs documentation 112 | /site 113 | 114 | # mypy 115 | .mypy_cache/ 116 | 117 | # CMake build system 118 | CMakeCache.txt 119 | cmake_install.cmake 120 | CMakeFiles/ 121 | Makefile 122 | 123 | # Windows soft links 124 | /*.lnk 125 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | exclude: '^$' 2 | fail_fast: false 3 | repos: 4 | - repo: https://github.com/psf/black 5 | rev: 24.8.0 6 | hooks: 7 | - id: black 8 | language_version: python3 9 | args: 10 | - --target-version=py38 11 | - repo: https://github.com/pycqa/isort 12 | rev: 5.13.2 13 | hooks: 14 | - id: isort 15 | language_version: python3 16 | - repo: https://github.com/pycqa/flake8 17 | rev: 7.1.1 18 | hooks: 19 | - id: flake8 20 | language_version: python3 21 | additional_dependencies: [flake8-docstrings, flake8-debugger, flake8-bugbear, mccabe] 22 | args: [--max-complexity, "10"] 23 | - repo: https://github.com/pre-commit/pre-commit-hooks 24 | rev: v4.6.0 25 | hooks: 26 | - id: trailing-whitespace 27 | - id: end-of-file-fixer 28 | - id: check-yaml 29 | args: [--unsafe] 30 | # conda-recipes use jinja templating which isn't valid YAML syntax 31 | exclude: conda-recipe\/ 32 | - repo: https://github.com/PyCQA/bandit 33 | rev: '1.7.9' 34 | hooks: 35 | - id: bandit 36 | args: [--ini, .bandit] 37 | - repo: https://github.com/pre-commit/mirrors-mypy 38 | rev: 'v1.11.2' # Use the sha / tag you want to point at 39 | hooks: 40 | - id: mypy 41 | additional_dependencies: 42 | - types-docutils 43 | - types-setuptools 44 | - types-PyYAML 45 | - types-requests 46 | - types-python-dateutil 47 | ci: 48 | # To trigger manually, comment on a pull request with "pre-commit.ci autofix" 49 | autofix_prs: false 50 | autoupdate_schedule: "monthly" 51 | skip: [] 52 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | build: 4 | os: "ubuntu-20.04" 5 | tools: 6 | python: "mambaforge-4.10" 7 | 8 | # Build documentation in the docs/ directory with Sphinx 9 | sphinx: 10 | configuration: doc/source/conf.py 11 | fail_on_warning: true 12 | 13 | 14 | conda: 15 | environment: continuous_integration/rtd_environment.yaml 16 | 17 | #python: 18 | # install: 19 | # - method: pip 20 | # path: .[docs] 21 | -------------------------------------------------------------------------------- /AUTHORS.md: -------------------------------------------------------------------------------- 1 | # Project Contributors 2 | 3 | The following people have made contributions to this project: 4 | 5 | 6 | 7 | 8 | - [Rohan Daruwala (rdaruwala)](https://github.com/rdaruwala) 9 | - [Colin Duff (ColinDuff)](https://github.com/ColinDuff) 10 | - [Ray Garcia (rayg-ssec)](https://github.com/rayg-ssec) 11 | - [Jordan Gerth (jgerth)](https://github.com/jgerth) 12 | - [David Hoese (djhoese)](https://github.com/djhoese) 13 | - [Sauli Joro (sjoro)](https://github.com/sjoro) 14 | - [Nicolai Kellerer (nbke)](https://github.com/nbke) 15 | - [Max Kreischer (MaxKreischer)](https://github.com/MaxKreischer) 16 | - [Alexandra Melzer (armelzer)](https://github.com/armelzer) 17 | - [Andrea Meraner (ameraner)](https://github.com/ameraner) 18 | - [Coda Phillips (CodaP)](https://github.com/CodaP) 19 | - [Alexander Rettig (arcanerr)](https://github.com/arcanerr) 20 | - [William Roberts (wroberts4)](https://github.com/wroberts4) 21 | - [Eva Schiffer (evas-ssec)](https://github.com/evas-ssec) 22 | - [Johan Strandgren (strandgren)](https://github.com/strandgren) 23 | -------------------------------------------------------------------------------- /CONTRIBUTING.rst: -------------------------------------------------------------------------------- 1 | How to Contribute 2 | ================= 3 | 4 | Information on contributing to SIFT can be found on our 5 | [Contributor's Guide](https://sift.readthedocs.io/en/latest/dev_guide/contributing.html). 6 | -------------------------------------------------------------------------------- /INSTALLER_README.md: -------------------------------------------------------------------------------- 1 | # SIFT 2 | 3 | SIFT (Satellite Information Familiarization Tool) is a visualisation tool 4 | for satellite data. It provides a graphical interface that can be used for 5 | e.g. fast visualisation, scientific data analysis, training, cal/val activities 6 | and operations. 7 | 8 | SIFT is built on open source technologies like Python, OpenGL, PyQt5, and 9 | makes use of the [Pytroll framework](https://pytroll.github.io/) for reading 10 | and processing the input data. 11 | It can be run from Mac, Windows, and Linux. The SIFT application is provided as 12 | a python library called "uwsift". It can also be installed as a standalone 13 | application. 14 | 15 | SIFT's main website is http://sift.ssec.wisc.edu/. 16 | 17 | The Git repository where you can find SIFT's source code, issue tracker, and 18 | other documentation is on GitHub: https://github.com/ssec/sift 19 | 20 | The project wiki with some in-depth usage and installation instructions can 21 | also be found on GitHub: https://github.com/ssec/sift/wiki 22 | 23 | Developer and configuration documentation can be found on 24 | https://sift.readthedocs.io/en/latest/. 25 | 26 | ## What's new in SIFT 2.0 27 | 28 | Many new features have been added starting from the version 2.0 of SIFT, including: 29 | - reading of data from both geostationary (GEO) as well as low-Earth-orbit (LEO) 30 | satellite instruments 31 | - visualisation of point data (e.g. lightning) 32 | - support for composite (RGB) visualisation 33 | - an improved timeline manager 34 | - integration of a statistics module 35 | - full resampling functionalities using Pyresample 36 | - an automatic update/monitoring mode 37 | - partial redesign of the UI/UX 38 | - ... many more small but useful features! 39 | 40 | ## History 41 | 42 | SIFT was originally created and designed at [SSEC/CIMSS at the University of 43 | Wisconsin - Madison](https://cimss.ssec.wisc.edu/) as a training tool for US 44 | NWS forecasters. Later, [EUMETSAT, European Organization for the Exploitation 45 | of Meteorological Satellites](https://www.eumetsat.int/), 46 | joined the project contributing many new features and refactoring various 47 | portions of the project to support instrument calibration/validation workflows 48 | as well as additional scientific analysis. CIMSS and EUMETSAT now work on the 49 | project together as well as accepting contributions from users outside these 50 | groups. 51 | 52 | EUMETSAT contributions, leading up to SIFT 2.0, were carried out by 53 | [ask – Innovative Visualisierungslösungen GmbH](https://askvisual.de/). 54 | 55 | ## Data Access and Reading 56 | 57 | SIFT uses the open source python library Satpy to read input data. By using 58 | Satpy, SIFT is able to read many satellite instrument file formats, 59 | especially in the meteorology domain. The full list of available Satpy readers 60 | can be found in 61 | [Satpy's documentation](https://satpy.readthedocs.io/en/stable/index.html#id1). 62 | Note however that SIFT may not be able to display or understand all data formats 63 | that Satpy can read. 64 | SIFT defaults to a limited set of readers; head to the 65 | [configuration documentation](https://sift.readthedocs.io/en/latest/configuration/index.html) 66 | for customising your SIFT. 67 | 68 | ## Installation 69 | 70 | SIFT can be installed as an all-in-one bundled application or the python 71 | library "uwsift" can be installed in a traditional python environment. 72 | 73 | Detailed installation instructions can be found on the 74 | [GitHub Wiki](https://github.com/ssec/sift/wiki/Installation-Guide). 75 | 76 | ## Contributors 77 | 78 | SIFT is an open source project welcoming all contributions. See the 79 | [Contributing Guide](https://github.com/ssec/sift/wiki/Contributing) 80 | for more information on how you can help. 81 | 82 | ### Building and releasing 83 | 84 | For instructions on how SIFT is built and packaged see the 85 | [releasing instructions](RELEASING.md). Note that these instructions 86 | are mainly for SIFT developers and may require technical understanding of 87 | SIFT and the libraries it depends on. 88 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include uwsift/data/shadedrelief.jpg 2 | include uwsift/data/ne_50m_admin_0_countries/* 3 | include uwsift/data/ne_110m_admin_0_countries/* 4 | include uwsift/data/ne_50m_admin_1_states_provinces_lakes/* 5 | recursive-include uwsift/data/fonts *.ttf 6 | recursive-include uwsift/data/colormaps *.cmap 7 | recursive-include uwsift/data/grib_definitions *.def 8 | recursive-include uwsift/data/icons *.svg 9 | recursive-include uwsift/etc * 10 | include uwsift/ui/*.ui 11 | include uwsift/ui/*.qml 12 | include uwsift/ui/*.sh 13 | include LICENSE.txt 14 | -------------------------------------------------------------------------------- /RELEASING.md: -------------------------------------------------------------------------------- 1 | # Releasing SIFT 2 | 3 | The following instructions will walk you through making a release of the 4 | SIFT application and python library. These instructions assume that you 5 | already have the SIFT git repository cloned from GitHub and that the 6 | `origin` git remote is pointing to the `ssec/sift` repository. Instructions 7 | must be adjusted if `origin` points to your fork of the `sift` repository. 8 | 9 | 1. Make sure you are on the master branch (`git checkout master`) 10 | 2. Pull the most recent changes (`git pull`) 11 | 3. Run any necessary tests. For basic dependency checks `python sift -h` 12 | should suffice. 13 | 4. Run `loghub` and update the `CHANGELOG.md` file. If `loghub` is not 14 | installed, do so by running `pip install loghub`. 15 | 16 | ```bash 17 | loghub ssec/sift --token $LOGHUB_GITHUB_TOKEN -st -plg bug "Bugs fixed" -plg enhancement "Features added" -plg documentation "Documentation changes" -plg backwards-incompatibility "Backwards incompatible changes" 18 | ``` 19 | 20 | 5. Commit the changelog changes. 21 | 22 | 6. Bump the version of the package: 23 | 24 | ```bash 25 | python setup.py bump --new-version 1.0.5 -c -t 26 | ``` 27 | 28 | See [semver.org](http://semver.org/) on how to write a version number. 29 | 30 | 7. Push changes to github `git push --follow-tags` 31 | 32 | 8. Create a release of the package on 33 | [github](https://github.com/ssec/sift/releases) by drafting a new release 34 | and copying the release notes from the changelog (see above). 35 | -------------------------------------------------------------------------------- /build_conda_pack.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Create a conda-pack'd SIFT installation tarball. 3 | 4 | Note: This script will place extra files in the currently activated python 5 | environment in order to include these files in the produced tarball. 6 | 7 | SIFT must be installed in the current environment with:: 8 | 9 | pip install --no-deps . 10 | 11 | Instead of installing it in development mode (`-e`). 12 | 13 | Example:: 14 | 15 | python build_conda_pack.py -c 16 | """ 17 | 18 | import os 19 | import re 20 | import shutil 21 | import subprocess # nosec: B404 22 | import sys 23 | 24 | 25 | def get_version(): 26 | try: 27 | from uwsift import __version__ 28 | 29 | return __version__ 30 | except ImportError: 31 | raise RuntimeError("Could not determine SIFT version. Is SIFT installed?") 32 | 33 | 34 | def main(): 35 | import argparse 36 | 37 | parser = argparse.ArgumentParser( 38 | description="Build SIFT installation tarball (remaining arguments " "are passed to conda-pack)" 39 | ) 40 | parser.add_argument("--arcroot", help="Directory name inside the tarball (default: SIFT_X.Y.Z)") 41 | parser.add_argument( 42 | "-o", 43 | "--output", 44 | help="Pathname for bundled file. Default is " 45 | "'SIFT_X.Y.Z_.' where platform is " 46 | "'linux', 'darwin', or 'win32' and ext is " 47 | "'.tar.gz' for linux and OSX, '.zip' for Windows.", 48 | ) 49 | args, unknown_args = parser.parse_known_args() 50 | 51 | version = get_version() 52 | if args.arcroot is None: 53 | args.arcroot = f"SIFT_{version}" 54 | if args.output is None: 55 | ext = ".zip" if sys.platform.startswith("win") else ".tar.gz" 56 | args.output = f"SIFT_{version}_{sys.platform}{ext}" 57 | 58 | # Copy appropriate wrapper scripts 59 | dst = sys.prefix 60 | script_dir = os.path.realpath(os.path.dirname(__file__)) 61 | if "nux" in sys.platform: 62 | script = os.path.join(script_dir, "bundle_scripts", "SIFT.sh") 63 | shutil.copy(script, os.path.join(dst, "SIFT.sh")) 64 | elif "darwin" in sys.platform: 65 | script = os.path.join(script_dir, "bundle_scripts", "SIFT.sh") 66 | shutil.copy(script, os.path.join(dst, "SIFT.command")) 67 | elif "win" in sys.platform: 68 | script = os.path.join(script_dir, "bundle_scripts", "SIFT.bat") 69 | shutil.copy(script, os.path.join(dst, "SIFT.bat")) 70 | else: 71 | raise RuntimeError(f"Unknown platform: {sys.platform}") 72 | 73 | # HACK: https://github.com/conda/conda-pack/issues/141 74 | if sys.platform.startswith("win"): 75 | _hack_conda_packed_qtconf_on_windows() 76 | 77 | subprocess.check_call( # nosec: B603 78 | ["conda-pack", "--arcroot", args.arcroot, "--output", args.output] + unknown_args 79 | ) 80 | os.chmod(args.output, 0o755) # nosec: B103 81 | 82 | # TODO: Do additional risky cleanup to reduce output file size 83 | 84 | 85 | def _hack_conda_packed_qtconf_on_windows(): 86 | qt_conf_path = os.path.join(sys.prefix, "Library", "bin", "qt.conf") 87 | if not os.path.exists(qt_conf_path): 88 | return 89 | with open(qt_conf_path, "rt") as qtconf: 90 | old_text = qtconf.read() 91 | (old_prefix,) = tuple(re.findall(r"^Prefix\s*=\s*(.*?).Library\s*$", old_text, re.MULTILINE)) 92 | new_prefix = old_prefix.replace("/", "\\") 93 | new_text = old_text.replace(old_prefix, new_prefix) 94 | with open(os.path.join(sys.prefix, "qt.conf"), "wt") as qtconf: 95 | qtconf.write(new_text) 96 | with open(os.path.join(sys.prefix, "Library", "bin", "qt.conf"), "wt") as qtconf: 97 | qtconf.write(new_text) 98 | 99 | 100 | if __name__ == "__main__": 101 | sys.exit(main()) 102 | -------------------------------------------------------------------------------- /bundle_scripts/README.md: -------------------------------------------------------------------------------- 1 | # Bundle Scripts 2 | 3 | The scripts in this directory are specially constructed to run from a 4 | conda-pack'd bundled installation of SIFT. The types of scripts included are 5 | currently: 6 | 7 | 1. `SIFT.X` where `X` corresponds to a scripting extension specific to each 8 | platform. This is `.sh` for Linux (CentOS 7+), `.command` for OSX, and 9 | `.bat` for Windows. These scripts are placed in the root directory of 10 | the released bundle. 11 | 12 | Note to reuse code as much as possible some scripts may be copied to 13 | the appropriate name rather than existing as separate files. 14 | -------------------------------------------------------------------------------- /bundle_scripts/SIFT.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | REM Initialize SIFT installation if necessary and run SIFT 3 | 4 | set base_dir=%~p0 5 | 6 | REM Activate the conda environment 7 | call %base_dir%Scripts\activate 8 | 9 | REM Create a signal file that we have run conda-unpack 10 | set installed=%base_dir%.installed 11 | if not exist "%installed%" goto install 12 | 13 | set /p install_dir=< %installed% 14 | if not %base_dir% == %install_dir:~0,-1% goto install 15 | 16 | goto run_sift 17 | 18 | :install 19 | echo Running one-time initialization of SIFT installation... 20 | conda-unpack 21 | echo %base_dir% > %installed% 22 | 23 | :run_sift 24 | 25 | echo Running SIFT... 26 | 27 | python -m uwsift %* 28 | -------------------------------------------------------------------------------- /bundle_scripts/SIFT.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Usage: SIFT.sh 3 | # Description: Initialize the SIFT installation if necessary and run SIFT 4 | set -e 5 | 6 | # get current base directory for this script 7 | SOURCE="${BASH_SOURCE[0]}" 8 | while [[ -h "$SOURCE" ]] ; do SOURCE="$(readlink "$SOURCE")"; done 9 | BASE="$( cd -P "$( dirname "$SOURCE" )" && pwd )" 10 | 11 | # Remove user environment variables that may conflict with installation 12 | unset LD_PRELOAD 13 | unset LD_LIBRARY_PATH 14 | unset DYLD_LIBRARY_PATH 15 | unset PYTHONPATH 16 | export PYTHONNOUSERSITE=1 17 | 18 | # Activate the conda-pack'd environment 19 | source $BASE/bin/activate 20 | 21 | # Check if we already ran conda-unpack 22 | install_signal="${BASE}/.installed" 23 | if [[ "$(head -n 1 ${install_signal} 2>/dev/null)" != "${BASE}" ]]; then 24 | echo "Running one-time initialization of SIFT installation..." 25 | conda-unpack 26 | echo "${BASE}" > "${install_signal}" 27 | echo "Running SIFT..." 28 | fi 29 | 30 | python -m uwsift "$@" 31 | -------------------------------------------------------------------------------- /cmake/FindConda.cmake: -------------------------------------------------------------------------------- 1 | find_program( Conda_EXECUTABLE 2 | NAMES mamba conda 3 | PATHS ${CONDA_PREFIX}/bin ${CONDA_PREFIX}/Scripts ENV PATH 4 | ) 5 | 6 | if( NOT DEFINED ${Conda_EXECUTABLE} AND DEFINED ENV{CONDA_EXE} ) 7 | set( Conda_EXECUTABLE $ENV{CONDA_EXE} CACHE PATH "Path to an executable" ) 8 | endif() 9 | 10 | if( DEFINED ENV{CONDA_PREFIX} ) 11 | set( CONDA_PREFIX $ENV{CONDA_PREFIX} ) 12 | else() 13 | # Assuming the active conda environment is on PATH, this finds the path of bin/ in the environment 14 | if( Conda_EXECUTABLE ) 15 | execute_process( COMMAND ${Conda_EXECUTABLE} info --root 16 | OUTPUT_VARIABLE CONDA_PREFIX 17 | OUTPUT_STRIP_TRAILING_WHITESPACE 18 | ) 19 | execute_process(COMMAND ${Conda_EXECUTABLE} info --envs ) 20 | else() 21 | message( "No Conda installation found in PATH!\nPATH=$ENV{PATH}\n" ) 22 | endif() 23 | endif() 24 | 25 | set( Conda_ENVIRONMENT_DIR ${CONDA_PREFIX} ) 26 | set( Conda_ENVIRONMENT $ENV{CONDA_DEFAULT_ENV} ) 27 | 28 | #------------------------------------------------------------------------------- 29 | # Determine Conda repository platform name 30 | # 31 | # Asking conda for that information is tedious, let's calculate ourselves 32 | 33 | string( TOLOWER ${CMAKE_SYSTEM_NAME} Conda_SYSTEM_NAME ) 34 | if( ${CMAKE_SYSTEM_PROCESSOR} MATCHES .*64.* ) 35 | set( Conda_SYSTEM_PROCESSOR 64 ) 36 | else() 37 | set( Conda_SYSTEM_PROCESSOR 32 ) 38 | endif() 39 | 40 | set( Conda_PLATFORM ${Conda_SYSTEM_NAME}-${Conda_SYSTEM_PROCESSOR} ) 41 | 42 | #------------------------------------------------------------------------------- 43 | # Finalize 44 | 45 | include(FindPackageHandleStandardArgs) 46 | find_package_handle_standard_args(Conda 47 | REQUIRED_VARS Conda_ENVIRONMENT Conda_EXECUTABLE Conda_PLATFORM 48 | ) 49 | -------------------------------------------------------------------------------- /cmake/FindPyInstaller.cmake: -------------------------------------------------------------------------------- 1 | # Find PyInstaller 2 | # Will find the path to Makespec.py and Build.py 3 | 4 | # python Makespec.py [opts] [ ...] 5 | # python Build.py specfile 6 | find_program( PyInstaller_EXECUTABLE 7 | NAMES pyinstaller 8 | DOC "Path to the pyinstaller executable" 9 | ) 10 | 11 | # $ python Makespec.py hello.py 12 | # -> wrote /home/mmalaterre/Projects/pyinstaller/hello/hello.spec 13 | set( PyInstaller_MAKESPEC 14 | ${PyInstaller_PATH}/Makespec.py 15 | ) 16 | 17 | set( PyInstaller_BUILD_SPEC 18 | ${PyInstaller_PATH}/Build.py 19 | ) 20 | 21 | # Look for Python: 22 | #find_package( PythonLibs REQUIRED ) 23 | -------------------------------------------------------------------------------- /conda-envs/sift-devel-minimal.pkgs: -------------------------------------------------------------------------------- 1 | # This file may be used to create an environment using: 2 | # e.g. ENV=devel 3 | # $ conda create --name $ENV --channel conda-forge --strict-channel-priority python=3.10 4 | # $ conda activate $ENV 5 | # $ conda config --env --add channels conda-forge 6 | # $ conda config --env --set channel_priority strict 7 | # $ conda install --file 8 | # 9 | # Only the minimal set of packages to install is listed (that is the intention 10 | # at least), all further dependencies should be resolved by Conda. 11 | # 12 | defusedxml=0.7.1 13 | donfig=0.7.0 14 | imageio-ffmpeg=0.4.7 15 | # imageio-ffmpeg -> ffmpeg 16 | # imageio-ffmpeg -> imageio 17 | matplotlib=3.5.2 18 | numba=0.55.2 19 | proj=9.1.0 20 | pyproj=3.4.1 21 | pygrib=2.1.4 22 | pyqtgraph=0.12.4 23 | pyqtwebengine=5.15.7 24 | # pyqtwebengine # -> pyqt 25 | pyshp=2.3.1 26 | rasterio=1.3.4 27 | satpy=0.39.0 28 | # satpy -> appdirs 29 | # satpy -> h5py 30 | # satpy -> netcdf4 31 | # satpy -> numpy 32 | # satpy -> pillow 33 | # satpy -> pyproj 34 | # satpy -> pyyaml 35 | scikit-image=0.19.3 36 | shapely=2.0.0 37 | sqlalchemy=1.4.39 38 | vispy=0.12.1 39 | 40 | # Explicit Satpy dependencies to make more readers work 41 | bottleneck=1.3.5 42 | h5netcdf=1.1.0 43 | hdf5plugin=4.0.1 44 | # pygac: not available in conda-forge, you may have a look here: https://anaconda.org/bucricket/pygac 45 | pyhdf=0.10.5 46 | python-eccodes=1.4.2 # This and its dependency 'eecodes' seem to be broken on Windows 47 | rioxarray=0.13.3 48 | 49 | # This is only for development 50 | cmake=3.24.0 51 | conda-build=3.21.9 52 | git=2.39.1 53 | make=4.3 54 | pre-commit=2.21.0 55 | pyinstaller-hooks-contrib=2022.8 56 | pyinstaller=5.1 57 | pytest-mock=3.8.2 58 | pytest-qt=4.1.0 59 | pytest=7.1.2 60 | sphinx=5.1.1 61 | # sphinx -> sphinxcontrib-applehelp=1.0.2 62 | # sphinx -> sphinxcontrib-devhelp=1.0.2 63 | # sphinx -> sphinxcontrib-htmlhelp=2.0.0 64 | # sphinx -> sphinxcontrib-jsmath=1.0.1 65 | # sphinx -> sphinxcontrib-qthelp=1.0.3 66 | # sphinx -> sphinxcontrib-serializinghtml=1.1.5 67 | -------------------------------------------------------------------------------- /continuous_integration/build_conda_pack.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -ex 4 | GIT_TAG="${GITHUB_REF##*/}" 5 | 6 | if [[ $GIT_TAG =~ [0-9]+.[0-9]+.[0-9]+ ]]; then 7 | # valid tag (use default script options) 8 | oflag="" 9 | else 10 | # master branch 11 | version=$(python -c "from uwsift import __version__; print(__version__)") 12 | 13 | if [[ "${OS}" == "windows-latest" ]]; then 14 | ext="zip" 15 | platform="windows" 16 | else 17 | ext="tar.gz" 18 | if [[ "${OS}" == "macos-latest" ]]; then 19 | platform="darwin" 20 | else 21 | platform="linux" 22 | fi; 23 | fi; 24 | oflag="-o SIFT_${version}dev_${platform}_$(date +%Y%m%d_%H%M%S).${ext}" 25 | fi 26 | 27 | python build_conda_pack.py -j -1 $oflag 28 | ls -l 29 | 30 | set +ex 31 | -------------------------------------------------------------------------------- /continuous_integration/environment.yaml: -------------------------------------------------------------------------------- 1 | name: test-environment 2 | channels: 3 | - conda-forge 4 | dependencies: 5 | # limiting python due to ecmwflibs 6 | - python<=3.11 7 | - appdirs 8 | - defusedxml 9 | - Cython 10 | # until https://github.com/imageio/imageio/issues/1120 is solved we need to limit imageio and pyav 11 | - imageio<=2.35.1 12 | - av<14.0.0 13 | - matplotlib 14 | - numba 15 | - numpy 16 | - pyproj 17 | - pyshp 18 | - pyqt 19 | - pyqtgraph 20 | - pyqtwebengine 21 | - satpy 22 | - scikit-image 23 | - shapely 24 | - sqlalchemy 25 | - vispy 26 | ### Satpy-only Optional Deps 27 | - bottleneck 28 | - dask 29 | - donfig 30 | # 2.19.1 seems to cause library linking issues 31 | - eccodes>=2.20 32 | - cfgrib 33 | - fsspec 34 | - h5netcdf 35 | - h5py 36 | - hdf5plugin 37 | - netcdf4 38 | - pillow 39 | - pooch 40 | - pyhdf 41 | - pyresample 42 | - python-eccodes 43 | - python-geotiepoints 44 | - pyyaml 45 | - rasterio 46 | - rioxarray 47 | - xarray 48 | - zarr 49 | ### Development/Test dependencies 50 | - coveralls 51 | - coverage 52 | - codecov 53 | - pytest 54 | - pytest-cov 55 | - pytest-mock 56 | - pytest-qt 57 | - pip 58 | - sphinx 59 | ### Pip Dependencies 60 | - pip: 61 | - trollsift 62 | - trollimage 63 | - pyspectral 64 | - pyorbital 65 | - ecmwflibs 66 | -------------------------------------------------------------------------------- /continuous_integration/linux_full_deps_apt.txt: -------------------------------------------------------------------------------- 1 | libglu1-mesa-dev 2 | libgl1-mesa-dev 3 | libxi-dev 4 | libglfw3-dev 5 | libgles2-mesa-dev 6 | libsdl2-2.0-0 7 | mesa-utils 8 | -------------------------------------------------------------------------------- /continuous_integration/rtd_environment.yaml: -------------------------------------------------------------------------------- 1 | name: test-environment 2 | channels: 3 | - conda-forge 4 | dependencies: 5 | # limiting python due to ecmwflibs 6 | - python<=3.11 7 | - appdirs 8 | - defusedxml 9 | - Cython 10 | - imageio 11 | - imageio-ffmpeg 12 | - matplotlib 13 | - numba 14 | - numpy 15 | - pyproj 16 | - pyshp 17 | - pyqt 18 | - pyqtgraph 19 | - pyqtwebengine 20 | - satpy 21 | - scikit-image 22 | - shapely 23 | - sqlalchemy 24 | - vispy 25 | ### Satpy-only Optional Deps 26 | - bottleneck 27 | - dask 28 | - donfig 29 | # 2.19.1 seems to cause library linking issues 30 | - eccodes>=2.20 31 | - cfgrib 32 | - fsspec 33 | - h5netcdf 34 | - h5py 35 | - hdf5plugin 36 | - netcdf4 37 | - pillow 38 | - pooch 39 | - pyhdf 40 | - pyresample 41 | - python-eccodes 42 | - python-geotiepoints 43 | - pyyaml 44 | - rasterio 45 | - rioxarray 46 | - xarray 47 | - zarr 48 | ### Development/Test dependencies 49 | - coveralls 50 | - coverage 51 | - codecov 52 | - pytest 53 | - pytest-cov 54 | - pytest-mock 55 | - pytest-qt 56 | - pip 57 | - sphinx 58 | ### Pip Dependencies 59 | - pip: 60 | - trollsift 61 | - trollimage 62 | - pyspectral 63 | - pyorbital 64 | - ecmwflibs 65 | # docs: 66 | - blockdiag 67 | - sphinx 68 | - sphinx-rtd-theme 69 | - sphinxcontrib-seqdiag 70 | - sphinxcontrib-blockdiag 71 | - psutil 72 | -------------------------------------------------------------------------------- /continuous_integration/upload_conda_pack.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -ex 4 | 5 | GIT_TAG="${GITHUB_REF##*/}" 6 | if [[ $GIT_TAG =~ [0-9]+.[0-9]+.[0-9]+ ]]; then 7 | # valid tag 8 | odir="" 9 | else 10 | # master branch 11 | odir="experimental/" 12 | fi 13 | # Upload the new bundle 14 | curl -k --ftp-create-dirs -T SIFT_*.*.*_*.* --key $HOME/.ssh/id_rsa_sftp sftp://sift@ftp.ssec.wisc.edu/${odir} 15 | set +e 16 | # Delete any old 17 | if [[ $GIT_TAG =~ [0-9]+.[0-9]+.[0-9]+ ]]; then 18 | curl -k -l --key $HOME/.ssh/id_rsa_sftp sftp://sift@ftp.ssec.wisc.edu/experimental/ | grep SIFT_*.*.*_*.* | xargs -I{} -- curl -k -v --key $HOME/.ssh/id_rsa_sftp sftp://sift@ftp.ssec.wisc.edu/experimental/ -Q "RM experimental/{}" 19 | if [ $? -ne 0 ]; then 20 | echo "Failed to delete old experimental SIFT tarballs from FTP server" 21 | fi 22 | fi 23 | 24 | set +x 25 | -------------------------------------------------------------------------------- /doc/source/_static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssec/sift/5a949ee4fa4a823d262bc39a42551a5b96679788/doc/source/_static/.gitkeep -------------------------------------------------------------------------------- /doc/source/api/uwsift.control.rst: -------------------------------------------------------------------------------- 1 | uwsift.control package 2 | ====================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | uwsift.control.auto\_update module 8 | ---------------------------------- 9 | 10 | .. automodule:: uwsift.control.auto_update 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | uwsift.control.qml\_utils module 16 | -------------------------------- 17 | 18 | .. automodule:: uwsift.control.qml_utils 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | uwsift.control.time\_matcher module 24 | ----------------------------------- 25 | 26 | .. automodule:: uwsift.control.time_matcher 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | uwsift.control.time\_matcher\_policies module 32 | --------------------------------------------- 33 | 34 | .. automodule:: uwsift.control.time_matcher_policies 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | 39 | uwsift.control.time\_transformer module 40 | --------------------------------------- 41 | 42 | .. automodule:: uwsift.control.time_transformer 43 | :members: 44 | :undoc-members: 45 | :show-inheritance: 46 | 47 | uwsift.control.time\_transformer\_policies module 48 | ------------------------------------------------- 49 | 50 | .. automodule:: uwsift.control.time_transformer_policies 51 | :members: 52 | :undoc-members: 53 | :show-inheritance: 54 | 55 | Module contents 56 | --------------- 57 | 58 | .. automodule:: uwsift.control 59 | :members: 60 | :undoc-members: 61 | :show-inheritance: 62 | -------------------------------------------------------------------------------- /doc/source/api/uwsift.model.rst: -------------------------------------------------------------------------------- 1 | uwsift.model package 2 | ==================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | uwsift.model.area\_definitions\_manager module 8 | ---------------------------------------------- 9 | 10 | .. automodule:: uwsift.model.area_definitions_manager 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | uwsift.model.catalogue module 16 | ----------------------------- 17 | 18 | .. automodule:: uwsift.model.catalogue 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | uwsift.model.composite\_recipes module 24 | -------------------------------------- 25 | 26 | .. automodule:: uwsift.model.composite_recipes 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | uwsift.model.document module 32 | ---------------------------- 33 | 34 | .. automodule:: uwsift.model.document 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | 39 | uwsift.model.layer\_item module 40 | ------------------------------- 41 | 42 | .. automodule:: uwsift.model.layer_item 43 | :members: 44 | :undoc-members: 45 | :show-inheritance: 46 | 47 | uwsift.model.layer\_model module 48 | -------------------------------- 49 | 50 | .. automodule:: uwsift.model.layer_model 51 | :members: 52 | :undoc-members: 53 | :show-inheritance: 54 | 55 | uwsift.model.product\_dataset module 56 | ------------------------------------ 57 | 58 | .. automodule:: uwsift.model.product_dataset 59 | :members: 60 | :undoc-members: 61 | :show-inheritance: 62 | 63 | uwsift.model.shapes module 64 | -------------------------- 65 | 66 | .. automodule:: uwsift.model.shapes 67 | :members: 68 | :undoc-members: 69 | :show-inheritance: 70 | 71 | uwsift.model.time\_manager module 72 | --------------------------------- 73 | 74 | .. automodule:: uwsift.model.time_manager 75 | :members: 76 | :undoc-members: 77 | :show-inheritance: 78 | 79 | Module contents 80 | --------------- 81 | 82 | .. automodule:: uwsift.model 83 | :members: 84 | :undoc-members: 85 | :show-inheritance: 86 | -------------------------------------------------------------------------------- /doc/source/api/uwsift.project.rst: -------------------------------------------------------------------------------- 1 | uwsift.project package 2 | ====================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | uwsift.project.organize\_data\_bands module 8 | ------------------------------------------- 9 | 10 | .. automodule:: uwsift.project.organize_data_bands 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | uwsift.project.organize\_data\_topics module 16 | -------------------------------------------- 17 | 18 | .. automodule:: uwsift.project.organize_data_topics 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | Module contents 24 | --------------- 25 | 26 | .. automodule:: uwsift.project 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | -------------------------------------------------------------------------------- /doc/source/api/uwsift.rst: -------------------------------------------------------------------------------- 1 | uwsift package 2 | ============== 3 | 4 | Subpackages 5 | ----------- 6 | 7 | .. toctree:: 8 | :maxdepth: 4 9 | 10 | uwsift.control 11 | uwsift.model 12 | uwsift.project 13 | uwsift.ui 14 | uwsift.util 15 | uwsift.view 16 | uwsift.workspace 17 | 18 | Submodules 19 | ---------- 20 | 21 | uwsift.common module 22 | -------------------- 23 | 24 | .. automodule:: uwsift.common 25 | :members: 26 | :undoc-members: 27 | :show-inheritance: 28 | 29 | uwsift.queue module 30 | ------------------- 31 | 32 | .. automodule:: uwsift.queue 33 | :members: 34 | :undoc-members: 35 | :show-inheritance: 36 | 37 | uwsift.satpy\_compat module 38 | --------------------------- 39 | 40 | .. automodule:: uwsift.satpy_compat 41 | :members: 42 | :undoc-members: 43 | :show-inheritance: 44 | 45 | uwsift.version module 46 | --------------------- 47 | 48 | .. automodule:: uwsift.version 49 | :members: 50 | :undoc-members: 51 | :show-inheritance: 52 | 53 | Module contents 54 | --------------- 55 | 56 | .. automodule:: uwsift 57 | :members: 58 | :undoc-members: 59 | :show-inheritance: 60 | -------------------------------------------------------------------------------- /doc/source/api/uwsift.ui.rst: -------------------------------------------------------------------------------- 1 | uwsift.ui package 2 | ================= 3 | 4 | Submodules 5 | ---------- 6 | 7 | uwsift.ui.change\_colormap\_dialog\_ui module 8 | --------------------------------------------- 9 | 10 | .. automodule:: uwsift.ui.change_colormap_dialog_ui 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | uwsift.ui.custom\_widgets module 16 | -------------------------------- 17 | 18 | .. automodule:: uwsift.ui.custom_widgets 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | uwsift.ui.dataset\_statistics\_widget\_ui module 24 | ------------------------------------------------ 25 | 26 | .. automodule:: uwsift.ui.dataset_statistics_widget_ui 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | uwsift.ui.export\_image\_dialog\_ui module 32 | ------------------------------------------ 33 | 34 | .. automodule:: uwsift.ui.export_image_dialog_ui 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | 39 | uwsift.ui.layer\_details\_widget\_ui module 40 | ------------------------------------------- 41 | 42 | .. automodule:: uwsift.ui.layer_details_widget_ui 43 | :members: 44 | :undoc-members: 45 | :show-inheritance: 46 | 47 | uwsift.ui.open\_cache\_dialog\_ui module 48 | ---------------------------------------- 49 | 50 | .. automodule:: uwsift.ui.open_cache_dialog_ui 51 | :members: 52 | :undoc-members: 53 | :show-inheritance: 54 | 55 | uwsift.ui.open\_file\_wizard\_ui module 56 | --------------------------------------- 57 | 58 | .. automodule:: uwsift.ui.open_file_wizard_ui 59 | :members: 60 | :undoc-members: 61 | :show-inheritance: 62 | 63 | uwsift.ui.pov\_main\_ui module 64 | ------------------------------ 65 | 66 | .. automodule:: uwsift.ui.pov_main_ui 67 | :members: 68 | :undoc-members: 69 | :show-inheritance: 70 | 71 | Module contents 72 | --------------- 73 | 74 | .. automodule:: uwsift.ui 75 | :members: 76 | :undoc-members: 77 | :show-inheritance: 78 | -------------------------------------------------------------------------------- /doc/source/api/uwsift.util.rst: -------------------------------------------------------------------------------- 1 | uwsift.util package 2 | =================== 3 | 4 | Subpackages 5 | ----------- 6 | 7 | .. toctree:: 8 | :maxdepth: 4 9 | 10 | uwsift.util.widgets 11 | 12 | Submodules 13 | ---------- 14 | 15 | uwsift.util.common module 16 | ------------------------- 17 | 18 | .. automodule:: uwsift.util.common 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | uwsift.util.default\_paths module 24 | --------------------------------- 25 | 26 | .. automodule:: uwsift.util.default_paths 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | uwsift.util.disk\_management module 32 | ----------------------------------- 33 | 34 | .. automodule:: uwsift.util.disk_management 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | 39 | uwsift.util.heap\_analyzer module 40 | --------------------------------- 41 | 42 | .. automodule:: uwsift.util.heap_analyzer 43 | :members: 44 | :undoc-members: 45 | :show-inheritance: 46 | 47 | uwsift.util.heap\_profiler module 48 | --------------------------------- 49 | 50 | .. automodule:: uwsift.util.heap_profiler 51 | :members: 52 | :undoc-members: 53 | :show-inheritance: 54 | 55 | uwsift.util.logger module 56 | ------------------------- 57 | 58 | .. automodule:: uwsift.util.logger 59 | :members: 60 | :undoc-members: 61 | :show-inheritance: 62 | 63 | uwsift.util.ps\_analyzer module 64 | ------------------------------- 65 | 66 | .. automodule:: uwsift.util.ps_analyzer 67 | :members: 68 | :undoc-members: 69 | :show-inheritance: 70 | 71 | uwsift.util.ps\_profiler module 72 | ------------------------------- 73 | 74 | .. automodule:: uwsift.util.ps_profiler 75 | :members: 76 | :undoc-members: 77 | :show-inheritance: 78 | 79 | uwsift.util.storage\_agent module 80 | --------------------------------- 81 | 82 | .. automodule:: uwsift.util.storage_agent 83 | :members: 84 | :undoc-members: 85 | :show-inheritance: 86 | 87 | uwsift.util.watchdog module 88 | --------------------------- 89 | 90 | .. automodule:: uwsift.util.watchdog 91 | :members: 92 | :undoc-members: 93 | :show-inheritance: 94 | 95 | Module contents 96 | --------------- 97 | 98 | .. automodule:: uwsift.util 99 | :members: 100 | :undoc-members: 101 | :show-inheritance: 102 | -------------------------------------------------------------------------------- /doc/source/api/uwsift.util.widgets.rst: -------------------------------------------------------------------------------- 1 | uwsift.util.widgets package 2 | =========================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | uwsift.util.widgets.pie\_dial module 8 | ------------------------------------ 9 | 10 | .. automodule:: uwsift.util.widgets.pie_dial 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | Module contents 16 | --------------- 17 | 18 | .. automodule:: uwsift.util.widgets 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | -------------------------------------------------------------------------------- /doc/source/api/uwsift.view.rst: -------------------------------------------------------------------------------- 1 | uwsift.view package 2 | =================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | uwsift.view.algebraic\_config module 8 | ------------------------------------ 9 | 10 | .. automodule:: uwsift.view.algebraic_config 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | uwsift.view.cameras module 16 | -------------------------- 17 | 18 | .. automodule:: uwsift.view.cameras 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | uwsift.view.colormap module 24 | --------------------------- 25 | 26 | .. automodule:: uwsift.view.colormap 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | uwsift.view.colormap\_editor module 32 | ----------------------------------- 33 | 34 | .. automodule:: uwsift.view.colormap_editor 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | 39 | uwsift.view.dataset\_statistics\_pane module 40 | -------------------------------------------- 41 | 42 | .. automodule:: uwsift.view.dataset_statistics_pane 43 | :members: 44 | :undoc-members: 45 | :show-inheritance: 46 | 47 | uwsift.view.export\_image module 48 | -------------------------------- 49 | 50 | .. automodule:: uwsift.view.export_image 51 | :members: 52 | :undoc-members: 53 | :show-inheritance: 54 | 55 | uwsift.view.layer\_details module 56 | --------------------------------- 57 | 58 | .. automodule:: uwsift.view.layer_details 59 | :members: 60 | :undoc-members: 61 | :show-inheritance: 62 | 63 | uwsift.view.layer\_tree\_view module 64 | ------------------------------------ 65 | 66 | .. automodule:: uwsift.view.layer_tree_view 67 | :members: 68 | :undoc-members: 69 | :show-inheritance: 70 | 71 | uwsift.view.open\_file\_wizard module 72 | ------------------------------------- 73 | 74 | .. automodule:: uwsift.view.open_file_wizard 75 | :members: 76 | :undoc-members: 77 | :show-inheritance: 78 | 79 | uwsift.view.probes module 80 | ------------------------- 81 | 82 | .. automodule:: uwsift.view.probes 83 | :members: 84 | :undoc-members: 85 | :show-inheritance: 86 | 87 | uwsift.view.rgb\_config module 88 | ------------------------------ 89 | 90 | .. automodule:: uwsift.view.rgb_config 91 | :members: 92 | :undoc-members: 93 | :show-inheritance: 94 | 95 | uwsift.view.scene\_graph module 96 | ------------------------------- 97 | 98 | .. automodule:: uwsift.view.scene_graph 99 | :members: 100 | :undoc-members: 101 | :show-inheritance: 102 | 103 | uwsift.view.test\_visuals module 104 | -------------------------------- 105 | 106 | .. automodule:: uwsift.view.test_visuals 107 | :members: 108 | :undoc-members: 109 | :show-inheritance: 110 | 111 | uwsift.view.texture\_atlas module 112 | --------------------------------- 113 | 114 | .. automodule:: uwsift.view.texture_atlas 115 | :members: 116 | :undoc-members: 117 | :show-inheritance: 118 | 119 | uwsift.view.tile\_calculator module 120 | ----------------------------------- 121 | 122 | .. automodule:: uwsift.view.tile_calculator 123 | :members: 124 | :undoc-members: 125 | :show-inheritance: 126 | 127 | uwsift.view.transform module 128 | ---------------------------- 129 | 130 | .. automodule:: uwsift.view.transform 131 | :members: 132 | :undoc-members: 133 | :show-inheritance: 134 | 135 | uwsift.view.visuals module 136 | -------------------------- 137 | 138 | .. automodule:: uwsift.view.visuals 139 | :members: 140 | :undoc-members: 141 | :show-inheritance: 142 | 143 | Module contents 144 | --------------- 145 | 146 | .. automodule:: uwsift.view 147 | :members: 148 | :undoc-members: 149 | :show-inheritance: 150 | -------------------------------------------------------------------------------- /doc/source/api/uwsift.workspace.rst: -------------------------------------------------------------------------------- 1 | uwsift.workspace package 2 | ======================== 3 | 4 | Subpackages 5 | ----------- 6 | 7 | .. toctree:: 8 | :maxdepth: 4 9 | 10 | uwsift.workspace.utils 11 | 12 | Submodules 13 | ---------- 14 | 15 | uwsift.workspace.caching\_workspace module 16 | ------------------------------------------ 17 | 18 | .. automodule:: uwsift.workspace.caching_workspace 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | 23 | uwsift.workspace.collector module 24 | --------------------------------- 25 | 26 | .. automodule:: uwsift.workspace.collector 27 | :members: 28 | :undoc-members: 29 | :show-inheritance: 30 | 31 | uwsift.workspace.guidebook module 32 | --------------------------------- 33 | 34 | .. automodule:: uwsift.workspace.guidebook 35 | :members: 36 | :undoc-members: 37 | :show-inheritance: 38 | 39 | uwsift.workspace.importer module 40 | -------------------------------- 41 | 42 | .. automodule:: uwsift.workspace.importer 43 | :members: 44 | :undoc-members: 45 | :show-inheritance: 46 | 47 | uwsift.workspace.metadatabase module 48 | ------------------------------------ 49 | 50 | .. automodule:: uwsift.workspace.metadatabase 51 | :members: 52 | :undoc-members: 53 | :show-inheritance: 54 | 55 | uwsift.workspace.simple\_workspace module 56 | ----------------------------------------- 57 | 58 | .. automodule:: uwsift.workspace.simple_workspace 59 | :members: 60 | :undoc-members: 61 | :show-inheritance: 62 | 63 | uwsift.workspace.statistics module 64 | ---------------------------------- 65 | 66 | .. automodule:: uwsift.workspace.statistics 67 | :members: 68 | :undoc-members: 69 | :show-inheritance: 70 | 71 | uwsift.workspace.workspace module 72 | --------------------------------- 73 | 74 | .. automodule:: uwsift.workspace.workspace 75 | :members: 76 | :undoc-members: 77 | :show-inheritance: 78 | 79 | Module contents 80 | --------------- 81 | 82 | .. automodule:: uwsift.workspace 83 | :members: 84 | :undoc-members: 85 | :show-inheritance: 86 | -------------------------------------------------------------------------------- /doc/source/api/uwsift.workspace.utils.rst: -------------------------------------------------------------------------------- 1 | uwsift.workspace.utils package 2 | ============================== 3 | 4 | Submodules 5 | ---------- 6 | 7 | uwsift.workspace.utils.metadata\_utils module 8 | --------------------------------------------- 9 | 10 | .. automodule:: uwsift.workspace.utils.metadata_utils 11 | :members: 12 | :undoc-members: 13 | :show-inheritance: 14 | 15 | Module contents 16 | --------------- 17 | 18 | .. automodule:: uwsift.workspace.utils 19 | :members: 20 | :undoc-members: 21 | :show-inheritance: 22 | -------------------------------------------------------------------------------- /doc/source/configuration/area_definitions.rst: -------------------------------------------------------------------------------- 1 | .. role:: yaml(code) 2 | 3 | Configuring Area Definitions 4 | ---------------------------- 5 | 6 | SIFT allows only map projections which are provided by configuration via 7 | Satpy. All or some of them must be "activated" for use by configuring 8 | ``area_definitions`` as follows:: 9 | 10 | area_definitions: 11 | [DISPLAY_NAME_AREA_GROUP_1]: 12 | { 13 | [DISPLAY_RESOLUTION_IDENTIFIER_1_1] : [AREA_ID_1_1], 14 | [DISPLAY_RESOLUTION_IDENTIFIER_1_2] : [AREA_ID_1_2], 15 | ... 16 | } 17 | ... 18 | [DISPLAY_NAME_AREA_GROUP_N]: 19 | { 20 | [DISPLAY_RESOLUTION_IDENTIFIER_N_1] : [AREA_ID_N_1], 21 | [DISPLAY_RESOLUTION_IDENTIFIER_N_2] : [AREA_ID_N_2], 22 | ... 23 | } 24 | 25 | where ``DISPLAY_NAME_AREA_GROUP_i`` is the name to be used in the GUI to refer to the area group. Each 26 | ``DISPLAY_NAME_AREA_GROUP_i`` represents a group of areas that share the same projection but have 27 | different resolutions. Therefore, within a single area group, there are one or more areas organized 28 | in a key-value structure. The key denotes ``DISPLAY_RESOLUTION_IDENTIFIER_i_j``, which is used in the GUI 29 | to represent resolutions for the selected area group. The value represents ``AREA_ID_i_j``, by which a 30 | specific area definition is reached. Area ID ``AREA_ID_i_j`` must be provided by according Satpy 31 | configuration (unknown area ids are skipped with a warning log message). 32 | 33 | The area groups appear in the *Projection:* picklist in the same order they are listed in the 34 | ``area_definitions`` configuration, with the first entry selected at application start. The resolution 35 | identifiers appear in the *Resolution:* picklist in the Open File Wizard window based on the selected 36 | projection (area group). They are listed in the same order as within a single area group in the 37 | ``area_definitions`` configuration, and by default, the first resolution identifier entry is selected. 38 | In this way, the user has the possibility to select the projection and the resolution and based on that the area 39 | ID is determined. 40 | 41 | One additional area definition is appended as a fallback by SIFT if no area 42 | definition or none with a pseudo lat/lon projection (Plate Carree) is 43 | found. This is to make sure there is always a projection showing the whole world 44 | selectable in the application, which is useful for examining data of a yet unknown 45 | area. 46 | 47 | **Example**:: 48 | 49 | area_definitions: 50 | MTG FCI FDSS: 51 | { 52 | 1km: mtg_fci_fdss_1km, 53 | 2km: mtg_fci_fdss_2km, 54 | 500m: mtg_fci_fdss_500m, 55 | 32km: mtg_fci_fdss_32km 56 | } 57 | 58 | MSG SEVIRI FES: 59 | { 60 | 3km: msg_seviri_fes_3km, 61 | 1km: msg_seviri_fes_1km, 62 | 9km: msg_seviri_fes_9km 63 | } 64 | -------------------------------------------------------------------------------- /doc/source/configuration/default_colormaps.rst: -------------------------------------------------------------------------------- 1 | Configuring a Colormap and its Colorlimits Based on the Dataset Standard Name 2 | ----------------------------------------------------------------------------- 3 | 4 | SIFT automatically associates a colormap and a value range to a newly 5 | loaded dataset based on the standard name of each dataset via its internal 6 | *Guidebook*. The colormap is applied to the values in the range, values 7 | outside this range get the first respectively last color of the colormap. 8 | 9 | This association can be overwritten by configuring a colormap and range 10 | (optional) as follows:: 11 | 12 | default_colormaps: 13 | STANDARD_NAME_1: 14 | colormap: COLORMAP_NAME_1 15 | range: RANGE_1 16 | STANDARD_NAME_2: 17 | colormap: COLORMAP_NAME_2 18 | ... 19 | 20 | **Example** :: 21 | 22 | default_colormaps: 23 | toa_bidirectional_reflectance: 24 | colormap: IR Color Clouds Summer 25 | range: [-1.2, 120] 26 | toa_brightness_temperature: 27 | colormap: Square Root (Vis Default) 28 | 29 | 30 | If a given ``COLORMAP_NAME_`` is not registered internally a warning is 31 | logged and the colormap is chosen by the Guidebook as fallback. The same 32 | happens for all standard names which are not listed in the configuration. 33 | 34 | .. note :: 35 | 36 | When file based caching is active changing the associated default colormap or clims 37 | by configuration will not affect data which is already cached from an 38 | earlier run of SIFT because the colormap is stored as meta-data in the 39 | cache. In such a case you may destroy the cache (usually at 40 | ``~/.cache/SIFT``) or manually choose the wanted colormap after loading the 41 | data. 42 | -------------------------------------------------------------------------------- /doc/source/configuration/display.rst: -------------------------------------------------------------------------------- 1 | .. role:: yaml(code) 2 | 3 | Configuring Display Options 4 | --------------------------- 5 | 6 | Display settings can be configured below the item ``display``. 7 | 8 | Geostationary satellite imagery can be displayed in its original projection or 9 | with a projection transformation applied to fit the currently selected map 10 | projection. The former is referred to here as *pixel matrix display*, while the 11 | latter is referred to as *geolocated display*. SIFT implements two kinds of 12 | geolocated display: the so-called *tiled geolocated image display* and the 13 | *simple geolocated image display*. 14 | 15 | The kind of display used for image data (data with an *AreaDefinition* in Satpy 16 | terms) is controlled by setting the `display.image_mode` configuration to one of 17 | three options: 18 | 19 | - `simple_geolocated`: In this mode the rasterisation of image data to the 20 | screen pixels is done entirely on the GPU. Technically, the image is placed as 21 | a texture on a coarser grid (a regular subdivision of a quad). This is then 22 | re-projected, resulting in the appropriate distortion of the texture to 23 | resemble the map projection. The accuracy of this kind of projection 24 | can be controlled by setting the `display.grid_cell_width` and 25 | `display.grid_cell_height` options, which specify the size in metres of the 26 | subdivision grid cell containing the sub-satellite point. The smaller the 27 | value, the finer the grid and the more accurate the projection, but the more 28 | time and memory consuming the projection will be. 29 | 30 | As long as the projection of the data is exactly the same as the currently 31 | selected display projection the result is the same as when using the pixel 32 | matrix display. 33 | 34 | - `tiled_geolocated`: The image is broken into smaller pieces (called tiles), 35 | which are resampled to currently 512x512 pixels each before being passed to 36 | the GPU, which does the final rasterisation to screen pixels. The advantage 37 | of this is that images that exceed the texture size limitations of the GPU 38 | can still be rendered. 39 | 40 | - `pixel_matrix`: The image is only scaled and moved when zooming in and out 41 | or panning, but otherwise no map projection is applied. This ensures that 42 | the original data can be examined without any resampling artefacts. Changing 43 | the current map projection has no effect on the visualisation of the data, 44 | so the coastline and latitude/longitude grid overlay would no longer fit the 45 | data. Also, loading data with different projections is usually not useful 46 | with this setting. 47 | 48 | Currently the modes are mutually exclusive and only one mode can be used during 49 | the same SIFT session. By default, *simple geolocated image display* with a 50 | subdivision grid resolution of 24000 metres is active, as in this 51 | configuration:: 52 | 53 | display: 54 | image_mode: simple_geolocated 55 | grid_cell_width: 24000 56 | grid_cell_height: 24000 57 | -------------------------------------------------------------------------------- /doc/source/configuration/external_satpy.rst: -------------------------------------------------------------------------------- 1 | Configuring External Satpy Components 2 | ===================================== 3 | 4 | SIFT can use external :ref:`Satpy component configuration ` folder, 5 | that hosts extra ``readers``, ``composites``, ``enhancements`` and ``areas`` definitions. 6 | To use the external satpy component configuration it is necessary to define either 7 | ``satpy_extra_config_path`` in the personal user configs (e.g. inside a file called `external_satpy.yaml`):: 8 | 9 | satpy_extra_config_path: [directory path] 10 | 11 | or the environment variable ``SATPY_CONFIG_PATH`` as described `here `_. 12 | 13 | Example of external readers configuration 14 | ----------------------------------------- 15 | 16 | Several data formats which are or will be produced by EUMETSAT need special 17 | readers which are not (yet) part of the official Satpy distribution. EUMETSAT 18 | maintains a Git repository ``satpy/local_readers`` on their `GitLab 19 | `_ providing these special 20 | readers. To use these readers it is neccsary to put them into folder: ``satpy_extra_config_path/readers``. 21 | 22 | Furthermore the desired readers need to be added to the configuration 23 | ``data_reading.readers`` and their reader specific configuration as well (see 24 | **TODO**). 25 | 26 | For example assuming that the repository has been cloned as follows:: 27 | 28 | git clone https://gitlab.eumetsat.int/satpy/local_readers.git /path/to/satpy_extra_config_path/readers 29 | 30 | the readers for the *FCI L1 Landmark Locations Catalogue*, *FCI L1 GEOOBS 31 | Landmarks* (landmark locations) and *FCI L1 GEOOBS Landmark Matching Results* 32 | (landmark navigation error) can be made available in SIFT with:: 33 | 34 | satpy_extra_config_path: /path/to/satpy_extra_config_path 35 | 36 | data_reading: 37 | readers: 38 | ... 39 | - fci_l1_cat_lmk_loc 40 | - fci_l1_geoobs_lmk_loc 41 | - fci_l1_geoobs_lmk_nav_err 42 | ... 43 | 44 | and adding according reader detail configuration files 45 | ``~/.config/SIFT/settings/config/readers/fci_l1_cat_lmk_loc.yaml``, 46 | ``~/.config/SIFT/settings/config/readers/fci_l1_geoobs_lmk_loc.yaml`` and 47 | ``~/.config/SIFT/settings/config/readers/fci_l1_geoobs_lmk_nav_err.yaml``. 48 | -------------------------------------------------------------------------------- /doc/source/configuration/index.rst: -------------------------------------------------------------------------------- 1 | Configuration 2 | ------------- 3 | 4 | Many aspects of SIFT can or must be configured. 5 | 6 | The software comes with a default - *system* - configuration split in several 7 | separate files in a directory structure below the directory 8 | ``etc/``:: 9 | 10 | etc/ 11 | └── SIFT/ 12 | └── config/ 13 | ├── *.yaml 14 | └── readers/ 15 | └── *.yaml 16 | 17 | Configurations specific to single Satpy readers are in separate files in a 18 | sub-directory 'readers'. 19 | 20 | The configuration in this directory tree is not intended to be edited by the 21 | user, as any changes would be lost when the software is updated. 22 | Instead, to configure the software differently from the default, the user can 23 | place additional configuration files below the into an analogous directory 24 | tree:: 25 | 26 | / 27 | └── config/ 28 | ├── *.yaml 29 | └── readers/ 30 | └── *.yaml 31 | 32 | 33 | where USER_SIFT_CONFIG_DIR is the the standard operation system configuration 34 | path for the application SIFT 35 | (Windows: ``C:\Users\\AppData\Roaming\SIFT\``, 36 | Linux: ``~/.config/SIFT/``). 37 | 38 | The *user* configuration can be empty or only be partial: it is merged with the 39 | *system* configuration, adding or overwriting settings of the latter. 40 | It is not necessary to keep the configuration in individual files, it can be 41 | put into larger files as you wish. 42 | 43 | SIFT uses the Donfig config library, for additional details on how to write 44 | configurations have a look here: https://donfig.readthedocs.io/en/latest/. 45 | 46 | .. toctree:: 47 | :maxdepth: 2 48 | 49 | Logging 50 | Catalogue and Auto Update Mode 51 | Watchdog 52 | Default Colormaps 53 | Points Styles 54 | Display 55 | Layer Manager Display Names 56 | External Satpy 57 | Readers 58 | Latlon Grid Resolution 59 | Projections / Area Definitions 60 | Units 61 | Storage 62 | -------------------------------------------------------------------------------- /doc/source/configuration/latlon-grid-resolution.rst: -------------------------------------------------------------------------------- 1 | .. role:: yaml(code) 2 | 3 | Changing spacing of lat/lon grid 4 | -------------------------------- 5 | 6 | The spacing of the lat/lon grid can be controlled with the setting:: 7 | 8 | latlon_grid: 9 | resolution: [value] 10 | 11 | where ``[value]`` is the grid spacing in degrees as float value between 0.1 and 12 | 10.0. For values smaller and larger than these bounds the value is clamped 13 | before applied and a warning is logged. 14 | 15 | **Example** :: 16 | 17 | latlon_grid: 18 | resolution: 3.5 19 | -------------------------------------------------------------------------------- /doc/source/configuration/logging.rst: -------------------------------------------------------------------------------- 1 | .. role:: yaml(code) 2 | 3 | Configuring Logging 4 | ------------------- 5 | 6 | Logging can be configured to write either to the console or to a file. 7 | Furthermore the global log level can be set as well as individual levels for 8 | each logger. 9 | 10 | All logging configuration is done below the item ``logging``. 11 | 12 | Logging to file is activated, when an *absolute* [#abspath]_ file path is given 13 | for the keyword ``filename``:: 14 | 15 | logging: 16 | filename: [absolute file path] 17 | 18 | If the configured file is not writable, logging falls back to the console. 19 | 20 | A global log level can be set as follows:: 21 | 22 | logging: 23 | loggers: 24 | all: 25 | level: [log level] 26 | 27 | where ``[log level]`` must be one of ``CRITICAL``, ``ERROR``, ``WARNING``, 28 | ``INFO``, ``DEBUG`` or ``NOTSET``. The default log level is ``WARNING``. 29 | 30 | Additionally the log level of specifig loggers can be overwritten by listing 31 | their names below the keyword ``loggers`` and adding a ``level`` setting 32 | analogously. 33 | 34 | **Example** :: 35 | 36 | logging: 37 | filename: /tmp/sift.log 38 | loggers: 39 | all: 40 | level: DEBUG 41 | vispy: 42 | level: INFO 43 | 44 | With this configuration all log messages go to the file ``/tmp/sift.log`` and 45 | all modules output messages of all levels except for the module ``vispy`` which 46 | only outputs messages of level ``INFO`` and higher. 47 | 48 | 49 | .. rubric:: Footnotes 50 | 51 | .. [#abspath] Accepting a relative path could lead to stray log files in every 52 | directory which is current when SIFT is started. 53 | -------------------------------------------------------------------------------- /doc/source/configuration/points_styles.rst: -------------------------------------------------------------------------------- 1 | Points Styles 2 | ------------- 3 | 4 | Definition of Points Styles 5 | =========================== 6 | 7 | Named point styles are defined below the setting ``point_styles``. They follow 8 | the conventions of SVG/HTML styling (see https://www.w3.org/TR/SVG/styling.html 9 | and https://www.w3.org/TR/SVG/painting.html) but only a small subset is 10 | supported (yet):: 11 | 12 | point_styles: 13 | STYLE_NAME: 14 | symbol: SYMBOL_NAME 15 | size: LENGTH_DEFINITON 16 | fill: COLOR 17 | stroke: COLOR 18 | stroke-width: LENGTH_DEFINITON 19 | 20 | where 21 | 22 | - ``STYLE_NAME`` is an arbitrary name for the marker style to be defined 23 | - ``SYMBOL_NAME`` is one of ``disc``, ``arrow``, ``ring``, ``clobber``, 24 | ``square``, ``diamond``, ``vbar``, ``hbar``, ``cross``, ``tailed_arrow``, 25 | ``x``, ``triangle_up``, ``triangle_down``, ``star`` 26 | - ``LENGTH_DEFINITON`` is a number directly followed by one of the units ``px`` 27 | or ``%`` which controls, whether the value is interpreted in screen pixels or 28 | relative to the scene, i.e. zoom level dependant 29 | - ``COLOR`` is a string recognized by the underlying Vispy library (see 30 | http://vispy.org/color.html#vispy.color.Color), i.e., something like ``black`` 31 | or ``yellow`` or a hexadecimal representation of an RGB or RGBA value 32 | introduced by '``#``' (e.g., ``'#00FF0080'`` is semitransparent green). Note, 33 | that in the latter case the string *must be quoted* to prevent the 34 | configuration parser from interpreting the '``#``' as begin of a comment. 35 | 36 | All styling settings are optional, for missing ones a predefined default is 37 | chosen. 38 | 39 | **Example** 40 | 41 | The following would be an explicit definition of the default marker style:: 42 | 43 | point_styles: 44 | red_empty_cross: 45 | symbol: cross 46 | size: 9px 47 | fill: '#00000000' 48 | stroke: white 49 | stroke-width: 1px 50 | 51 | Configuring Point Styles Based on the Dataset Standard Name 52 | ----------------------------------------------------------- 53 | 54 | Analogous to the default colormap configuration the style of the markers used to 55 | render a dataset can (and - since there are no default definitions in the 56 | SIFT's internal *Guidebook* for this - should) be configured by associating a 57 | named points style to the standard name of each points dataset:: 58 | 59 | default_point_styles: 60 | STANDARD_NAME_1: STYLE_NAME_1 61 | STANDARD_NAME_2: STYLE_NAME_2 62 | ... 63 | 64 | **Example** :: 65 | 66 | default_colormaps: 67 | observed_lmk_locations_ir_105: red_empty_cross 68 | -------------------------------------------------------------------------------- /doc/source/configuration/standard_names.rst: -------------------------------------------------------------------------------- 1 | .. role:: yaml(code) 2 | 3 | Configuring Display Names For Layer Manager 4 | ------------------------------------------- 5 | 6 | The ``STANDARD_NAME`` of many products coming from Satpy is too long to display 7 | well in the Layer Manager column *Name*. Using the configration setting 8 | ``standard_names`` it is possible to define shorter names for display:: 9 | 10 | standard_names: 11 | '[STANDARD NAME 1]': [DISPLAY NAME 1] 12 | '[STANDARD NAME 2]': [DISPLAY NAME 2] 13 | 14 | For example, with the following configuration for ``reflectance_mean_all`` the 15 | displayed name will be *REFL (mean, all)*, for 16 | ``toa_outgoing_radiance_per_unit_wavelength`` it will be *RAD*:: 17 | 18 | standard_names: 19 | 'toa_outgoing_radiance_per_unit_wavelength': RAD 20 | 'reflectance_mean_all': REFL (mean, all) 21 | -------------------------------------------------------------------------------- /doc/source/configuration/storage.rst: -------------------------------------------------------------------------------- 1 | .. role:: yaml(code) 2 | 3 | Storage Configuration 4 | ===================== 5 | 6 | Activate File Based Inventory Database and Caching 7 | -------------------------------------------------- 8 | 9 | SIFT can either run with a file system based inventory database or without 10 | it. The first operation mode is useful if certain data files are loaded 11 | repeatedly while the latter is preferable when the system operates automatically 12 | and usually loads each file only once. 13 | 14 | The options to control the behaviour are in the ``storage`` group:: 15 | 16 | storage: 17 | use_inventory_db: [boolean] 18 | cleanup_file_cache: [boolean] 19 | 20 | The option ``use_inventory_db`` controls whether the inventory database is 21 | used. If so, in the `File` menu two items - `Open from Cache` and `Open Recent` 22 | - are available, which help loading recently loaded data again. 23 | 24 | The second option ``cleanup_file_cache`` controls, whether intermediate files 25 | used internally are removed as early as possible to keep the disk space usage 26 | low. This option has only an effect when ``use_inventory_db`` is ``False``, 27 | otherwise they are `not` housekept anyways. 28 | 29 | **Examples** 30 | 31 | For interactive sessions this configuration is most user-friendly:: 32 | 33 | storage: 34 | use_inventory_db: True 35 | 36 | In automated environments the following configuration is recommended (which is 37 | the default):: 38 | 39 | storage: 40 | use_inventory_db: False 41 | cleanup_file_cache: True 42 | 43 | Observing Directories with the Storage Agent 44 | -------------------------------------------- 45 | 46 | The settings below ``storage.agent`` are read by the *Storage Agent*:: 47 | 48 | storage: 49 | agent: 50 | notification_cmd: [path to executable] 51 | # interval: [number] 52 | files_lifetime: [number] 53 | directories: 54 | - [directory path 1] 55 | - [directory path 2] 56 | - ... 57 | 58 | All time related settings are in seconds. The ``files_lifetime`` setting defines 59 | the age of files with respect to their last modification in the given 60 | ``directories`` after which they are to be deleted. When given, ``interval`` is 61 | the time the storage agent waits, before it does its next check. It defaults to 62 | the ``files_lifetime`` or 60 seconds, whatever is lower. Finally if the 63 | ``notification_cmd`` is configured it will be called additionally to console 64 | logging to inform the GEMS monitoring system about events. 65 | 66 | The paths given for ``directories`` may contain a placeholder in the form 67 | ``$$CACHE_DIR$$``. When used, this part is expanded to the default cache 68 | directory for the application according to the XDG standard 69 | (``$$CACHE_DIR$$`` expands to ``~/.cache/SIFT`` on Linux systems). 70 | 71 | 72 | **Example** 73 | 74 | .. code-block:: yaml 75 | 76 | storage: 77 | agent: 78 | notification_cmd: /opt/eum/bin/raiseEvent.sh 79 | # interval: 60 80 | files_lifetime: 1200 81 | directories: 82 | - "$$CACHE_DIR$$/workspace/data_cache" 83 | - "$$CACHE_DIR$$/workspace/temp" 84 | -------------------------------------------------------------------------------- /doc/source/configuration/units.rst: -------------------------------------------------------------------------------- 1 | .. role:: yaml(code) 2 | 3 | Configuring Unit Display 4 | ------------------------ 5 | 6 | The unit of measurement for the display of physical values can be configured 7 | under the item ``units``. 8 | 9 | Currently, only the units for ``temperature`` calibrations can be configured to 10 | either ``kelvin`` (aliases ``K``, ``Kelvin``) or ``degrees_Celsius`` (aliases 11 | ``°C``, ``C``). 12 | 13 | The default for all temperatures can be configured using the keyword 14 | ``all``. The display setting for specific calibrations can be configured 15 | diffently. Currently known are ``toa_brightnes_temperature`` and 16 | ``brightnes_temperature``. 17 | 18 | If no configuration is provided every temperature display defaults to ``K`` 19 | (``kelvin``). 20 | 21 | An exemplary configuration may look as follows:: 22 | 23 | units: 24 | temperature: 25 | all: kelvin 26 | toa_brightness_temperature: degrees_Celsius 27 | brightness_temperature: kelvin 28 | -------------------------------------------------------------------------------- /doc/source/configuration/watchdog.rst: -------------------------------------------------------------------------------- 1 | Configuring Watchdog Functionality 2 | ---------------------------------- 3 | 4 | The *Watchdog* is a script (``uwsift/util/watchdog.py``) running separately from 5 | SIFT and has the responsibility to assess, whether SIFT running as 6 | monitoring tool (with ``auto_update.active: True``) is working correctly and to 7 | "bark" otherwise by calling an adaptor script *raiseEvent.sh* to notify 8 | GEMS. The location of this script has to be configured as ``notification_cmd``. 9 | 10 | The Watchdog does not directly interact with the running SIFT instance but 11 | monitors a file to be configured as ``heartbeat_file``, which SIFT updates 12 | with the data timestamp (i.e. the ``start_time`` is written into the file) every 13 | time it loads new data. From this information and the filesystem change time of 14 | the heartbeat file the Watchdog can determine, when the monitoring system is not 15 | alive anymore and/or it does not succeed to ingest up to date satellite 16 | data. With the frequency configured by ``heartbeat_check_interval`` the Watchdog 17 | reads the file and compares the time information against the current time and 18 | gives alarm, when the data timestamp stored is older than 19 | ``max_tolerable_dataset_age`` and/or the last time the heartbeat file was 20 | updated is longer ago than the ``max_tolerable_idle_time``. These three time 21 | span related configurations are in seconds. 22 | 23 | To work around the memory leak in SIFT, the watchdog is able to issue a 24 | restart request once the ``auto_restart_interval`` is over. If the user denies 25 | this request by cklicking on the *cancel* button in the popup window, the 26 | watchdog will send another request every ``auto_restart_ask_again_interval`` 27 | seconds. Both configuration options are in seconds and can be disabled with 28 | the value *0*. 29 | 30 | Furthermore the watchdog is capable of monitoring the memory consumption of the 31 | SIFT application. If the application exceeds the amount specified by 32 | ``max_memory_consumption``, a restart request is issued. The units ``M`` 33 | (*Mebibytes*) and ``G`` (*Gibiabytes*) can be used. If this setting is not 34 | given, the watchdog won't trigger a restart based on excessive memory 35 | consumption. 36 | 37 | **Note:** The units are interpreted with base 1024 to be compatible with 38 | analogous configuration options of `systemd` (see `systemd.resource-control: 39 | MemoryHigh 40 | `_) 41 | 42 | A complete watchdog configuration looks as follows: 43 | 44 | .. code-block:: yaml 45 | 46 | watchdog: 47 | heartbeat_file: "$$CACHE_DIR$$/heartbeat.txt" 48 | notification_cmd: /path/to/raiseEvent.sh 49 | heartbeat_check_interval: 30 50 | max_tolerable_dataset_age: 120 51 | max_tolerable_idle_time: 60 52 | auto_restart_interval: 86400 53 | auto_restart_ask_again_interval: 60 54 | max_memory_consumption: 5G 55 | 56 | Note the part ``$$CACHE_DIR$$`` of the path for the heartbeat file. When used, 57 | this part is expanded to the default cache directory for the application 58 | according to the XDG standard (``$$CACHE_DIR$$`` expands to ``~/.cache/SIFT`` 59 | on Linux systems). A normal absolute file path works too. 60 | -------------------------------------------------------------------------------- /doc/source/dev_guide/design_overview.rst: -------------------------------------------------------------------------------- 1 | Design Overview 2 | =============== 3 | 4 | SIFT's software design revolves around a few key components: 5 | 6 | - Main Window (GUI) 7 | - Workspace 8 | - Document 9 | - Scene Graph 10 | 11 | Each of these components is described in the sections below. Other 12 | components involved in accomplishing SIFT's feature. 13 | 14 | Main Window 15 | ----------- 16 | 17 | Currently the main window for the SIFT GUI connects all other components 18 | and helper objects. This may change in future versions of SIFT. By defining 19 | things this way the main window has access to UI events and can connect them 20 | to the other SIFT components that need to use them like those listed below. 21 | 22 | Workspace 23 | --------- 24 | 25 | The Workspace acts as the manager of on-disk or remote data. It will 26 | handle importing requested datasets, caching binary data, and storing 27 | dataset metadata in a database for easier querying. Since the Workspace 28 | manages all of the cached data it is also the best place that SIFT components 29 | will go for variations on the data (different resolutions, data within a 30 | polygon, etc). 31 | 32 | Document 33 | -------- 34 | 35 | The Document acts as the "model" of the Model-View-Controller design of SIFT. 36 | Through the Document a developer can get access to individual layer objects 37 | containing metadata, layer order, and animation order. In the future as other 38 | features are added to SIFT the Document may provide user profile or 39 | configuration information. 40 | 41 | Scene Graph 42 | ----------- 43 | 44 | The Scene Graph wraps all map canvas elements visual elements. 45 | It handles connecting all mouse events from the map canvas like pan and zoom 46 | events. The majority of this components responsibility is to map SIFT 47 | functions to the python ``vispy`` library. 48 | -------------------------------------------------------------------------------- /doc/source/dev_guide/index.rst: -------------------------------------------------------------------------------- 1 | Developer's Guide 2 | ================= 3 | 4 | This section of the documentation is focused on instructions and low-level 5 | information on how to work with SIFT as a developer. It may include everything 6 | from complex installation procedures, to design discussion, to help with 7 | contributing to the SIFT project. 8 | 9 | .. toctree:: 10 | :maxdepth: 2 11 | 12 | contributing 13 | design_overview 14 | writing_tests 15 | -------------------------------------------------------------------------------- /doc/source/dev_guide/writing_tests.rst: -------------------------------------------------------------------------------- 1 | Writing Tests 2 | ============= 3 | 4 | SIFT uses `pytest `_ as its testing framework and 5 | tests are automatically run in GitHub Actions. All tests should go under 6 | ``uwsift/tests`` and should be named ``test_.py``. 7 | Any multi-file pytest fixtures should be placed in ``conftest.py``. 8 | 9 | The below sections provide guidelines and gotchas for writing tests for SIFT. 10 | If you have any remaining questions you can create a GitHub issue or talk to 11 | the developers on `Gitter `_. 12 | 13 | Testing the GUI 14 | --------------- 15 | 16 | To test interactions with the SIFT GUI, you can use 17 | `pytest-qt `_, which is 18 | a pytest plugin that provides a fixture that makes it easy to interact with a 19 | dialog window. Examples of using this fixture can be found in the pytest-qt 20 | documentation or in 21 | `SIFT `_. 22 | 23 | A couple of things to note: 24 | 25 | * The window that you're testing must be in focus for qtbot to act on it. You 26 | can ensure the window is in focus by calling ``window.raise_()`` and 27 | ``window.activateWindow()`` (an example of this found 28 | `here `_). 29 | * Do not create an instance of the main SIFT window. There is a fixture of the 30 | main window provided in ``conftest.py`` that you should use instead. 31 | 32 | Things to note 33 | -------------- 34 | 35 | * Mocking in the pytest framework can be done with 36 | `monkeypatching `_, 37 | but `pytest-mock `_ 38 | (pytest plugin that wraps mock) can be used if more robust mock 39 | functionality is needed. 40 | * Coverage for functions decorated with ``@jit`` does not work, so in order 41 | to get an accurate coverage value, you should run the test once with 42 | ``@jit`` and then once without ``@jit`` by calling ``my_function.pyfunc`` 43 | instead. 44 | 45 | * An example of this is found in 46 | `test_tile_calculator.py `_. 47 | There is a fixture that runs tests once with functions with ``@jit`` 48 | enabled and once again with the original python functions 49 | 50 | * If you're running the tests on your local machine, do not click anywhere 51 | else while the tests are running. Some tests require that the SIFT GUI is 52 | in focus, otherwise they'll fail. 53 | 54 | Running the tests 55 | ----------------- 56 | 57 | All tests can be run using the command ``pytest path/to/uwsift``. A specific 58 | test directory or file can be run using ``pytest path/to/test``. The packages 59 | required to run the tests can be installed from conda with: 60 | 61 | .. code-block:: bash 62 | 63 | conda install pytest pytest-qt pytest-mock 64 | -------------------------------------------------------------------------------- /doc/source/diag/open_file.diag: -------------------------------------------------------------------------------- 1 | seqdiag { 2 | "UserOpensFileBehavior"; "Document"; "Workspace"; "SceneGraphManager"; 3 | 4 | UserOpensFileBehavior -> Document [ label = "openFile" ]; 5 | Document -> Workspace [ label = "import_image" ]; 6 | Document <- Workspace [ label = "uuid, info-dict, initial-content-array" ]; 7 | Document -> SceneGraphManager [ label = "didAddBasicLayer -> add_basic_layer" ]; 8 | SceneGraphManager -> SceneGraphManager [ label = "on_view_change" ]; 9 | Document <- SceneGraphManager; 10 | } 11 | -------------------------------------------------------------------------------- /doc/source/fonts/DejaVuSerif.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssec/sift/5a949ee4fa4a823d262bc39a42551a5b96679788/doc/source/fonts/DejaVuSerif.ttf -------------------------------------------------------------------------------- /doc/source/index.rst: -------------------------------------------------------------------------------- 1 | SIFT Documentation 2 | ================== 3 | 4 | SIFT, Satellite Information Familiarization Tool, is a GUI application 5 | for viewing and analyzing earth-observing satellite data. This documentation 6 | includes information on high-level concepts and how-tos of SIFT, but low-level 7 | information for advanced features and how to contribute to the project can also 8 | be found. 9 | 10 | For general information on the use of SIFT, official releases, and 11 | installation instructions of those releases see the SIFT 12 | `home page `_. Note that the library and 13 | python package for the SIFT project are named ``uwsift``. 14 | 15 | For source code see the `GitHub repository `_. 16 | 17 | .. toctree:: 18 | :maxdepth: 2 19 | 20 | installation 21 | Initial setup for packaging SIFT with CMake 22 | Configuring SIFT 23 | Auto Update Mode 24 | profiling 25 | API 26 | dev_guide/index 27 | 28 | Indices and tables 29 | ================== 30 | 31 | * :ref:`genindex` 32 | * :ref:`modindex` 33 | * :ref:`search` 34 | -------------------------------------------------------------------------------- /doc/source/profiling.rst: -------------------------------------------------------------------------------- 1 | SIFT Profiling 2 | ================== 3 | 4 | SIFT can be started with a custom Heap Profiler, which is using the Python 5 | tracemalloc module underneath. When done so it creates a directory 6 | ``_uwsift_heap_profile`` in the current working directory and stores 7 | memory usage snapshot data into it. The command to take a snapshot every 2.0 8 | seconds is as follows:: 9 | 10 | python -m uwsift --profile-heap 2.0 11 | 12 | Afterwards the snapshorts must be combined:: 13 | 14 | python ./uwsift/util/heap_analyzer.py --combine ./combined_stats.prof --snapshot-dir <_uwsift_heap_profile> 15 | 16 | This creates the file ``combined_stats.prof``, which can be visualized with 17 | matplotlib for analysis:: 18 | 19 | python ./uwsift/util/heap_analyzer.py --load ./combined_stats.prof --plot 20 | -------------------------------------------------------------------------------- /doc/source/test.diag: -------------------------------------------------------------------------------- 1 | seqdiag test { 2 | A => B => C; 3 | } 4 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools >= 40.9.0", "wheel", "oldest-supported-numpy"] 3 | build-backend = "setuptools.build_meta" 4 | 5 | [tool.black] 6 | line-length = 120 7 | exclude = ''' 8 | ( 9 | \.git 10 | | build 11 | | dist 12 | ) 13 | 14 | ''' 15 | 16 | [tool.coverage.run] 17 | relative_files = true 18 | omit = ["uwsift/version.py"] 19 | 20 | [tool.isort] 21 | sections = ["FUTURE", "STDLIB", "THIRDPARTY", "FIRSTPARTY", "LOCALFOLDER"] 22 | profile = "black" 23 | skip_gitignore = true 24 | default_section = "THIRDPARTY" 25 | known_first_party = "uwsift" 26 | skip = [".gitignore"] 27 | -------------------------------------------------------------------------------- /resources/bin/readme.txt: -------------------------------------------------------------------------------- 1 | Startup scripts for different platforms used in pyinstaller packaging. 2 | -------------------------------------------------------------------------------- /resources/bin/sift.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | set base_dir=%~dp0 4 | 5 | set PATH=%base_dir%;%PATH% 6 | 7 | cd "%base_dir%..\lib" || goto NOPACKAGE 8 | .\sift.exe %* 9 | goto END 10 | 11 | :END 12 | cd "%base_dir%" 13 | goto EOF 14 | 15 | :NOPACKAGE 16 | echo Failed to change into pyinstaller sift directory at %base_dir%..\lib 17 | msg "%USERNAME%" /TIME:0 /W "Failed to change into pyinstaller SIFT directory at %base_dir%..\lib" || pause 18 | 19 | :EOF 20 | -------------------------------------------------------------------------------- /resources/bin/sift.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | set -e 4 | set -u 5 | 6 | PROJ_NAME='sift' 7 | 8 | BASE_DIR="$(dirname -- "$0")/.." 9 | cd "$BASE_DIR" || exit 10 | BASE_DIR="$(pwd -P)" 11 | 12 | if [ -d "$BASE_DIR/lib/$PROJ_NAME" ] || [ ! -x "$BASE_DIR/lib/$PROJ_NAME" ]; then 13 | echo "Missing binary @ '$BASE_DIR/lib/$PROJ_NAME' to start $PROJ_NAME." 14 | exit 1 15 | fi 16 | 17 | PATH="$BASE_DIR/bin:$PATH" 18 | export PATH 19 | 20 | cd "$BASE_DIR/lib" || exit 21 | 22 | "./$PROJ_NAME" "$@" 23 | -------------------------------------------------------------------------------- /resources/pyinstaller/Library/bin/dummy.txt: -------------------------------------------------------------------------------- 1 | Dummy file to ensure the directory is not skipped by PyInstaller. 2 | 3 | This directory is required for llvmlite whose Conda package tries to add Library/bin with os.add_ddl_directory(...). 4 | -------------------------------------------------------------------------------- /resources/pyinstaller/rasterio/.libs/dummy.txt: -------------------------------------------------------------------------------- 1 | Dummy file to ensure the directory is not skipped by PyInstaller. 2 | 3 | Note: the rasterio/.libs directory is not anymore needed if 4 | https://github.com/rasterio/rasterio/pull/2626 is fixed. 5 | -------------------------------------------------------------------------------- /resources/service/uwsift-watchdog.service: -------------------------------------------------------------------------------- 1 | # copy this file to ~/.local/share/systemd/user/uwsift-watchdog.service 2 | # then activate auto-start: systemctl --user enable uwsift-watchdog.service 3 | 4 | [Unit] 5 | Description=Watchdog for SIFT 6 | After=uwsift.service 7 | 8 | [Service] 9 | Type=exec 10 | WorkingDirectory=/home/username/Dokumente/eumSIFT 11 | ExecStart=/var/local/miniconda3/envs/devel-default/bin/python -m uwsift.util.watchdog 12 | Restart=always 13 | 14 | [Install] 15 | WantedBy=default.target 16 | -------------------------------------------------------------------------------- /resources/service/uwsift.service: -------------------------------------------------------------------------------- 1 | # copy this file to ~/.local/share/systemd/user/uwsift.service 2 | # then activate auto-start: systemctl --user enable uwsift.service 3 | 4 | [Unit] 5 | Description=SIFT in monitoring mode 6 | After=graphical-session.target 7 | 8 | [Service] 9 | Type=exec 10 | # `User` and `Group` can't be used in a --user service 11 | Environment="DISPLAY=:1" 12 | WorkingDirectory=/home/username/documents/eumSIFT 13 | ExecStart=/var/local/miniconda3/envs/devel-default/bin/python -m uwsift 14 | Restart=always 15 | 16 | OOMPolicy=kill 17 | OOMScoreAdjust=100 18 | 19 | # soft and hard memory limits, no restart request 20 | MemoryHigh=5G 21 | MemoryMax=6G 22 | 23 | [Install] 24 | WantedBy=default.target 25 | -------------------------------------------------------------------------------- /rtd_requirements.txt: -------------------------------------------------------------------------------- 1 | blockdiag 2 | sphinxcontrib-seqdiag 3 | sphinxcontrib-blockdiag 4 | sphinx_rtd_theme 5 | numpy 6 | pillow 7 | pyproj 8 | sqlalchemy 9 | pyyaml 10 | appdirs 11 | donfig 12 | psutil 13 | setuptools>=65.5.1 # not directly required, pinned by Snyk to avoid a vulnerability 14 | requests>=2.32.2 # not directly required, pinned by Snyk to avoid a vulnerability 15 | urllib3>=2.2.2 # not directly required, pinned by Snyk to avoid a vulnerability 16 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 120 3 | ignore = D,D107,D202,E203,E226,E241,E265,E266,W291,W293,W503,F999,E305,F405,W503,W504 4 | exclude = 5 | uwsift/ui/* 6 | -------------------------------------------------------------------------------- /sift.iss: -------------------------------------------------------------------------------- 1 | ; -- sift.iss -- 2 | ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING .ISS SCRIPT FILES! 3 | 4 | [Setup] 5 | AppName=SIFT 6 | AppVersion=2.0.0b1 7 | DefaultDirName={pf}\SIFT 8 | DefaultGroupName=SIFT 9 | Compression=lzma2 10 | SolidCompression=yes 11 | OutputDir=sift_inno_setup_output 12 | 13 | [Files] 14 | Source: "dist\SIFT\*"; DestDir: "{app}\bin"; Flags: replacesameversion recursesubdirs 15 | Source: "INSTALLER_README.md"; DestName: "README.txt"; DestDir: "{app}"; Flags: isreadme; AfterInstall: ConvertLineEndings 16 | 17 | [Icons] 18 | Name: "{group}\SIFT"; Filename: "{app}\bin\SIFT.exe" 19 | Name: "{group}\Bug Tracker"; Filename: "https://github.com/ssec/sift/issues" 20 | Name: "{group}\Wiki"; Filename: "https://github.com/ssec/sift/wiki" 21 | Name: "{group}\Open Workspace Folder"; Filename: "{%WORKSPACE_DB_DIR}" 22 | Name: "{group}\Open Settings Folder"; Filename: "{%DOCUMENT_SETTINGS_DIR}" 23 | Name: "{group}\Uninstall SIFT"; Filename: "{uninstallexe}" 24 | 25 | [Code] 26 | const 27 | LF = #10; 28 | CR = #13; 29 | CRLF = CR + LF; 30 | 31 | procedure ConvertLineEndings(); 32 | var 33 | FilePath : String; 34 | FileContents : String; 35 | begin 36 | FilePath := ExpandConstant(CurrentFileName) 37 | LoadStringFromFile(FilePath, FileContents); 38 | StringChangeEx(FileContents, LF, CRLF, False); 39 | SaveStringToFile(FilePath, FileContents, False); 40 | end; 41 | -------------------------------------------------------------------------------- /splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssec/sift/5a949ee4fa4a823d262bc39a42551a5b96679788/splash.png -------------------------------------------------------------------------------- /uwsift/control/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssec/sift/5a949ee4fa4a823d262bc39a42551a5b96679788/uwsift/control/__init__.py -------------------------------------------------------------------------------- /uwsift/control/time_matcher.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from typing import Callable, List, Optional 3 | 4 | 5 | class TimeMatcher: 6 | def __init__(self, policy: Callable): 7 | self.policy = policy 8 | 9 | def match(self, timeline: List[datetime], t_sim: datetime, policy: Optional[Callable] = None): 10 | if not isinstance(t_sim, datetime): 11 | raise ValueError("Queried Time not an instance of a datetime object.") 12 | if policy is None: 13 | policy = self.policy 14 | matched = policy(timeline, t_sim) 15 | return matched 16 | -------------------------------------------------------------------------------- /uwsift/control/time_matcher_policies.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from typing import List, Optional 3 | 4 | import numpy as np 5 | 6 | 7 | # Example time Matching policies 8 | def find_nearest(ref: List[datetime], query: datetime) -> Optional[datetime]: 9 | ref_np = np.asarray(ref) 10 | query_np = np.asarray(query) 11 | distances = np.abs(ref_np - query_np) 12 | return ref_np[np.argmin(distances)] 13 | 14 | 15 | def find_nearest_past(ref: List[datetime], query: datetime) -> Optional[datetime]: 16 | query_np = np.asarray(query) 17 | ref_np = np.array([t for t in ref]) 18 | past_idcs = ref_np <= query_np 19 | if np.any(past_idcs): 20 | distances = np.abs(ref_np[past_idcs] - query_np) 21 | return ref_np[np.argmin(distances)] 22 | else: 23 | return None 24 | -------------------------------------------------------------------------------- /uwsift/control/time_transformer.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | import logging 4 | import time 5 | from typing import TYPE_CHECKING 6 | 7 | from uwsift.common import DEFAULT_TIME_FORMAT 8 | 9 | LOG = logging.getLogger(__name__) 10 | 11 | if TYPE_CHECKING: 12 | from uwsift.control.time_transformer_policies import WrappingDrivingPolicy 13 | 14 | 15 | class TimeTransformer: 16 | """ 17 | Tick-to-Timestep Translator in concept. 18 | - get simulated time t_sim from driving layer/timeline 19 | at each tick: - check for curr. driving layer 20 | - get t_sim from driving layer 21 | - sends t_sim to DisplayManager 22 | """ 23 | 24 | def __init__(self, translation_policy: WrappingDrivingPolicy): 25 | self._translation_policy = translation_policy 26 | 27 | self.curr_tick_time: float = -1.0 28 | self.prev_tick_time: float = -1.0 29 | self._tick_delta: float = -1.0 30 | self._tick_accum: float = 0.0 31 | self.t_sim = self._translation_policy.curr_t_sim() 32 | self.timeline_index = self._translation_policy.curr_timeline_index() 33 | 34 | def create_formatted_time_stamp(self, fmt=DEFAULT_TIME_FORMAT): 35 | return self.t_sim.strftime(fmt) 36 | 37 | def change_timebase(self, layer): 38 | self._translation_policy.change_timebase(layer) 39 | self.update_current_timebase() 40 | 41 | def jump(self, index): 42 | self.t_sim = self._translation_policy.jump_to_t_sim(index=index) 43 | self.timeline_index = self._translation_policy.curr_timeline_index() 44 | 45 | def step(self, backwards=False): 46 | # tick times in milliseconds since Epoch 47 | self.curr_tick_time = time.time_ns() // 1000000 48 | self.t_sim = self._translation_policy.compute_t_sim(self.curr_tick_time, backwards=backwards) 49 | self.timeline_index = self._translation_policy.curr_timeline_index() 50 | 51 | def update_current_timebase(self): 52 | """Update timebase parameters to pick up according changes from the time translation policy. 53 | 54 | Implementation details: This method is only public to be callable from TimeManager, no other use intended. 55 | """ 56 | self.t_sim = self._translation_policy.curr_t_sim() 57 | self.timeline_index = self._translation_policy.curr_timeline_index() 58 | -------------------------------------------------------------------------------- /uwsift/data/colormaps/OAX/GOES-R/GOESR-L2/ACTP.cmap: -------------------------------------------------------------------------------- 1 | 2 | 21 | 24 | 26 | 29 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /uwsift/data/colormaps/OAX/GOES-R/GOESR-L2/ADP.cmap: -------------------------------------------------------------------------------- 1 | 2 | 5 | 22 | 26 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /uwsift/data/colormaps/OAX/GOES-R/GOESR-L2/CSM.cmap: -------------------------------------------------------------------------------- 1 | 2 | 21 | 24 | 26 | 29 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /uwsift/data/colormaps/OAX/GOES-R/GOESR-L2/Dust.cmap: -------------------------------------------------------------------------------- 1 | 2 | 21 | 24 | 31 | 34 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /uwsift/data/colormaps/OAX/GOES-R/GOESR-L2/Smoke.cmap: -------------------------------------------------------------------------------- 1 | 2 | 21 | 24 | 31 | 34 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /uwsift/data/fonts/Andale Mono.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssec/sift/5a949ee4fa4a823d262bc39a42551a5b96679788/uwsift/data/fonts/Andale Mono.ttf -------------------------------------------------------------------------------- /uwsift/data/grib_definitions/grib2/localConcepts/kwbc/units.def: -------------------------------------------------------------------------------- 1 | 'K' = { 2 | discipline = 3 ; 3 | parameterCategory = 192 ; 4 | parameterNumber = 0 ; 5 | } 6 | 'K' = { 7 | discipline = 3 ; 8 | parameterCategory = 192 ; 9 | parameterNumber = 1 ; 10 | } 11 | 'K' = { 12 | discipline = 3 ; 13 | parameterCategory = 192 ; 14 | parameterNumber = 2 ; 15 | } 16 | 'K' = { 17 | discipline = 3 ; 18 | parameterCategory = 192 ; 19 | parameterNumber = 3 ; 20 | } 21 | 'Byte' = { 22 | discipline = 3 ; 23 | parameterCategory = 192 ; 24 | parameterNumber = 4 ; 25 | } 26 | 'Byte' = { 27 | discipline = 3 ; 28 | parameterCategory = 192 ; 29 | parameterNumber = 5 ; 30 | } 31 | 'K' = { 32 | discipline = 3 ; 33 | parameterCategory = 192 ; 34 | parameterNumber = 6 ; 35 | } 36 | 'K' = { 37 | discipline = 3 ; 38 | parameterCategory = 192 ; 39 | parameterNumber = 7 ; 40 | } 41 | 'K' = { 42 | discipline = 3 ; 43 | parameterCategory = 192 ; 44 | parameterNumber = 8 ; 45 | } 46 | 'K' = { 47 | discipline = 3 ; 48 | parameterCategory = 192 ; 49 | parameterNumber = 9 ; 50 | } 51 | 'K' = { 52 | discipline = 3 ; 53 | parameterCategory = 192 ; 54 | parameterNumber = 10 ; 55 | } 56 | 'K' = { 57 | discipline = 3 ; 58 | parameterCategory = 192 ; 59 | parameterNumber = 11 ; 60 | } 61 | 'K' = { 62 | discipline = 3 ; 63 | parameterCategory = 192 ; 64 | parameterNumber = 12 ; 65 | } 66 | 'K' = { 67 | discipline = 3 ; 68 | parameterCategory = 192 ; 69 | parameterNumber = 13 ; 70 | } 71 | '' = { 72 | discipline = 3 ; 73 | parameterCategory = 192 ; 74 | parameterNumber = 14 ; 75 | } 76 | '' = { 77 | discipline = 3 ; 78 | parameterCategory = 192 ; 79 | parameterNumber = 15 ; 80 | } 81 | '' = { 82 | discipline = 3 ; 83 | parameterCategory = 192 ; 84 | parameterNumber = 16 ; 85 | } 86 | '' = { 87 | discipline = 3 ; 88 | parameterCategory = 192 ; 89 | parameterNumber = 17 ; 90 | } 91 | '' = { 92 | discipline = 3 ; 93 | parameterCategory = 192 ; 94 | parameterNumber = 18 ; 95 | } 96 | '' = { 97 | discipline = 3 ; 98 | parameterCategory = 192 ; 99 | parameterNumber = 19 ; 100 | } 101 | 'K' = { 102 | discipline = 3 ; 103 | parameterCategory = 192 ; 104 | parameterNumber = 20 ; 105 | } 106 | 'K' = { 107 | discipline = 3 ; 108 | parameterCategory = 192 ; 109 | parameterNumber = 21 ; 110 | } 111 | 'K' = { 112 | discipline = 3 ; 113 | parameterCategory = 192 ; 114 | parameterNumber = 22 ; 115 | } 116 | 'K' = { 117 | discipline = 3 ; 118 | parameterCategory = 192 ; 119 | parameterNumber = 23 ; 120 | } 121 | 'K' = { 122 | discipline = 3 ; 123 | parameterCategory = 192 ; 124 | parameterNumber = 24 ; 125 | } 126 | 'K' = { 127 | discipline = 3 ; 128 | parameterCategory = 192 ; 129 | parameterNumber = 25 ; 130 | } 131 | 'K' = { 132 | discipline = 3 ; 133 | parameterCategory = 192 ; 134 | parameterNumber = 26 ; 135 | } 136 | 'K' = { 137 | discipline = 3 ; 138 | parameterCategory = 192 ; 139 | parameterNumber = 27 ; 140 | } 141 | 'K' = { 142 | discipline = 3 ; 143 | parameterCategory = 192 ; 144 | parameterNumber = 28 ; 145 | } 146 | 'K' = { 147 | discipline = 3 ; 148 | parameterCategory = 192 ; 149 | parameterNumber = 29 ; 150 | } 151 | '' = { 152 | discipline = 3 ; 153 | parameterCategory = 192 ; 154 | parameterNumber = 30 ; 155 | } 156 | '' = { 157 | discipline = 3 ; 158 | parameterCategory = 192 ; 159 | parameterNumber = 31 ; 160 | } 161 | '' = { 162 | discipline = 3 ; 163 | parameterCategory = 192 ; 164 | parameterNumber = 32 ; 165 | } 166 | '' = { 167 | discipline = 3 ; 168 | parameterCategory = 192 ; 169 | parameterNumber = 33 ; 170 | } 171 | '' = { 172 | discipline = 3 ; 173 | parameterCategory = 192 ; 174 | parameterNumber = 34 ; 175 | } 176 | '' = { 177 | discipline = 3 ; 178 | parameterCategory = 192 ; 179 | parameterNumber = 35 ; 180 | } 181 | 'K' = { 182 | discipline = 3 ; 183 | parameterCategory = 192 ; 184 | parameterNumber = 36 ; 185 | } 186 | 'K' = { 187 | discipline = 3 ; 188 | parameterCategory = 192 ; 189 | parameterNumber = 37 ; 190 | } 191 | 'K' = { 192 | discipline = 3 ; 193 | parameterCategory = 192 ; 194 | parameterNumber = 38 ; 195 | } 196 | 'K' = { 197 | discipline = 3 ; 198 | parameterCategory = 192 ; 199 | parameterNumber = 39 ; 200 | } 201 | 'K' = { 202 | discipline = 3 ; 203 | parameterCategory = 192 ; 204 | parameterNumber = 40 ; 205 | } 206 | 'K' = { 207 | discipline = 3 ; 208 | parameterCategory = 192 ; 209 | parameterNumber = 41 ; 210 | } 211 | 'K' = { 212 | discipline = 3 ; 213 | parameterCategory = 192 ; 214 | parameterNumber = 42 ; 215 | } 216 | 'K' = { 217 | discipline = 3 ; 218 | parameterCategory = 192 ; 219 | parameterNumber = 43 ; 220 | } 221 | 'K' = { 222 | discipline = 3 ; 223 | parameterCategory = 192 ; 224 | parameterNumber = 44 ; 225 | } 226 | 'K' = { 227 | discipline = 3 ; 228 | parameterCategory = 192 ; 229 | parameterNumber = 45 ; 230 | } 231 | -------------------------------------------------------------------------------- /uwsift/data/icons/menu.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 40 | 44 | 45 | 47 | 48 | 50 | image/svg+xml 51 | 53 | 54 | 55 | 56 | 57 | 61 | 70 | 77 | 84 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /uwsift/data/ne_110m_admin_0_countries/ne_110m_admin_0_countries.VERSION.txt: -------------------------------------------------------------------------------- 1 | 2.0.0 2 | -------------------------------------------------------------------------------- /uwsift/data/ne_110m_admin_0_countries/ne_110m_admin_0_countries.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssec/sift/5a949ee4fa4a823d262bc39a42551a5b96679788/uwsift/data/ne_110m_admin_0_countries/ne_110m_admin_0_countries.dbf -------------------------------------------------------------------------------- /uwsift/data/ne_110m_admin_0_countries/ne_110m_admin_0_countries.prj: -------------------------------------------------------------------------------- 1 | GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]] 2 | -------------------------------------------------------------------------------- /uwsift/data/ne_110m_admin_0_countries/ne_110m_admin_0_countries.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssec/sift/5a949ee4fa4a823d262bc39a42551a5b96679788/uwsift/data/ne_110m_admin_0_countries/ne_110m_admin_0_countries.shp -------------------------------------------------------------------------------- /uwsift/data/ne_110m_admin_0_countries/ne_110m_admin_0_countries.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssec/sift/5a949ee4fa4a823d262bc39a42551a5b96679788/uwsift/data/ne_110m_admin_0_countries/ne_110m_admin_0_countries.shx -------------------------------------------------------------------------------- /uwsift/data/ne_50m_admin_0_countries/ne_50m_admin_0_countries.VERSION.txt: -------------------------------------------------------------------------------- 1 | 2.0.0 2 | -------------------------------------------------------------------------------- /uwsift/data/ne_50m_admin_0_countries/ne_50m_admin_0_countries.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssec/sift/5a949ee4fa4a823d262bc39a42551a5b96679788/uwsift/data/ne_50m_admin_0_countries/ne_50m_admin_0_countries.dbf -------------------------------------------------------------------------------- /uwsift/data/ne_50m_admin_0_countries/ne_50m_admin_0_countries.prj: -------------------------------------------------------------------------------- 1 | GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]] 2 | -------------------------------------------------------------------------------- /uwsift/data/ne_50m_admin_0_countries/ne_50m_admin_0_countries.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssec/sift/5a949ee4fa4a823d262bc39a42551a5b96679788/uwsift/data/ne_50m_admin_0_countries/ne_50m_admin_0_countries.shp -------------------------------------------------------------------------------- /uwsift/data/ne_50m_admin_0_countries/ne_50m_admin_0_countries.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssec/sift/5a949ee4fa4a823d262bc39a42551a5b96679788/uwsift/data/ne_50m_admin_0_countries/ne_50m_admin_0_countries.shx -------------------------------------------------------------------------------- /uwsift/data/ne_50m_admin_1_states_provinces_lakes/ne_50m_admin_1_states_provinces_lakes.VERSION.txt: -------------------------------------------------------------------------------- 1 | 3.0.0 2 | -------------------------------------------------------------------------------- /uwsift/data/ne_50m_admin_1_states_provinces_lakes/ne_50m_admin_1_states_provinces_lakes.dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssec/sift/5a949ee4fa4a823d262bc39a42551a5b96679788/uwsift/data/ne_50m_admin_1_states_provinces_lakes/ne_50m_admin_1_states_provinces_lakes.dbf -------------------------------------------------------------------------------- /uwsift/data/ne_50m_admin_1_states_provinces_lakes/ne_50m_admin_1_states_provinces_lakes.prj: -------------------------------------------------------------------------------- 1 | GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]] 2 | -------------------------------------------------------------------------------- /uwsift/data/ne_50m_admin_1_states_provinces_lakes/ne_50m_admin_1_states_provinces_lakes.shp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssec/sift/5a949ee4fa4a823d262bc39a42551a5b96679788/uwsift/data/ne_50m_admin_1_states_provinces_lakes/ne_50m_admin_1_states_provinces_lakes.shp -------------------------------------------------------------------------------- /uwsift/data/ne_50m_admin_1_states_provinces_lakes/ne_50m_admin_1_states_provinces_lakes.shx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssec/sift/5a949ee4fa4a823d262bc39a42551a5b96679788/uwsift/data/ne_50m_admin_1_states_provinces_lakes/ne_50m_admin_1_states_provinces_lakes.shx -------------------------------------------------------------------------------- /uwsift/data/shadedrelief.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssec/sift/5a949ee4fa4a823d262bc39a42551a5b96679788/uwsift/data/shadedrelief.jpg -------------------------------------------------------------------------------- /uwsift/etc/SIFT/config/area_definitions.yaml: -------------------------------------------------------------------------------- 1 | area_definitions: 2 | 3 | MTG FCI FDSS: 4 | { 5 | 1km: mtg_fci_fdss_1km, 6 | 2km: mtg_fci_fdss_2km, 7 | 500m: mtg_fci_fdss_500m, 8 | 32km: mtg_fci_fdss_32km 9 | } 10 | 11 | MSG SEVIRI FES: 12 | { 13 | 3km: msg_seviri_fes_3km, 14 | 1km: msg_seviri_fes_1km, 15 | 9km: msg_seviri_fes_9km 16 | } 17 | MSG SEVIRI RSS: 18 | { 19 | 3km: msg_seviri_rss_3km, 20 | 1km: msg_seviri_rss_1km 21 | } 22 | MSG SEVIRI IODC: 23 | { 24 | 3km: msg_seviri_iodc_3km, 25 | 1km: msg_seviri_iodc_1km 26 | } 27 | GOES-East ABI F: 28 | { 29 | 500m: goes_east_abi_f_500m, 30 | 1km: goes_east_abi_f_1km, 31 | 2km: goes_east_abi_f_2km 32 | } 33 | 34 | GOES-West ABI F: 35 | { 36 | 500m: goes_west_abi_f_500m, 37 | 1km: goes_west_abi_f_1km, 38 | 2km: goes_west_abi_f_2km 39 | } 40 | 41 | EUROL: 42 | { 43 | eurol: eurol 44 | } 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | #---- SIFT doesn't implement proj=eqc correctly/completely ---- 54 | # Plate Carree 3km: worldeqc3km 55 | -------------------------------------------------------------------------------- /uwsift/etc/SIFT/config/auto_update.yaml: -------------------------------------------------------------------------------- 1 | # Activate auto update and set interval (in seconds) in which 2 | # the search path specified in catalogue settings is queried. 3 | 4 | auto_update: 5 | active: False 6 | interval: 20 7 | 8 | data_reading: 9 | merge_with_existing: False # shall be activated only with active auto_update 10 | -------------------------------------------------------------------------------- /uwsift/etc/SIFT/config/catalogue.yaml: -------------------------------------------------------------------------------- 1 | # The Catalogue configuration defines a list of "queries", used in auto update 2 | # mode. 3 | # 4 | # Two queries are given here: 5 | # - for MTG FCI FDHSI suitable for auto update 6 | # - for MSG SEVIRI suitable to load a certain fixed dataset 7 | # (NOTE: currently only one query at a time is supported, i.e. only the first is 8 | # active) 9 | # 10 | # Each query must define the *reader* to use, the *search_path* where to look 11 | # for files, optional *constraints*, and a mandatory definition of the desired 12 | # *products*. 13 | # 14 | # From the configration for the given *reader* the *filter_patterns* are taken 15 | # and used to match files in the given *search_path*. The *constraints* are 16 | # applied to reduce the result list (for example to see only files where 17 | # *platform_shortname* is "MSG4"). The given constraint items correspond to the 18 | # replacement fields of the *filter_patterns* (different *filter_patterns* may 19 | # have arbitrarily different constraints). 20 | # 21 | 22 | # Very important constraint options are those for defining restrictions for the 23 | # data time(s). For at most one datetime replacement field from the 24 | # *filter_patterns* a constraint can be given (all but the first are ignored). 25 | # This type of constraint is detected, when an according explicit 'type' is 26 | # defined for them; two of these explicit constraint types are available (for 27 | # now): 28 | # 29 | # * ``type: datetime`` 30 | # a fixed filter based on the different parts of the data time can be defined, 31 | # e.g. data from all 1st days of each month in 2019 at 12:00 32 | # * ``type: recent_datetime`` 33 | # a range of time steps relative to the current time ("now") can be defined, 34 | # e.g. all data for the current hour and the two before 35 | # 36 | # 37 | # Finally with filename based filtering defined it must be configured, which 38 | # actual *products* should be loaded/generated from the actual selection. Each 39 | # channel (or dataset name as defined in the file) must be given with a 40 | # (possibly empty) list of derived product names - if the list is empty, the 41 | # original dataset name is taken as product name. 42 | # 43 | # Note, that the order of items in a query is free, but the order of the top 44 | # level items is recommended as shown here. 45 | 46 | catalogue: 47 | 48 | # An example query configuration for loading MTG FCI FDHSI ir_105 product 49 | # "brightness temperature" for the current and previous hour from the 50 | # configured search path 51 | 52 | - reader: 'fci_l1c_nc' 53 | search_path: '/path/to/fci/data/' 54 | 55 | # Constraints items must match replacement fields as defined in readers/fci_l1c_fdhsi.yaml 56 | constraints: 57 | spacecraft_id: 1 58 | data_source: FCI 59 | processing_level: 1C 60 | subtype: FDHSI 61 | coverage: FD 62 | purpose: '' 63 | start_time: 64 | type: recent_datetime 65 | M: [0, -1, -2, -3, -4, -5] 66 | 67 | products: 68 | ir_105: [brightness_temperature] 69 | 70 | #---------------------------------------------------------------------------- 71 | # Currently only the first query is evaluated thus this one is inactive 72 | 73 | # An example query configuration for loading SEVIRI IR_108 products 74 | # "brightness temperature" and "radiance" for data times 2019-10-21T12:00 75 | # until 2019-10-21T13:00 (exclusive) from the configured search path 76 | 77 | - reader: 'seviri_l1b_hrit' 78 | search_path: '/path/to/seviri/data/' 79 | 80 | # Constraints items must match replacement fields as defined in readers/seviri_l1b_hrit.yaml: 81 | constraints: 82 | platform_shortname: 83 | - MSG4 84 | channel: 85 | - ______ # catch EPI and PRO files, for SEVIRI HRIT this must be given in addition when any channel is listed 86 | - IR_108 87 | start_time: 88 | type: datetime 89 | Y: 2019 90 | m: 10 91 | d: 21 92 | H: 12 93 | 94 | products: 95 | IR_108: [brightness_temperature, radiance] 96 | -------------------------------------------------------------------------------- /uwsift/etc/SIFT/config/default_colormaps.yaml: -------------------------------------------------------------------------------- 1 | default_colormaps: 2 | toa_bidirectional_reflectance: 3 | colormap: Square Root (Vis Default) 4 | # range: [-1.2, 120] 5 | toa_brightness_temperature: 6 | colormap: Rainbow (IR Default) 7 | brightness_temperature: 8 | colormap: Rainbow (IR Default) 9 | height_at_cloud_top: 10 | colormap: Cloud Top Height 11 | air_temperature: 12 | colormap: Rainbow (IR Default) 13 | relative_humidity: 14 | colormap: Rainbow (IR Default) 15 | -------------------------------------------------------------------------------- /uwsift/etc/SIFT/config/default_points_styles.yaml: -------------------------------------------------------------------------------- 1 | point_styles: 2 | # Allowed values: disc, arrow, ring, clobber, square, diamond, vbar, hbar, 3 | # cross, tailed_arrow, x, triangle_up, triangle_down, star 4 | 5 | # note: scaled markers (using % size here) are affected by https://github.com/vispy/vispy/issues/2453 6 | red_x: 7 | symbol: 'x' 8 | size: '9px' 9 | fill: '#FF0000' 10 | stroke: '#000000' 11 | stroke-width: '2px' 12 | 13 | red_empty_square: 14 | symbol: 'square' 15 | size: '20px' 16 | stroke: '#FF0000' 17 | stroke-width: '1px' 18 | 19 | yellow_disc: 20 | symbol: 'disc' 21 | size: '14px' 22 | fill: '#FFFF00' 23 | stroke: '#FFFF00' 24 | stroke-width: '0.5px' 25 | 26 | default_point_styles: 27 | observed_lmk_locations_ir_105: 'red_x' 28 | observed_lmk_locations_ir_123: 'red_x' 29 | observed_lmk_locations_ir_133: 'red_x' 30 | observed_lmk_locations_ir_38: 'red_x' 31 | observed_lmk_locations_ir_87: 'red_x' 32 | observed_lmk_locations_ir_97: 'red_x' 33 | observed_lmk_locations_nir_13: 'red_x' 34 | observed_lmk_locations_nir_16: 'red_x' 35 | observed_lmk_locations_nir_22: 'red_x' 36 | observed_lmk_locations_vis_04: 'red_x' 37 | observed_lmk_locations_vis_05: 'red_x' 38 | observed_lmk_locations_vis_06: 'red_x' 39 | observed_lmk_locations_vis_08: 'red_x' 40 | observed_lmk_locations_vis_09: 'red_x' 41 | observed_lmk_locations_wv_63: 'red_x' 42 | observed_lmk_locations_wv_73: 'red_x' 43 | catalogue_landmark_locations: 'red_empty_square' 44 | peak_current: 'yellow_disc' 45 | -------------------------------------------------------------------------------- /uwsift/etc/SIFT/config/default_reader.yaml: -------------------------------------------------------------------------------- 1 | open_file_wizard: 2 | default_reader: fci_l1c_nc 3 | -------------------------------------------------------------------------------- /uwsift/etc/SIFT/config/default_standard_names.yaml: -------------------------------------------------------------------------------- 1 | # Config file for translating Satpy's standard_name to a shorter name better 2 | # suited for GUI display 3 | 4 | standard_names: 5 | # L1 data 6 | 'toa_outgoing_radiance_per_unit_wavelength': RAD 7 | 'toa_outgoing_radiance_per_unt_wavenumber': RAD 8 | 'toa_bidirectional_reflectance': REFL 9 | 'toa_brightness_temperature': BT 10 | 11 | #L2 data 12 | 'cloud_mask_classification': cloud mask 13 | 'air_pressure_at_cloud_top': CTP 14 | 'reflectance_mean_all': REFL (mean, all) 15 | 'reflectance_mean_cld': REFL (mean, cloudy) 16 | -------------------------------------------------------------------------------- /uwsift/etc/SIFT/config/display.yaml: -------------------------------------------------------------------------------- 1 | # Configuration of display features 2 | display: 3 | # Choose from three options how to represent and display images (i.e. raster 4 | # data, data with an AreaDefinition): 5 | # - simple_geolocated: reprojected image (without dynamic tiling and 6 | # resampling), best for powerful graphics hardware (default) 7 | # - tiled_geolocated: reprojected image with dynamic tiling and resampling 8 | # - pixel_matrix: original image, i.e. neither reprojected nor resampled 9 | image_mode: simple_geolocated 10 | # image_mode: pixel_matrix 11 | # image_mode: tiled_geolocated 12 | 13 | # Settings relevant only for mode 'simple_geolocated' 14 | 15 | # The approximate extent of the subdivision grid cells in meters. This has 16 | # to be interpreted analogously to the pixel_width/pixel_height parameters 17 | # of and AreaDefinition, i.e. it is usually only valid for the sub-satellite 18 | # point 19 | grid_cell_width: 12000 20 | grid_cell_height: 12000 21 | 22 | # Settings relevant only for mode 'tiled_geolocated' 23 | 24 | # tess_level: 20 # not yet configurable 25 | # image_mesh_size: 100 # not yet configurable 26 | 27 | latlon_grid: 28 | resolution: 5.0 29 | -------------------------------------------------------------------------------- /uwsift/etc/SIFT/config/external_satpy.yaml: -------------------------------------------------------------------------------- 1 | # Overwrite the default import path for the Satpy package 2 | # This can be used during development to load a different version of Satpy without the need to package it first. 3 | # satpy_import_path: "/path/to/your/satpy/repo/clone/satpy" 4 | 5 | # Define the path to a folder containing custom Satpy configuration of readers, composites, enhancements and areas to be used in SIFT. 6 | # satpy_extra_config_path: "path/to/your/local_component_configuration" 7 | -------------------------------------------------------------------------------- /uwsift/etc/SIFT/config/limit_available_readers.yaml: -------------------------------------------------------------------------------- 1 | data_reading: 2 | # define readers to activate in open file wizard 3 | readers: 4 | - abi_l1b 5 | - abi_l2_nc 6 | - fci_l1c_nc 7 | - fci_l2_nc 8 | - fci_l2_bufr 9 | - fci_l2_grib 10 | - li_l1b_nc 11 | - li_l2_nc 12 | - seviri_l1b_hrit 13 | - seviri_l1b_native 14 | - seviri_l2_binary 15 | - seviri_l2_bufr 16 | - seviri_l2_grib 17 | - avhrr_l1b_eps 18 | - vii_l1b_nc 19 | - gld360_ualf2 20 | - modis_l1b 21 | - modis_l2 22 | - viirs_l1b 23 | - viirs_l2 24 | -------------------------------------------------------------------------------- /uwsift/etc/SIFT/config/logging.yaml: -------------------------------------------------------------------------------- 1 | # All logging related settings are grouped below the keyword 'logging'. 2 | # All settings are optional. 3 | logging: 4 | 5 | # If 'filename' is given all logging is appended to that file, nothing is 6 | # printed to the console. 7 | # Only an absolute path is accepted. 8 | # filename: /tmp/log_file.txt 9 | 10 | # Listed loggers can get individual settings (currently the log 'level' only). 11 | # A special case is the pseudo-logger 'all'. It can be used to set the default 12 | # for all loggers. 13 | loggers: 14 | all: 15 | level: DEBUG 16 | vispy: 17 | level: INFO 18 | sqlalchemy: 19 | level: ERROR 20 | -------------------------------------------------------------------------------- /uwsift/etc/SIFT/config/open_file_wizard.yaml: -------------------------------------------------------------------------------- 1 | open_file_wizard: 2 | # exclude datasets from dataset list in open file wizard 3 | exclude_datasets: 4 | calibration: 5 | - counts 6 | name: 7 | - latitude # must not be loaded 8 | - longitude # must not be loaded 9 | # define columns in dataset list window 10 | id_components: 11 | - name 12 | - wavelength 13 | - resolution 14 | - calibration 15 | - level 16 | -------------------------------------------------------------------------------- /uwsift/etc/SIFT/config/readers/abi_l1b.yaml: -------------------------------------------------------------------------------- 1 | data_reading: 2 | abi_l1b: 3 | group_keys: ['start_time', 'platform_shortname'] 4 | filter_patterns: ['{env:2s}_{mission:3s}-L1b-{obs_type:3s}{scene:s}-{scan_mode:2s}{channel:3s}_{platform_shortname:3s}_s{start_time:%Y%j%H%M%S%f}_e{end_time:%Y%j%H%M%S%f}_c{creation_time:%Y%j%H%M%S%f}{appendix}.nc{nc_version}'] 5 | -------------------------------------------------------------------------------- /uwsift/etc/SIFT/config/readers/avhrr_l1b_eps.yaml: -------------------------------------------------------------------------------- 1 | data_reading: 2 | avhrr_l1b_eps: 3 | geometry_definition: SwathDefinition 4 | filter_patterns: 5 | [ 6 | 'AVHR_xxx_1B_{platform_short_name}_{start_time:%Y%m%d%H%M%SZ}_{end_time:%Y%m%d%H%M%SZ}_{processing_mode}_{disposition_mode}_{creation_time:%Y%m%d%H%M%SZ}', 7 | 'AVHR_xxx_1B_{platform_short_name}_{start_time:%Y%m%d%H%M%SZ}_{end_time:%Y%m%d%H%M%SZ}_{processing_mode}_{disposition_mode}_{creation_time:%Y%m%d%H%M%SZ}.nat', 8 | ] 9 | -------------------------------------------------------------------------------- /uwsift/etc/SIFT/config/readers/fci_l1c_nc.yaml: -------------------------------------------------------------------------------- 1 | data_reading: 2 | fci_l1c_nc: 3 | group_keys: ['repeat_cycle_in_day'] 4 | filter_patterns: ['{pflag}_{location_indicator},{data_designator},MTI{spacecraft_id:1d}+FCI-1C-RRAD-{subtype}-{coverage}-{subsetting}-{component1}-BODY-{component3}-{purpose}-{format}_{oflag}_{originator}_{processing_time:%Y%m%d%H%M%S}_{facility_or_tool}_{environment}_{start_time:%Y%m%d%H%M%S}_{end_time:%Y%m%d%H%M%S}_{processing_mode}_{special_compression}_{disposition_mode}_{repeat_cycle_in_day:>04d}_{count_in_repeat_cycle:>04d}.nc'] 5 | 6 | grid: 7 | origin: "SW" 8 | first_index_x: 1 9 | first_index_y: 1 10 | -------------------------------------------------------------------------------- /uwsift/etc/SIFT/config/readers/fci_l2_bufr.yaml: -------------------------------------------------------------------------------- 1 | data_reading: 2 | fci_l2_bufr: 3 | filter_patterns: ['{pflag}_{location_indicator},{data_designator},MTI{spacecraft_id:1d}+FCI-2-{type}-{subtype}-{coverage}-{subsetting}-{component1}-{component2}-{component3}-{purpose}-BUFR_{oflag}_{originator}_{processing_time:%Y%m%d%H%M%S}_{facility_or_tool}_{environment}_{start_time:%Y%m%d%H%M%S}_{end_time:%Y%m%d%H%M%S}_{processing_mode}_{special_compression}_{disposition_mode}_{repeat_cycle_in_day:>04d}_{count_in_repeat_cycle:>04d}.bin'] 4 | reader_kwargs: 5 | with_area_definition: True 6 | -------------------------------------------------------------------------------- /uwsift/etc/SIFT/config/readers/fci_l2_grib.yaml: -------------------------------------------------------------------------------- 1 | data_reading: 2 | fci_l2_grib: 3 | filter_patterns: ['{pflag}_{location_indicator},{data_designator},MTI{spacecraft_id:1d}+FCI-2-{type}-{subtype}-{coverage}-{subsetting}-{component1}-{component2}-{component3}-{purpose}-GRIB2_{oflag}_{originator}_{processing_time:%Y%m%d%H%M%S}_{facility_or_tool}_{environment}_{start_time:%Y%m%d%H%M%S}_{end_time:%Y%m%d%H%M%S}_{processing_mode}_{special_compression}_{disposition_mode}_{repeat_cycle_in_day:>04d}_{count_in_repeat_cycle:>04d}.bin'] 4 | -------------------------------------------------------------------------------- /uwsift/etc/SIFT/config/readers/fci_l2_nc.yaml: -------------------------------------------------------------------------------- 1 | data_reading: 2 | fci_l2_nc: 3 | filter_patterns: ['{pflag}_{location_indicator},{data_designator},MTI{spacecraft_id:1d}+FCI-2-{type}-{subtype}-{coverage}-{subsetting}-{component1}-{component2}-{component3}-{purpose}-{format}_{oflag}_{originator}_{processing_time:%Y%m%d%H%M%S}_{facility_or_tool}_{environment}_{start_time:%Y%m%d%H%M%S}_{end_time:%Y%m%d%H%M%S}_{processing_mode}_{special_compression}_{disposition_mode}_{repeat_cycle_in_day:>04d}_{count_in_repeat_cycle:>04d}.nc'] 4 | reader_kwargs: 5 | with_area_definition: True 6 | -------------------------------------------------------------------------------- /uwsift/etc/SIFT/config/readers/gld360_ualf2.yaml: -------------------------------------------------------------------------------- 1 | data_reading: 2 | gld360_ualf2: 3 | group_keys: ['start_time'] 4 | filter_patterns: 5 | - '{start_time:%Y.%m.%d.%H.%M}.txt' 6 | - 'gld360_{start_time:%Y%m%d}_{south}S-{north}N_{west}W-{east}E_ualf2.asc' 7 | - 'GLD_{start_time:%Y%m%d}_{north_south}NS_{east_west}EW.ualf2' 8 | kind: 'POINTS' 9 | style_attributes: 10 | fill: ['peak_current', 'altitude'] 11 | -------------------------------------------------------------------------------- /uwsift/etc/SIFT/config/readers/li_l1b_nc.yaml: -------------------------------------------------------------------------------- 1 | data_reading: 2 | li_l1b_nc: 3 | group_keys: ['start_time'] 4 | filter_patterns: 5 | [ 6 | '{pflag}_{location_indicator},{data_designator},{spacecraft_id}+LI-1B-{type}--{subtype}--{component1}-{component2}-{component3}-{purpose}-{format}_{oflag}_{originator}_{processing_time:%Y%m%d%H%M%S}_{facility_or_tool}_{environment}_{start_time:%Y%m%d%H%M%S}_{end_time:%Y%m%d%H%M%S}_{processing_mode}_{special_compression}_{disposition_mode}_{repeat_cycle_in_day:>04d}_{count_in_repeat_cycle:>04d}.nc' 7 | ] 8 | kind: 'DYNAMIC' 9 | style_attributes: 10 | fill: [ 'radiance' ] 11 | -------------------------------------------------------------------------------- /uwsift/etc/SIFT/config/readers/li_l2_nc.yaml: -------------------------------------------------------------------------------- 1 | data_reading: 2 | li_l2_nc: 3 | group_keys: ['start_time'] 4 | filter_patterns: 5 | [ 6 | '{pflag}_{location_indicator},{data_designator},{spacecraft_id}+LI-2-{type}--{subtype}--{component1}-{component2}-{component3}-{purpose}-{format}_{oflag}_{originator}_{processing_time:%Y%m%d%H%M%S}_{facility_or_tool}_{environment}_{start_time:%Y%m%d%H%M%S}_{end_time:%Y%m%d%H%M%S}_{processing_mode}_{special_compression}_{disposition_mode}_{repeat_cycle_in_day:>04d}_{count_in_repeat_cycle:>04d}.nc' 7 | ] 8 | kind: 'DYNAMIC' 9 | style_attributes: 10 | fill: ['radiance'] 11 | reader_kwargs: 12 | with_area_definition: True 13 | -------------------------------------------------------------------------------- /uwsift/etc/SIFT/config/readers/modis_l1b.yaml: -------------------------------------------------------------------------------- 1 | data_reading: 2 | modis_l1b: 3 | geometry_definition: SwathDefinition 4 | -------------------------------------------------------------------------------- /uwsift/etc/SIFT/config/readers/seviri_l1b_hrit.yaml: -------------------------------------------------------------------------------- 1 | data_reading: 2 | seviri_l1b_hrit: 3 | group_keys: ['start_time', 'platform_shortname', 'service'] 4 | filter_patterns: ['{rate:1s}-000-{hrit_format:_<6s}-{platform_shortname:4s}_{service:_<7s}-{channel:_<6s}___-{segment:_<6s}___-{start_time:%Y%m%d%H%M}-{c:1s}_'] 5 | 6 | grid: 7 | origin: "SE" 8 | first_index_x: 1 9 | first_index_y: 1 10 | -------------------------------------------------------------------------------- /uwsift/etc/SIFT/config/readers/seviri_l1b_native.yaml: -------------------------------------------------------------------------------- 1 | data_reading: 2 | seviri_l1b_native: 3 | group_keys: ['end_time', 'satid', 'instr'] 4 | filter_patterns: [ 5 | '{satid:4s}-{instr:4s}-MSG{product_level:2d}-{processing_version}-NA-{end_time:%Y%m%d%H%M%S.%f}000Z{appendix}', 6 | '{satid:4s}-{instr:4s}-MSG{product_level:2d}-{processing_version}-NA-{end_time:%Y%m%d%H%M%S.%f}000Z-{order_id:s}.nat', 7 | '{satid:4s}-{instr:4s}-MSG{product_level:2d}-{processing_version}-NA-{end_time:%Y%m%d%H%M%S.%f}000Z-{processing_time:%Y%m%d%H%M%S}-{order_id:s}.nat', 8 | ] 9 | 10 | grid: 11 | origin: "SE" 12 | first_index_x: 1 13 | first_index_y: 1 14 | 15 | reader_kwargs: 16 | fill_disk: True # needed to load correctly the HRV channel 17 | -------------------------------------------------------------------------------- /uwsift/etc/SIFT/config/readers/seviri_l2_binary.yaml: -------------------------------------------------------------------------------- 1 | data_reading: 2 | seviri_l2_binary: 3 | filter_patterns: ['{product:s}_{start_time:%Y%m%d%H%M%S}Z_00_{server:s}_{satellite:s}_{mission:s}_{subsat:s}'] 4 | reader_kwargs: 5 | with_area_definition: True 6 | -------------------------------------------------------------------------------- /uwsift/etc/SIFT/config/readers/seviri_l2_bufr.yaml: -------------------------------------------------------------------------------- 1 | data_reading: 2 | seviri_l2_bufr: 3 | filter_patterns: 4 | - '{filename}' # generic pattern as default 5 | - '{product:s}_{start_time:%Y%m%d%H%M%S}Z_00_{server:s}_{satellite:s}_{mission:s}_{subsat:s}' 6 | - '{spacecraft:s}-SEVI-MSG{product:s}-{loc1:s}-{loc2:s}-{start_time:%Y%m%d%H%M%S}.000000000Z{appendix}' 7 | - '{spacecraft:s}-SEVI-MSG{product:s}-{loc1:s}-{loc2:s}-{start_time:%Y%m%d%H%M%S}.000000000Z-{time1:%Y%m%d%H%M%S}-{ord1:s}.bfr' 8 | - '{spacecraft:s}-SEVI-MSG{product:s}-{loc1:s}-{loc2:s}-{start_time:%Y%m%d%H%M%S}.000000000Z-{time1:%Y%m%d%H%M%S}-{ord1:s}' 9 | reader_kwargs: 10 | with_area_definition: True 11 | 12 | grid: 13 | origin: "SE" 14 | first_index_x: 1 15 | first_index_y: 1 16 | -------------------------------------------------------------------------------- /uwsift/etc/SIFT/config/readers/seviri_l2_grib.yaml: -------------------------------------------------------------------------------- 1 | data_reading: 2 | seviri_l2_grib: 3 | filter_patterns: 4 | - '{filename}' # generic pattern as default 5 | - '{product:s}_{start_time:%Y%m%d%H%M%S}Z_00_{server:8s}_{spacecraft:5s}_{scan_mode:3s}_{sub_sat:5s}' 6 | - '{spacecraft:4s}-SEVI-MSG{product:s}-{id1:4s}-{id2:4s}-{start_time:%Y%m%d%H%M%S}.000000000Z{appendix}' 7 | - '{spacecraft:4s}-SEVI-MSG{product:s}-{id1:4s}-{id2:4s}-{start_time:%Y%m%d%H%M%S}.000000000Z-{product_creation_time:%Y%m%d%H%M%S}-{ord_num:7s}' 8 | - '{spacecraft:4s}-SEVI-MSG{product:s}-{id1:4s}-{id2:4s}-{start_time:%Y%m%d%H%M%S}.000000000Z-{product_creation_time:%Y%m%d%H%M%S}-{ord_num:7s}.grb' 9 | 10 | grid: 11 | origin: "SE" 12 | first_index_x: 1 13 | first_index_y: 1 14 | -------------------------------------------------------------------------------- /uwsift/etc/SIFT/config/readers/vii_l1b_nc.yaml: -------------------------------------------------------------------------------- 1 | data_reading: 2 | vii_l1b_nc: 3 | geometry_definition: SwathDefinition 4 | filter_patterns: 5 | ['W_XX-EUMETSAT-Darmstadt,SAT,{spacecraft_name:s}-VII-1B-RAD_C_EUMT_{creation_time:%Y%m%d%H%M%S}_{mission_type:s}_{environment:s}_{sensing_start_time:%Y%m%d%H%M%S}_{sensing_end_time:%Y%m%d%H%M%S}_{disposition_mode:s}_{processing_mode:s}____.nc'] 6 | -------------------------------------------------------------------------------- /uwsift/etc/SIFT/config/storage.yaml: -------------------------------------------------------------------------------- 1 | # Control the operations mode regarding inventory database and housekeeping of 2 | # intermediate data files 3 | storage: 4 | use_inventory_db : False 5 | cleanup_file_cache: True 6 | 7 | agent: 8 | notification_cmd: /path/to/raiseEvent.sh # Optional 9 | # interval: 60 # Optional, sensible default can be calculated from files_lifetime 10 | files_lifetime: 1200 11 | directories: 12 | - "$$CACHE_DIR$$/workspace/data_cache" 13 | - "$$CACHE_DIR$$/workspace/temp" 14 | -------------------------------------------------------------------------------- /uwsift/etc/SIFT/config/units.yaml: -------------------------------------------------------------------------------- 1 | # Map physical quantities to units. 2 | # Note that unit names must conform to the following spellings: 3 | # 'kelvin', 'degrees_Celsius' 4 | units: 5 | temperature: 6 | all: kelvin 7 | toa_brightness_temperature: kelvin 8 | brightness_temperature: kelvin 9 | -------------------------------------------------------------------------------- /uwsift/etc/SIFT/config/watchdog.yaml: -------------------------------------------------------------------------------- 1 | watchdog: 2 | heartbeat_file: "$$CACHE_DIR$$/heartbeat.txt" 3 | notification_cmd: /path/to/raiseEvent.sh 4 | # Unit of the following settings: seconds 5 | heartbeat_check_interval: 60 6 | max_tolerable_dataset_age: 600 7 | max_tolerable_idle_time: 600 8 | 9 | # Restart the application after the interval expires 10 | # Set this option to 0 in order to disable the Auto Restart 11 | # Note: Auto Restart requires the heartbeat_file option 12 | auto_restart_interval: 86400 13 | # Ask again if the restart request was cancelled by the user 14 | # Set this option to 0 in order to only ask the user once 15 | auto_restart_ask_again_interval: 600 16 | # The user has to cancel the restart request within this time 17 | # to cancel the restart 18 | # Set this option to 0 in order to disable the deadline 19 | auto_restart_popup_deadline: 30 20 | 21 | # If the memory consumption of SIFT exceeds this value, 22 | # then the watchdog will issue a restart request. 23 | # Possible units: M -> Mebibyte, G -> Gibibyte (with base 1024 to be 24 | # consistent with systemd). 25 | # Leave this option empty in order to disable it 26 | max_memory_consumption: 5G 27 | -------------------------------------------------------------------------------- /uwsift/model/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | __init__.py 5 | ~~~ 6 | 7 | PURPOSE 8 | Model contains all the irreplaceable user input and state. 9 | It represents the metadata and planning of what's to be shown on the screen and 10 | what the user can do with it. 11 | Model uses a Workspace to help it work with large quantities of data. 12 | 13 | 14 | REFERENCES 15 | 16 | 17 | REQUIRES 18 | 19 | 20 | :author: R.K.Garcia 21 | :copyright: 2014 by University of Wisconsin Regents, see AUTHORS for more details 22 | :license: GPLv3, see LICENSE for more details 23 | """ 24 | 25 | from uwsift.model.document import Document # noqa 26 | -------------------------------------------------------------------------------- /uwsift/model/shapes.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | shapes.py 5 | ~~~~~~~~~ 6 | 7 | PURPOSE 8 | Shape datasets which can be represented in the workspace as data content masks 9 | 10 | REFERENCES 11 | 12 | 13 | REQUIRES 14 | 15 | 16 | :author: R.K.Garcia 17 | :copyright: 2014 by University of Wisconsin Regents, see AUTHORS for more details 18 | :license: GPLv3, see LICENSE for more details 19 | """ 20 | __author__ = "rayg" 21 | __docformat__ = "reStructuredText" 22 | 23 | import logging 24 | 25 | import numpy as np 26 | import shapely.geometry.polygon as sgp 27 | from rasterio import Affine 28 | from rasterio.features import rasterize 29 | 30 | LOG = logging.getLogger(__name__) 31 | 32 | 33 | def content_within_shape(content: np.ndarray, trans: Affine, shape: sgp.LinearRing): 34 | """ 35 | 36 | :param content: data being displayed on the screen 37 | :param trans: affine transform between content array indices and screen coordinates 38 | :param shape: LinearRing in screen coordinates (e.g. mercator meters) 39 | :return: masked_content:masked_array, (y_index_offset:int, x_index_offset:int) 40 | containing minified masked content array 41 | 42 | """ 43 | # Get the bounds so we can limit how big our rasterize boolean array actually is 44 | inv_trans = ~trans 45 | # convert bounding box to content coordinates 46 | # (0, 0) image index is upper-left origin of data (needs more work if otherwise) 47 | nx, ny, mx, my = shape.bounds # minx,miny,maxx,maxy 48 | nx, my = inv_trans * (nx, my) 49 | mx, ny = inv_trans * (mx, ny) 50 | nx, my = int(nx), int(my) 51 | mx, ny = int(np.ceil(mx)), int(np.ceil(ny)) 52 | 53 | # subset the content (ny is the higher *index*, my is the lower *index*) 54 | w = (mx - nx) + 1 55 | h = (ny - my) + 1 56 | 57 | # Make our linear ring a properly oriented shapely polygon 58 | shape = sgp.Polygon(shape) 59 | shape = sgp.orient(shape) 60 | # create a transform that is shifted to where the polygon is 61 | offset_trans = trans * Affine.translation(nx, my) 62 | 63 | # Get boolean mask for where the polygon is and get an index mask of those positions 64 | index_mask = np.nonzero( 65 | rasterize([shape], out_shape=(h, w), transform=offset_trans, default_value=1).astype(np.bool_) 66 | ) 67 | # translate the mask indexes back to the original data array coordinates (original index mask is read-only) 68 | index_mask = (index_mask[0] + my, index_mask[1] + nx) 69 | return index_mask, content[index_mask] 70 | -------------------------------------------------------------------------------- /uwsift/project/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ssec/sift/5a949ee4fa4a823d262bc39a42551a5b96679788/uwsift/project/__init__.py -------------------------------------------------------------------------------- /uwsift/project/organize_data_bands.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | organize_data_bands.py 5 | ~~~~~~~~~~~~~~~~~~~~~~ 6 | 7 | PURPOSE 8 | Mirror the default AHI data directory structure with band being the primary key using hardlinks. 9 | 10 | Note: Hardlinks are required for this and not softlinks because cwrsync for Windows does not properly support softlinks 11 | from basic testing. 12 | 13 | Data for SIFT is organized as `/odyssey/isis/tmp/davidh/sift_data/ahi/YYYY_MM_DD_JJJ/HHMM/*B[01-16]*.tif`. This 14 | doesn't make it easy to select a band for multiple time steps so this script will create hardlinks so the structure is: 15 | `/odyssey/isis/tmp/davidh/sift_data/ahi/B[01-16]/*B[01-16]*.tif` 16 | 17 | REFERENCES 18 | 19 | 20 | REQUIRES 21 | 22 | 23 | :author: David Hoese 24 | :copyright: 2014 by University of Wisconsin Regents, see AUTHORS for more details 25 | :license: GPLv3, see LICENSE for more details 26 | """ 27 | __docformat__ = "reStructuredText" 28 | __author__ = "davidh" 29 | 30 | import logging 31 | import os 32 | import re 33 | import sys 34 | from glob import glob 35 | 36 | LOG = logging.getLogger(__name__) 37 | 38 | FILENAME_RE = r"HS_H08_(?P\d{8})_(?P