├── .bandit ├── .codebeatignore ├── .git_archival.txt ├── .gitattributes ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE.md ├── dependabot.yml └── workflows │ ├── ci.yaml │ └── deploy-sdist.yaml ├── .gitignore ├── .pre-commit-config.yaml ├── .readthedocs.yml ├── AUTHORS.md ├── CHANGELOG.md ├── CITATION ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.rst ├── LICENSE.txt ├── README.rst ├── RELEASING.md ├── SECURITY.md ├── asv.conf.json ├── benchmarks ├── __init__.py ├── abi_l1b_benchmarks.py ├── ahi_hsd_benchmarks.py ├── fci_benchmarks.py ├── seviri_hrit_benchmarks.py ├── utils.py └── viirs_sdr_benchmarks.py ├── changelog_pre0.9.0.rst ├── continuous_integration └── environment.yaml ├── doc ├── Makefile ├── README ├── rtd_environment.yml └── source │ ├── _static │ ├── main.js │ └── theme_overrides.css │ ├── api │ └── .gitkeep │ ├── composites.rst │ ├── conf.py │ ├── config.rst │ ├── data_download.rst │ ├── dev_guide │ ├── CONTRIBUTING.rst │ ├── aux_data.rst │ ├── custom_reader.rst │ ├── index.rst │ ├── plugins.rst │ ├── remote_file_support.rst │ ├── satpy_internals.rst │ ├── testing.rst │ ├── writing_tests.rst │ └── xarray_migration.rst │ ├── docutils.conf │ ├── doi_role.py │ ├── enhancements.rst │ ├── examples │ ├── fci_l1c_natural_color.rst │ ├── index.rst │ └── vii_l1b_nc.rst │ ├── faq.rst │ ├── generate_area_def_list.py │ ├── index.rst │ ├── install.rst │ ├── modifiers.rst │ ├── multiscene.rst │ ├── overview.rst │ ├── quickstart.rst │ ├── reader_table.py │ ├── readers_formats.rst │ ├── reading.rst │ ├── remote_reading.rst │ ├── resample.rst │ └── writing.rst ├── pyproject.toml ├── satpy ├── __init__.py ├── _compat.py ├── _config.py ├── _scene_converters.py ├── area.py ├── aux_download.py ├── cf │ ├── __init__.py │ ├── area.py │ ├── attrs.py │ ├── coords.py │ ├── data_array.py │ ├── datasets.py │ ├── decoding.py │ └── encoding.py ├── composites │ ├── __init__.py │ ├── abi.py │ ├── agri.py │ ├── ahi.py │ ├── cloud_products.py │ ├── config_loader.py │ ├── glm.py │ ├── lightning.py │ ├── sar.py │ ├── spectral.py │ └── viirs.py ├── conftest.py ├── coords.py ├── dataset │ ├── __init__.py │ ├── anc_vars.py │ ├── data_dict.py │ ├── dataid.py │ └── metadata.py ├── decision_tree.py ├── demo │ ├── __init__.py │ ├── _google_cloud_platform.py │ ├── abi_l1b.py │ ├── ahi_hsd.py │ ├── fci.py │ ├── seviri_hrit.py │ ├── utils.py │ └── viirs_sdr.py ├── dependency_tree.py ├── enhancements │ ├── __init__.py │ ├── abi.py │ ├── enhancer.py │ ├── mimic.py │ └── viirs.py ├── etc │ ├── areas.yaml │ ├── composites │ │ ├── abi.yaml │ │ ├── agri.yaml │ │ ├── ahi.yaml │ │ ├── ami.yaml │ │ ├── amsr2.yaml │ │ ├── atms.yaml │ │ ├── avhrr-3.yaml │ │ ├── ec_msi.yaml │ │ ├── epic.yaml │ │ ├── fci.yaml │ │ ├── ghi.yaml │ │ ├── glm.yaml │ │ ├── goes_imager.yaml │ │ ├── hsaf.yaml │ │ ├── insat3d_img.yaml │ │ ├── li.yaml │ │ ├── mersi-1.yaml │ │ ├── mersi-2.yaml │ │ ├── mersi-3.yaml │ │ ├── mersi-ll.yaml │ │ ├── mersi-rm.yaml │ │ ├── mhs.yaml │ │ ├── microwave.yaml │ │ ├── modis.yaml │ │ ├── msu-gs.yaml │ │ ├── msu_gsa.yaml │ │ ├── mwr.yaml │ │ ├── oci.yaml │ │ ├── olci.yaml │ │ ├── oli_tirs.yaml │ │ ├── sar-c.yaml │ │ ├── sar.yaml │ │ ├── scatterometer.yaml │ │ ├── sen2_msi.yaml │ │ ├── seviri.yaml │ │ ├── sgli.yaml │ │ ├── slstr.yaml │ │ ├── tropomi.yaml │ │ ├── vii.yaml │ │ ├── viirs.yaml │ │ ├── virr.yaml │ │ └── visir.yaml │ ├── enhancements │ │ ├── abi.yaml │ │ ├── ahi.yaml │ │ ├── amsr2.yaml │ │ ├── atms.yaml │ │ ├── epic.yaml │ │ ├── fci.yaml │ │ ├── generic.yaml │ │ ├── glm.yaml │ │ ├── li.yaml │ │ ├── mersi-2.yaml │ │ ├── mhs.yaml │ │ ├── mimic.yaml │ │ ├── msi.yaml │ │ ├── mwr.yaml │ │ ├── olci.yaml │ │ ├── scatterometer.yaml │ │ ├── seviri.yaml │ │ ├── tropomi.yaml │ │ └── viirs.yaml │ ├── eps_avhrrl1b_6.5.xml │ ├── ninjo-cmd.yaml │ ├── readers │ │ ├── abi_l1b.yaml │ │ ├── abi_l1b_scmi.yaml │ │ ├── abi_l2_nc.yaml │ │ ├── acspo.yaml │ │ ├── agri_fy4a_l1.yaml │ │ ├── agri_fy4b_l1.yaml │ │ ├── ahi_hrit.yaml │ │ ├── ahi_hsd.yaml │ │ ├── ahi_l1b_gridded_bin.yaml │ │ ├── ahi_l2_nc.yaml │ │ ├── ami_l1b.yaml │ │ ├── amsr2_l1b.yaml │ │ ├── amsr2_l2.yaml │ │ ├── amsr2_l2_gaasp.yaml │ │ ├── amsub_l1c_aapp.yaml │ │ ├── ascat_l2_soilmoisture_bufr.yaml │ │ ├── atms_l1b_nc.yaml │ │ ├── atms_sdr_hdf5.yaml │ │ ├── avhrr_l1b_aapp.yaml │ │ ├── avhrr_l1b_eps.yaml │ │ ├── avhrr_l1b_gaclac.yaml │ │ ├── avhrr_l1b_hrpt.yaml │ │ ├── avhrr_l1c_eum_gac_fdr_nc.yaml │ │ ├── aws1_mwr_l1b_nc.yaml │ │ ├── aws1_mwr_l1c_nc.yaml │ │ ├── caliop_l2_cloud.yaml │ │ ├── camel_l3_nc.yaml │ │ ├── clavrx.yaml │ │ ├── cmsaf-claas2_l2_nc.yaml │ │ ├── electrol_hrit.yaml │ │ ├── epic_l1b_h5.yaml │ │ ├── eps_sterna_mwr_l1b_nc.yaml │ │ ├── fci_l1c_nc.yaml │ │ ├── fci_l2_bufr.yaml │ │ ├── fci_l2_grib.yaml │ │ ├── fci_l2_nc.yaml │ │ ├── fy3a_mersi1_l1b.yaml │ │ ├── fy3b_mersi1_l1b.yaml │ │ ├── fy3c_mersi1_l1b.yaml │ │ ├── generic_image.yaml │ │ ├── geocat.yaml │ │ ├── gerb_l2_hr_h5.yaml │ │ ├── ghi_l1.yaml │ │ ├── ghrsst_l2.yaml │ │ ├── gld360_ualf2.yaml │ │ ├── glm_l2.yaml │ │ ├── gms5-vissr_l1b.yaml │ │ ├── goci2_l2_nc.yaml │ │ ├── goes-imager_hrit.yaml │ │ ├── goes-imager_nc.yaml │ │ ├── gpm_imerg.yaml │ │ ├── grib.yaml │ │ ├── hsaf_grib.yaml │ │ ├── hsaf_h5.yaml │ │ ├── hy2_scat_l2b_h5.yaml │ │ ├── iasi_l2.yaml │ │ ├── iasi_l2_cdr_nc.yaml │ │ ├── iasi_l2_so2_bufr.yaml │ │ ├── iasi_ng_l2_nc.yaml │ │ ├── ici_l1b_nc.yaml │ │ ├── insat3d_img_l1b_h5.yaml │ │ ├── jami_hrit.yaml │ │ ├── li_l2_nc.yaml │ │ ├── maia.yaml │ │ ├── mcd12q1.yaml │ │ ├── meris_nc_sen3.yaml │ │ ├── mersi2_l1b.yaml │ │ ├── mersi3_l1b.yaml │ │ ├── mersi_ll_l1b.yaml │ │ ├── mersi_rm_l1b.yaml │ │ ├── mhs_l1c_aapp.yaml │ │ ├── mimicTPW2_comp.yaml │ │ ├── mirs.yaml │ │ ├── modis_l1b.yaml │ │ ├── modis_l2.yaml │ │ ├── modis_l3.yaml │ │ ├── msi_l1c_earthcare.yaml │ │ ├── msi_safe.yaml │ │ ├── msi_safe_l2a.yaml │ │ ├── msu_gsa_l1b.yaml │ │ ├── mtsat2-imager_hrit.yaml │ │ ├── multiple_sensors_isccpng_l1g_nc.yaml │ │ ├── mviri_l1b_fiduceo_nc.yaml │ │ ├── mwi_l1b_nc.yaml │ │ ├── mws_l1b_nc.yaml │ │ ├── nucaps.yaml │ │ ├── nwcsaf-geo.yaml │ │ ├── nwcsaf-msg2013-hdf5.yaml │ │ ├── nwcsaf-pps_nc.yaml │ │ ├── oceancolorcci_l3_nc.yaml │ │ ├── oci_l2_bgc.yaml │ │ ├── olci_l1b.yaml │ │ ├── olci_l2.yaml │ │ ├── oli_tirs_l1_tif.yaml │ │ ├── omps_edr.yaml │ │ ├── osisaf_nc.yaml │ │ ├── pace_oci_l1b_nc.yaml │ │ ├── safe_sar_l2_ocn.yaml │ │ ├── sar-c_safe.yaml │ │ ├── satpy_cf_nc.yaml │ │ ├── scatsat1_l2b.yaml │ │ ├── seadas_l2.yaml │ │ ├── seviri_l1b_hrit.yaml │ │ ├── seviri_l1b_icare.yaml │ │ ├── seviri_l1b_native.yaml │ │ ├── seviri_l1b_nc.yaml │ │ ├── seviri_l2_bufr.yaml │ │ ├── seviri_l2_grib.yaml │ │ ├── sgli_l1b.yaml │ │ ├── slstr_l1b.yaml │ │ ├── smos_l2_wind.yaml │ │ ├── tropomi_l2.yaml │ │ ├── vii_l1b_nc.yaml │ │ ├── vii_l2_nc.yaml │ │ ├── viirs_compact.yaml │ │ ├── viirs_edr.yaml │ │ ├── viirs_edr_active_fires.yaml │ │ ├── viirs_edr_flood.yaml │ │ ├── viirs_l1b.yaml │ │ ├── viirs_l2.yaml │ │ ├── viirs_sdr.yaml │ │ ├── viirs_vgac_l1c_nc.yaml │ │ └── virr_l1b.yaml │ └── writers │ │ ├── awips_tiled.yaml │ │ ├── cf.yaml │ │ ├── geotiff.yaml │ │ ├── mitiff.yaml │ │ ├── ninjogeotiff.yaml │ │ ├── ninjotiff.yaml │ │ └── simple_image.yaml ├── modifiers │ ├── __init__.py │ ├── _crefl.py │ ├── _crefl_utils.py │ ├── angles.py │ ├── atmosphere.py │ ├── base.py │ ├── filters.py │ ├── geometry.py │ ├── parallax.py │ └── spectral.py ├── multiscene │ ├── __init__.py │ ├── _blend_funcs.py │ └── _multiscene.py ├── node.py ├── plugin_base.py ├── py.typed ├── readers │ ├── __init__.py │ ├── aapp_l1b.py │ ├── aapp_mhs_amsub_l1c.py │ ├── abi_base.py │ ├── abi_l1b.py │ ├── abi_l2_nc.py │ ├── acspo.py │ ├── agri_l1.py │ ├── ahi_hsd.py │ ├── ahi_l1b_gridded_bin.py │ ├── ahi_l2_nc.py │ ├── ami_l1b.py │ ├── amsr2_l1b.py │ ├── amsr2_l2.py │ ├── amsr2_l2_gaasp.py │ ├── ascat_l2_soilmoisture_bufr.py │ ├── atms_l1b_nc.py │ ├── atms_sdr_hdf5.py │ ├── avhrr_l1b_gaclac.py │ ├── caliop_l2_cloud.py │ ├── camel_l3_nc.py │ ├── clavrx.py │ ├── cmsaf_claas2.py │ ├── core │ │ ├── __init__.py │ │ ├── _geos_area.py │ │ ├── abi.py │ │ ├── config.py │ │ ├── eum.py │ │ ├── fci.py │ │ ├── file_handlers.py │ │ ├── fy4.py │ │ ├── grouping.py │ │ ├── hdf4.py │ │ ├── hdf5.py │ │ ├── hdfeos.py │ │ ├── hrit.py │ │ ├── li_nc.py │ │ ├── loading.py │ │ ├── netcdf.py │ │ ├── remote.py │ │ ├── seviri.py │ │ ├── utils.py │ │ ├── vii.py │ │ ├── vii_nc.py │ │ ├── viirs_atms_sdr.py │ │ ├── xmlformat.py │ │ └── yaml_reader.py │ ├── electrol_hrit.py │ ├── epic_l1b_h5.py │ ├── eps_l1b.py │ ├── eum_base.py │ ├── eum_l2_bufr.py │ ├── eum_l2_grib.py │ ├── fci_base.py │ ├── fci_l1c_nc.py │ ├── fci_l2_nc.py │ ├── file_handlers.py │ ├── fy4_base.py │ ├── generic_image.py │ ├── geocat.py │ ├── gerb_l2_hr_h5.py │ ├── ghi_l1.py │ ├── ghrsst_l2.py │ ├── ghrsst_l3c_sst.py │ ├── gld360_ualf2.py │ ├── glm_l2.py │ ├── gms │ │ ├── __init__.py │ │ ├── gms5_vissr_format.py │ │ ├── gms5_vissr_l1b.py │ │ └── gms5_vissr_navigation.py │ ├── goci2_l2_nc.py │ ├── goes_imager_hrit.py │ ├── goes_imager_nc.py │ ├── gpm_imerg.py │ ├── grib.py │ ├── hdf4_utils.py │ ├── hdf5_utils.py │ ├── hdfeos_base.py │ ├── hrit_base.py │ ├── hrit_jma.py │ ├── hrpt.py │ ├── hsaf_grib.py │ ├── hsaf_h5.py │ ├── hy2_scat_l2b_h5.py │ ├── iasi_l2.py │ ├── iasi_l2_so2_bufr.py │ ├── iasi_ng_l2_nc.py │ ├── ici_l1b_nc.py │ ├── insat3d_img_l1b_h5.py │ ├── li_base_nc.py │ ├── li_l2_nc.py │ ├── maia.py │ ├── mcd12q1.py │ ├── meris_nc_sen3.py │ ├── mersi_l1b.py │ ├── mimic_TPW2_nc.py │ ├── mirs.py │ ├── modis_l1b.py │ ├── modis_l2.py │ ├── modis_l3.py │ ├── msi_ec_l1c_h5.py │ ├── msi_safe.py │ ├── msu_gsa_l1b.py │ ├── multiple_sensors_isccpng_l1g_nc.py │ ├── mviri_l1b_fiduceo_nc.py │ ├── mwr_l1b.py │ ├── mwr_l1c.py │ ├── mws_l1b.py │ ├── netcdf_utils.py │ ├── nucaps.py │ ├── nwcsaf_hrw_nc.py │ ├── nwcsaf_msg2013_hdf5.py │ ├── nwcsaf_nc.py │ ├── oceancolorcci_l3_nc.py │ ├── olci_nc.py │ ├── oli_tirs_l1_tif.py │ ├── omps_edr.py │ ├── osisaf_l3_nc.py │ ├── pace_oci_l1b_nc.py │ ├── pmw_channels_definitions.py │ ├── safe_sar_l2_ocn.py │ ├── sar_c_safe.py │ ├── satpy_cf_nc.py │ ├── scatsat1_l2b.py │ ├── scmi.py │ ├── seadas_l2.py │ ├── seviri_base.py │ ├── seviri_l1b_hrit.py │ ├── seviri_l1b_icare.py │ ├── seviri_l1b_native.py │ ├── seviri_l1b_native_hdr.py │ ├── seviri_l1b_nc.py │ ├── sgli_l1b.py │ ├── slstr_l1b.py │ ├── smos_l2_wind.py │ ├── tropomi_l2.py │ ├── utils.py │ ├── vaisala_gld360.py │ ├── vii_base_nc.py │ ├── vii_l1b_nc.py │ ├── vii_l2_nc.py │ ├── vii_utils.py │ ├── viirs_atms_sdr_base.py │ ├── viirs_compact.py │ ├── viirs_edr.py │ ├── viirs_edr_active_fires.py │ ├── viirs_edr_flood.py │ ├── viirs_l1b.py │ ├── viirs_l2.py │ ├── viirs_sdr.py │ ├── viirs_vgac_l1c_nc.py │ ├── virr_l1b.py │ ├── xmlformat.py │ └── yaml_reader.py ├── resample │ ├── __init__.py │ ├── base.py │ ├── bucket.py │ ├── ewa.py │ ├── kdtree.py │ └── native.py ├── scene.py ├── testing.py ├── tests │ ├── __init__.py │ ├── behave │ │ └── features │ │ │ ├── image_comparison.feature │ │ │ └── steps │ │ │ └── image_comparison.py │ ├── cf_tests │ │ ├── __init__.py │ │ ├── _test_data.py │ │ ├── test_area.py │ │ ├── test_attrs.py │ │ ├── test_coords.py │ │ ├── test_dataaarray.py │ │ ├── test_datasets.py │ │ ├── test_decoding.py │ │ └── test_encoding.py │ ├── compositor_tests │ │ ├── __init__.py │ │ ├── test_abi.py │ │ ├── test_agri.py │ │ ├── test_ahi.py │ │ ├── test_glm.py │ │ ├── test_lightning.py │ │ ├── test_sar.py │ │ ├── test_spectral.py │ │ └── test_viirs.py │ ├── conftest.py │ ├── enhancement_tests │ │ ├── __init__.py │ │ ├── test_abi.py │ │ ├── test_enhancements.py │ │ ├── test_enhancer.py │ │ └── test_viirs.py │ ├── etc │ │ ├── composites │ │ │ └── fake_sensor.yaml │ │ └── readers │ │ │ ├── fake1.yaml │ │ │ ├── fake1_1ds.yaml │ │ │ ├── fake2_1ds.yaml │ │ │ ├── fake2_3ds.yaml │ │ │ ├── fake3.yaml │ │ │ └── fake4.yaml │ ├── features │ │ ├── feature-load.feature │ │ ├── feature-real-load-process-write.feature │ │ ├── feature-save.feature │ │ └── steps │ │ │ ├── steps-load.py │ │ │ ├── steps-real-load-process-write.py │ │ │ └── steps-save.py │ ├── modifier_tests │ │ ├── __init__.py │ │ ├── test_angles.py │ │ ├── test_crefl.py │ │ ├── test_filters.py │ │ └── test_parallax.py │ ├── multiscene_tests │ │ ├── __init__.py │ │ ├── test_blend.py │ │ ├── test_misc.py │ │ ├── test_save_animation.py │ │ └── test_utils.py │ ├── reader_tests │ │ ├── __init__.py │ │ ├── _li_test_utils.py │ │ ├── conftest.py │ │ ├── gms │ │ │ ├── __init__.py │ │ │ ├── test_gms5_vissr_data.py │ │ │ ├── test_gms5_vissr_l1b.py │ │ │ └── test_gms5_vissr_navigation.py │ │ ├── modis_tests │ │ │ ├── __init__.py │ │ │ ├── _modis_fixtures.py │ │ │ ├── conftest.py │ │ │ ├── test_modis_l1b.py │ │ │ ├── test_modis_l2.py │ │ │ ├── test_modis_l3.py │ │ │ └── test_modis_l3_mcd12q1.py │ │ ├── test_aapp_l1b.py │ │ ├── test_aapp_mhs_amsub_l1c.py │ │ ├── test_abi_l1b.py │ │ ├── test_abi_l2_nc.py │ │ ├── test_acspo.py │ │ ├── test_agri_l1.py │ │ ├── test_ahi_hrit.py │ │ ├── test_ahi_hsd.py │ │ ├── test_ahi_l1b_gridded_bin.py │ │ ├── test_ahi_l2_nc.py │ │ ├── test_ami_l1b.py │ │ ├── test_amsr2_l1b.py │ │ ├── test_amsr2_l2.py │ │ ├── test_amsr2_l2_gaasp.py │ │ ├── test_ascat_l2_soilmoisture_bufr.py │ │ ├── test_atms_l1b_nc.py │ │ ├── test_atms_sdr_hdf5.py │ │ ├── test_avhrr_l0_hrpt.py │ │ ├── test_avhrr_l1b_gaclac.py │ │ ├── test_aws1_mwr_l1b.py │ │ ├── test_aws1_mwr_l1c.py │ │ ├── test_camel_l3_nc.py │ │ ├── test_clavrx │ │ │ ├── __init__.py │ │ │ ├── test_clavrx_geohdf.py │ │ │ ├── test_clavrx_nc.py │ │ │ └── test_clavrx_polarhdf.py │ │ ├── test_cmsaf_claas.py │ │ ├── test_electrol_hrit.py │ │ ├── test_epic_l1b_h5.py │ │ ├── test_eps_l1b.py │ │ ├── test_eps_sterna_mwr_l1b.py │ │ ├── test_eum_base.py │ │ ├── test_eum_l2_bufr.py │ │ ├── test_eum_l2_grib.py │ │ ├── test_fci_base.py │ │ ├── test_fci_l1c_nc.py │ │ ├── test_fci_l2_nc.py │ │ ├── test_fy4_base.py │ │ ├── test_generic_image.py │ │ ├── test_geocat.py │ │ ├── test_geos_area.py │ │ ├── test_gerb_l2_hr_h5.py │ │ ├── test_ghi_l1.py │ │ ├── test_ghrsst_l2.py │ │ ├── test_gld360_ualf2.py │ │ ├── test_glm_l2.py │ │ ├── test_goci2_l2_nc.py │ │ ├── test_goes_imager_hrit.py │ │ ├── test_goes_imager_nc_eum.py │ │ ├── test_goes_imager_nc_noaa.py │ │ ├── test_gpm_imerg.py │ │ ├── test_grib.py │ │ ├── test_hdf4_utils.py │ │ ├── test_hdf5_utils.py │ │ ├── test_hdfeos_base.py │ │ ├── test_hrit_base.py │ │ ├── test_hsaf_grib.py │ │ ├── test_hsaf_h5.py │ │ ├── test_hy2_scat_l2b_h5.py │ │ ├── test_iasi_l2.py │ │ ├── test_iasi_l2_so2_bufr.py │ │ ├── test_iasi_ng_l2_nc.py │ │ ├── test_ici_l1b_nc.py │ │ ├── test_insat3d_img_l1b_h5.py │ │ ├── test_li_l2_nc.py │ │ ├── test_meris_nc.py │ │ ├── test_mersi_l1b.py │ │ ├── test_mimic_TPW2_lowres.py │ │ ├── test_mimic_TPW2_nc.py │ │ ├── test_mirs.py │ │ ├── test_moved_reader_bases.py │ │ ├── test_msi_ec_l1c.py │ │ ├── test_msi_safe.py │ │ ├── test_msu_gsa_l1b.py │ │ ├── test_multiple_sensors_isccpng_l1g_nc.py │ │ ├── test_mviri_l1b_fiduceo_nc.py │ │ ├── test_mws_l1b_nc.py │ │ ├── test_netcdf_utils.py │ │ ├── test_nucaps.py │ │ ├── test_nwcsaf_hrw_nc.py │ │ ├── test_nwcsaf_msg.py │ │ ├── test_nwcsaf_nc.py │ │ ├── test_oceancolorcci_l3_nc.py │ │ ├── test_oci_l2_bgc.py │ │ ├── test_olci_nc.py │ │ ├── test_oli_tirs_l1_tif.py │ │ ├── test_omps_edr.py │ │ ├── test_osisaf_l3.py │ │ ├── test_pace_oci_l1b_nc.py │ │ ├── test_safe_sar_l2_ocn.py │ │ ├── test_sar_c_safe.py │ │ ├── test_satpy_cf_nc.py │ │ ├── test_scmi.py │ │ ├── test_seadas_l2.py │ │ ├── test_seviri_base.py │ │ ├── test_seviri_l1b_calibration.py │ │ ├── test_seviri_l1b_hrit.py │ │ ├── test_seviri_l1b_hrit_setup.py │ │ ├── test_seviri_l1b_icare.py │ │ ├── test_seviri_l1b_native.py │ │ ├── test_seviri_l1b_nc.py │ │ ├── test_sgli_l1b.py │ │ ├── test_slstr_l1b.py │ │ ├── test_smos_l2_wind.py │ │ ├── test_tropomi_l2.py │ │ ├── test_utils.py │ │ ├── test_vaisala_gld360.py │ │ ├── test_vii_base_nc.py │ │ ├── test_vii_l1b_nc.py │ │ ├── test_vii_l2_nc.py │ │ ├── test_vii_utils.py │ │ ├── test_vii_wv_nc.py │ │ ├── test_viirs_atms_utils.py │ │ ├── test_viirs_compact.py │ │ ├── test_viirs_edr.py │ │ ├── test_viirs_edr_active_fires.py │ │ ├── test_viirs_edr_flood.py │ │ ├── test_viirs_l1b.py │ │ ├── test_viirs_l2.py │ │ ├── test_viirs_sdr.py │ │ ├── test_viirs_vgac_l1c_nc.py │ │ ├── test_virr_l1b.py │ │ └── utils.py │ ├── scene_tests │ │ ├── __init__.py │ │ ├── test_conversions.py │ │ ├── test_data_access.py │ │ ├── test_init.py │ │ ├── test_load.py │ │ ├── test_resampling.py │ │ └── test_saving.py │ ├── test_cf_roundtrip.py │ ├── test_composites.py │ ├── test_config.py │ ├── test_coords.py │ ├── test_crefl_utils.py │ ├── test_data_download.py │ ├── test_dataset.py │ ├── test_demo.py │ ├── test_dependency_tree.py │ ├── test_file_handlers.py │ ├── test_modifiers.py │ ├── test_node.py │ ├── test_readers.py │ ├── test_regressions.py │ ├── test_resample.py │ ├── test_testing.py │ ├── test_utils.py │ ├── test_writers.py │ ├── test_yaml_reader.py │ ├── utils.py │ └── writer_tests │ │ ├── __init__.py │ │ ├── test_awips_tiled.py │ │ ├── test_cf.py │ │ ├── test_geotiff.py │ │ ├── test_mitiff.py │ │ ├── test_ninjogeotiff.py │ │ ├── test_ninjotiff.py │ │ ├── test_simple_image.py │ │ └── test_utils.py ├── utils.py └── writers │ ├── __init__.py │ ├── awips_tiled.py │ ├── cf_writer.py │ ├── geotiff.py │ ├── mitiff.py │ ├── ninjogeotiff.py │ ├── ninjotiff.py │ ├── simple_image.py │ └── utils.py └── utils ├── convert_to_ninjotiff.py ├── coord2area_def.py ├── create_reference.py └── fetch_avhrr_calcoeffs.py /.bandit: -------------------------------------------------------------------------------- 1 | [bandit] 2 | skips: B506 3 | exclude: satpy/tests 4 | -------------------------------------------------------------------------------- /.codebeatignore: -------------------------------------------------------------------------------- 1 | satpy/version.py 2 | -------------------------------------------------------------------------------- /.git_archival.txt: -------------------------------------------------------------------------------- 1 | node: ecd39317058a38f6fae734cb48c51f68bbf8517c 2 | node-date: 2025-06-05T09:28:35+02:00 3 | describe-name: v0.56.0-268-gecd3931705 4 | ref-names: HEAD -> main, refs/__gh__/pull/2996/rebase 5 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | .git_archival.txt export-subst 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | type: 'bug' 5 | 6 | --- 7 | 8 | **Describe the bug** 9 | A clear and concise description of what the bug is. 10 | 11 | **To Reproduce** 12 | 13 | ```python 14 | # Your code here 15 | 16 | ``` 17 | 18 | **Expected behavior** 19 | A clear and concise description of what you expected to happen. 20 | 21 | **Actual results** 22 | Text output of actual results or error messages including full tracebacks if applicable. 23 | 24 | 25 | **Screenshots** 26 | If applicable, add screenshots to help explain your problem. 27 | 28 | **Environment Info:** 29 | - OS: [e.g. OSX, Windows, Linux] 30 | - Satpy Version: [e.g. 0.9.0] 31 | - PyResample Version: 32 | - Readers and writers dependencies (when relevant): [run `from satpy.utils import check_satpy; check_satpy()`] 33 | 34 | **Additional context** 35 | Add any other context about the problem here. 36 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | type: 'feature' 5 | 6 | --- 7 | 8 | ## Feature Request 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe any changes to existing user workflow** 17 | Are there any backwards compatibility concerns? Changes to the build process? Additional dependencies? 18 | 19 | **Additional context** 20 | Have you considered any alternative solutions or is there anything else that would help describe your request. 21 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | - [ ] Closes #xxxx 5 | - [ ] Tests added 6 | - [ ] Fully documented 7 | - [ ] Add your name to `AUTHORS.md` if not there already 8 | -------------------------------------------------------------------------------- /.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-sdist.yaml: -------------------------------------------------------------------------------- 1 | name: Deploy sdist 2 | 3 | on: 4 | push: 5 | pull_request: 6 | release: 7 | types: 8 | - published 9 | 10 | jobs: 11 | test: 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - name: Checkout source 16 | uses: actions/checkout@v4 17 | 18 | - name: Create sdist 19 | shell: bash -l {0} 20 | run: | 21 | python -m pip install -q build 22 | python -m build 23 | 24 | - name: Publish package to PyPI 25 | if: github.event.action == 'published' 26 | uses: pypa/gh-action-pypi-publish@v1.12.4 27 | with: 28 | user: __token__ 29 | password: ${{ secrets.pypi_password }} 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### PYTHON IGNORES ### 2 | *.py[cod] 3 | 4 | # C extensions 5 | *.so 6 | 7 | # Packages 8 | *.egg 9 | *.egg-info 10 | dist 11 | build 12 | doc/build 13 | eggs 14 | *.eggs 15 | parts 16 | bin 17 | var 18 | sdist 19 | develop-eggs 20 | .installed.cfg 21 | lib 22 | lib64 23 | 24 | # Installer logs 25 | pip-log.txt 26 | 27 | # Unit test / coverage reports 28 | .coverage 29 | .tox 30 | nosetests.xml 31 | htmlcov 32 | 33 | #Translations 34 | *.mo 35 | 36 | #Sphinx 37 | doc/source/_build/* 38 | 39 | #Mr Developer 40 | .mr.developer.cfg 41 | 42 | ### C IGNORES ### 43 | # Object files 44 | *.o 45 | 46 | # Libraries 47 | *.lib 48 | *.a 49 | 50 | # Shared objects (inc. Windows DLLs) 51 | *.dll 52 | *.so 53 | *.so.* 54 | *.dylib 55 | 56 | # Executables 57 | *.exe 58 | *.out 59 | *.app 60 | 61 | # Others 62 | *~ 63 | # PyCharm Settings 64 | .idea 65 | 66 | # VSCode Settings 67 | .vscode 68 | 69 | # vi / vim swp files 70 | *.swp 71 | .DS_STORE 72 | 73 | # setuptools_scm files 74 | # this should be generated automatically when installed 75 | satpy/version.py 76 | doc/source/api/*.rst 77 | doc/source/reader_table.rst 78 | doc/source/area_def_list.rst 79 | 80 | # lock files 81 | *.lock 82 | 83 | # rye files 84 | .python-version 85 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | exclude: '^$' 2 | fail_fast: false 3 | repos: 4 | - repo: https://github.com/astral-sh/ruff-pre-commit 5 | # Ruff version. 6 | rev: 'v0.11.12' 7 | hooks: 8 | - id: ruff 9 | - repo: https://github.com/pre-commit/pre-commit-hooks 10 | rev: v5.0.0 11 | hooks: 12 | - id: trailing-whitespace 13 | - id: end-of-file-fixer 14 | - id: check-yaml 15 | args: [--unsafe] 16 | - repo: https://github.com/PyCQA/bandit 17 | rev: '1.8.3' # Update me! 18 | hooks: 19 | - id: bandit 20 | args: [--ini, .bandit] 21 | - repo: https://github.com/pre-commit/mirrors-mypy 22 | rev: 'v1.16.0' # Use the sha / tag you want to point at 23 | hooks: 24 | - id: mypy 25 | additional_dependencies: 26 | - types-docutils 27 | - types-setuptools 28 | - types-PyYAML 29 | - types-requests 30 | args: ["--python-version", "3.10", "--ignore-missing-imports"] 31 | - repo: https://github.com/pycqa/isort 32 | rev: 6.0.1 33 | hooks: 34 | - id: isort 35 | language_version: python3 36 | ci: 37 | # To trigger manually, comment on a pull request with "pre-commit.ci autofix" 38 | autofix_prs: false 39 | autoupdate_schedule: "monthly" 40 | skip: [bandit] 41 | -------------------------------------------------------------------------------- /.readthedocs.yml: -------------------------------------------------------------------------------- 1 | # Read the Docs configuration file 2 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 3 | version: 2 4 | # Build documentation in the docs/ directory with Sphinx 5 | sphinx: 6 | configuration: doc/source/conf.py 7 | fail_on_warning: true 8 | 9 | # Optionally build your docs in additional formats such as PDF and ePub 10 | formats: all 11 | 12 | build: 13 | os: "ubuntu-20.04" 14 | tools: 15 | python: "mambaforge-4.10" 16 | jobs: 17 | post_checkout: 18 | - git fetch --tags 19 | pre_install: 20 | - git update-index --assume-unchanged doc/rtd_environment.yml doc/source/conf.py 21 | pre_build: 22 | - cd doc/source && if [ "$READTHEDOCS_VERSION" = "latest" ] || [ "$READTHEDOCS_VERSION" = "stable" ]; then python generate_area_def_list.py; else touch area_def_list.rst; fi 23 | conda: 24 | environment: doc/rtd_environment.yml 25 | -------------------------------------------------------------------------------- /CITATION: -------------------------------------------------------------------------------- 1 | To find out how to reference satpy, go to https://zenodo.org/badge/latestdoi/51397392 2 | and choose your favourite citation format on the bottom of the right hand side-bar. 3 | -------------------------------------------------------------------------------- /CONTRIBUTING.rst: -------------------------------------------------------------------------------- 1 | Contributing Guidelines 2 | ======================= 3 | 4 | For detailed contribution guidelines, please see our `Developer's Guide on ReadTheDocs `_. 5 | 6 | 7 | .. If you're reading this file locally as a plain text, you may also 8 | directly refer to the file doc/source/dev_guide/CONTRIBUTING.rst for 9 | any unmerged/pending changes to the contribution guidelines. 10 | -------------------------------------------------------------------------------- /RELEASING.md: -------------------------------------------------------------------------------- 1 | # Releasing Satpy 2 | 3 | 1. checkout main branch 4 | 2. pull from repo 5 | 3. run the unittests 6 | 4. run `loghub` and update the `CHANGELOG.md` file: 7 | 8 | ``` 9 | loghub pytroll/satpy --token $LOGHUB_GITHUB_TOKEN -st $(git tag --sort=-version:refname --list 'v*' | head -n 1) -plg bug "Bugs fixed" -plg enhancement "Features added" -plg documentation "Documentation changes" -plg backwards-incompatibility "Backward incompatible changes" -plg refactor "Refactoring" 10 | ``` 11 | 12 | This uses a `LOGHUB_GITHUB_TOKEN` environment variable. This must be created 13 | on GitHub and it is recommended that you add it to your `.bashrc` or 14 | `.bash_profile` or equivalent. 15 | 16 | This command will create a CHANGELOG.temp file which need to be added 17 | to the top of the CHANGLOG.md file. The same content is also printed 18 | to terminal, so that can be copy-pasted, too. Remember to update also 19 | the version number to the same given in step 5. Don't forget to commit 20 | CHANGELOG.md! 21 | 22 | 5. Create a tag with the new version number, starting with a 'v', eg: 23 | 24 | ``` 25 | git tag -a v -m "Version " 26 | ``` 27 | 28 | For example if the previous tag was `v0.9.0` and the new release is a 29 | patch release, do: 30 | 31 | ``` 32 | git tag -a v0.9.1 -m "Version 0.9.1" 33 | ``` 34 | 35 | See [semver.org](http://semver.org/) on how to write a version number. 36 | 37 | 38 | 6. push changes to github `git push --follow-tags` 39 | 7. Verify github action unittests passed. 40 | 8. Create a "Release" on GitHub by going to 41 | https://github.com/pytroll/satpy/releases and clicking "Draft a new release". 42 | On the next page enter the newly created tag in the "Tag version" field, 43 | "Version X.Y.Z" in the "Release title" field, and paste the markdown from 44 | the changelog (the portion under the version section header) in the 45 | "Describe this release" box. Finally click "Publish release". 46 | 9. Verify the GitHub actions for deployment succeed and the release is on PyPI. 47 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Satpy is currently pre-1.0 and includes a lot of changes in every release. As such we can't 6 | guarantee that releases before 1.0 will see security updates except for the most recent 7 | release. After 1.0, you can expect more stability in the interfaces and security fixes to be 8 | backported more regularly. 9 | 10 | | Version | Supported | 11 | | ------- | ------------------ | 12 | | 0.x.x (latest) | :white_check_mark: | 13 | | < 0.33.0 | :x: | 14 | 15 | ## Unsafe YAML Loading 16 | 17 | Satpy allows for unsafe loading of YAML configuration files. Any YAML files 18 | from untrusted sources should be sanitized of possibly malicious code. 19 | 20 | ## Reporting a Vulnerability 21 | 22 | Do you think you've found a security vulnerability or issue in this project? Let us know by sending 23 | an email to the maintainers at `pytroll-security@groups.io`. Please include as much information on 24 | the issue as possible like code examples, documentation on the issue in other packages, etc. 25 | -------------------------------------------------------------------------------- /benchmarks/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2021 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | """Benchmark satpy.""" 19 | -------------------------------------------------------------------------------- /continuous_integration/environment.yaml: -------------------------------------------------------------------------------- 1 | name: test-environment 2 | channels: 3 | - conda-forge 4 | dependencies: 5 | - xarray!=2022.9.0 6 | - dask 7 | - distributed 8 | - dask-image 9 | - donfig 10 | - platformdirs 11 | - toolz 12 | - Cython 13 | - numba 14 | - sphinx 15 | - cartopy 16 | - panel>=0.12.7 17 | - pillow 18 | - matplotlib 19 | - scipy 20 | - pyyaml 21 | - pyproj 22 | - pyresample>=1.24 23 | - coveralls 24 | - coverage 25 | - codecov 26 | - behave 27 | - netcdf4 28 | - h5py 29 | - h5netcdf 30 | - gdal 31 | - rasterio 32 | - bottleneck 33 | - rioxarray 34 | - defusedxml 35 | - imageio 36 | - pyhdf 37 | - mock 38 | - libtiff 39 | - geoviews 40 | - holoviews 41 | - hvplot 42 | - zarr 43 | - python-eccodes 44 | # 2.19.1 seems to cause library linking issues 45 | - eccodes>=2.20 46 | - pytest 47 | - pytest-cov 48 | - fsspec 49 | - universal_pathlib 50 | - botocore>=1.33 51 | - s3fs 52 | - python-geotiepoints 53 | - pooch 54 | - pip 55 | - skyfield 56 | - astropy 57 | - pint-xarray 58 | - ephem 59 | - bokeh 60 | - pytest-xdist 61 | - pip: 62 | - pytest-lazy-fixtures 63 | - trollsift 64 | - trollimage>=1.24 65 | - pyspectral 66 | - pyorbital 67 | - pyPublicDecompWT 68 | -------------------------------------------------------------------------------- /doc/README: -------------------------------------------------------------------------------- 1 | With sphinx and satpy's dependencies installed documentation can be generated 2 | by running: 3 | 4 | make html 5 | 6 | The generated HTML documentation pages are available in `build/html`. 7 | -------------------------------------------------------------------------------- /doc/rtd_environment.yml: -------------------------------------------------------------------------------- 1 | name: readthedocs 2 | channels: 3 | - conda-forge 4 | dependencies: 5 | - python=3.11 6 | - pip 7 | - platformdirs 8 | - dask 9 | - dask-image 10 | - dask-expr 11 | - defusedxml 12 | - donfig 13 | # 2.19.1 seems to cause library linking issues 14 | - eccodes>=2.20 15 | - graphviz 16 | - numba 17 | - numpy 18 | - pillow 19 | - pooch 20 | - pyresample 21 | - pytest 22 | - python-eccodes 23 | - python-geotiepoints 24 | - rasterio 25 | - rioxarray 26 | - setuptools 27 | - setuptools_scm 28 | - sphinx>=8.2.0 29 | - sphinx_rtd_theme 30 | - sphinx-autodoc-typehints 31 | - trollsift 32 | - xarray 33 | - zarr 34 | - xarray-datatree 35 | - geoviews 36 | - pip: 37 | - graphviz 38 | - pytest-lazy-fixtures 39 | - .. # relative path to the satpy project 40 | -------------------------------------------------------------------------------- /doc/source/_static/main.js: -------------------------------------------------------------------------------- 1 | $(document).ready( function () { 2 | $('table.datatable').DataTable( { 3 | "paging": true, 4 | "pageLength": 15, 5 | "layout": { 6 | 'topStart': 'info', 7 | 'topEnd': 'search', 8 | 'bottomStart': null, 9 | 'bottomEnd': 'paging' 10 | }, 11 | "order": [[0, 'asc']] 12 | } ); 13 | 14 | $('table.area-table').DataTable( { 15 | "paging": true, 16 | "pageLength": 15, 17 | "layout": { 18 | 'topStart': 'info', 19 | 'topEnd': 'search', 20 | 'bottomEnd': 'paging', 21 | 'bottomStart': null 22 | } 23 | } ); 24 | } ); 25 | -------------------------------------------------------------------------------- /doc/source/_static/theme_overrides.css: -------------------------------------------------------------------------------- 1 | /* override table width restrictions */ 2 | @media screen and (min-width: 767px) { 3 | 4 | .wy-table-responsive table td { 5 | /* !important prevents the common CSS stylesheets from overriding 6 | this as on RTD they are loaded after this stylesheet */ 7 | white-space: normal !important; 8 | } 9 | 10 | .wy-table-responsive { 11 | overflow: visible !important; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /doc/source/api/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pytroll/satpy/ecd39317058a38f6fae734cb48c51f68bbf8517c/doc/source/api/.gitkeep -------------------------------------------------------------------------------- /doc/source/dev_guide/remote_file_support.rst: -------------------------------------------------------------------------------- 1 | ====================================== 2 | Adding remote file support to a reader 3 | ====================================== 4 | 5 | .. warning:: 6 | This feature is currently very new and might improve and change 7 | in the future. 8 | 9 | .. note:: 10 | 11 | All the base classes and reader utility functions have been moved 12 | to :mod:`satpy.readers.core` sub-package. Importing from the old 13 | location will issue a warning. The old import paths will work until 14 | they will be removed in Satpy 1.0. 15 | 16 | As of Satpy version 0.25.1 the possibility to search for files on remote 17 | file systems (see :ref:`search_for_files`) as well as the possibility 18 | for supported readers to read from remote filesystems has been added. 19 | 20 | To add this feature to a reader the call to :func:`xarray.open_dataset` 21 | has to be replaced by the function :func:`~satpy.readers.core.file_handlers.open_dataset` 22 | included in Satpy which handles passing on the filename to be opened regardless 23 | if it is a local file path or a :class:`~satpy.readers.core.remote.FSFile` object which can wrap 24 | :func:`fsspec.open` objects. 25 | 26 | To be able to cache the ``open_dataset`` call which is favourable for remote files 27 | it should be separated from the ``get_dataset`` method which needs to be implemented 28 | in every reader. This could look like: 29 | 30 | .. code-block:: python 31 | 32 | from satpy._compat importe cached_property 33 | from satpy.readers.core.file_handlers import BaseFileHandler, open_dataset 34 | 35 | class Reader(BaseFileHandler): 36 | 37 | def __init__(self, filename, filename_info, filetype_info): 38 | super(Reader).__init__(filename, filename_info, filetype_info): 39 | 40 | @cached_property 41 | def nc(self): 42 | return open_dataset(self.filename, chunks="auto") 43 | 44 | def get_dataset(self): 45 | # Access the opened dataset 46 | data = self.nc["key"] 47 | 48 | 49 | Any parameters allowed for :func:`xarray.open_dataset` can be passed as 50 | keywords to :func:`~satpy.readers.core.file_handlers.open_dataset` if needed. 51 | 52 | .. note:: 53 | It is important to know that for remote files xarray might use a different 54 | backend to open the file than for local files (e.g. h5netcdf instead of netcdf4), 55 | which might result in some attributes being returned as arrays instead of scalars. 56 | This has to be accounted for when accessing attributes in the reader. 57 | -------------------------------------------------------------------------------- /doc/source/dev_guide/testing.rst: -------------------------------------------------------------------------------- 1 | Testing Satpy-based applications 2 | ================================ 3 | 4 | The ``satpy.testing`` modules provides tools for writing tests of applications that use Satpy. 5 | 6 | - To allow Scene creation and loading fake datasets without reading any data files: :func:`~satpy.testing.fake_satpy_reading` 7 | -------------------------------------------------------------------------------- /doc/source/dev_guide/writing_tests.rst: -------------------------------------------------------------------------------- 1 | ================== 2 | Writing unit tests 3 | ================== 4 | 5 | Satpy tests are written using the third-party :doc:`pytest ` 6 | package. 7 | 8 | Fixtures 9 | ======== 10 | 11 | The usage of Pytest `fixtures `_ 12 | is encouraged for code re-usability. 13 | 14 | As the builtin fixtures (and those defined in ``conftest.py`` file) are injected by 15 | Pytest without them being imported explicitly, their usage can be very confusing for 16 | new developers. To lessen the confusion, it is encouraged to add a note at the 17 | top of the test modules listing all the automatically injected external fixtures 18 | that are used in the module:: 19 | 20 | # NOTE: 21 | # The following fixtures are not defined in this file, but are used and injected by Pytest: 22 | # - tmp_path 23 | # - fixture_defined_in_conftest.py 24 | -------------------------------------------------------------------------------- /doc/source/docutils.conf: -------------------------------------------------------------------------------- 1 | [parsers] 2 | line_length_limit=30000000 3 | -------------------------------------------------------------------------------- /doc/source/doi_role.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """Create sphinx roles for referencing the DOI of a published paper. 3 | 4 | Extension to add links to DOIs. With this extension you can use e.g. 5 | :doi:`10.1016/S0022-2836(05)80360-2` in your documents. This will 6 | create a link to a DOI resolver 7 | (``https://doi.org/10.1016/S0022-2836(05)80360-2``). 8 | The link caption will be the raw DOI. 9 | You can also give an explicit caption, e.g. 10 | :doi:`Basic local alignment search tool <10.1016/S0022-2836(05)80360-2>`. 11 | 12 | :copyright: Copyright 2015 Jon Lund Steffensen. Based on extlinks by 13 | the Sphinx team. 14 | :license: BSD. 15 | 16 | """ 17 | 18 | from docutils import nodes, utils 19 | from sphinx.util.nodes import split_explicit_title 20 | 21 | 22 | def doi_role(typ, rawtext, text, lineno, inliner, options=None, content=None): 23 | """Create a doi role.""" 24 | if options is None: 25 | options = {} 26 | if content is None: 27 | content = [] 28 | text = utils.unescape(text) 29 | has_explicit_title, title, part = split_explicit_title(text) 30 | full_url = "https://doi.org/" + part 31 | if not has_explicit_title: 32 | title = "DOI:" + part 33 | pnode = nodes.reference(title, title, internal=False, refuri=full_url) 34 | return [pnode], [] 35 | 36 | 37 | def arxiv_role(typ, rawtext, text, lineno, inliner, options=None, content=None): 38 | """Create an arxive role.""" 39 | if options is None: 40 | options = {} 41 | if content is None: 42 | content = [] 43 | text = utils.unescape(text) 44 | has_explicit_title, title, part = split_explicit_title(text) 45 | full_url = "https://arxiv.org/abs/" + part 46 | if not has_explicit_title: 47 | title = "arXiv:" + part 48 | pnode = nodes.reference(title, title, internal=False, refuri=full_url) 49 | return [pnode], [] 50 | 51 | 52 | def setup_link_role(app): 53 | """Set up the role link.""" 54 | app.add_role("doi", doi_role, override=True) 55 | app.add_role("DOI", doi_role, override=True) 56 | app.add_role("arXiv", arxiv_role, override=True) 57 | app.add_role("arxiv", arxiv_role, override=True) 58 | 59 | 60 | def setup(app): 61 | """Set up the app.""" 62 | app.connect("builder-inited", setup_link_role) 63 | return {"version": "0.1", "parallel_read_safe": True} 64 | -------------------------------------------------------------------------------- /doc/source/examples/fci_l1c_natural_color.rst: -------------------------------------------------------------------------------- 1 | MTG FCI - Natural Color Example 2 | =============================== 3 | 4 | Satpy includes a reader for the Meteosat Third Generation (MTG) FCI Level 1c 5 | data. The following Python code snippet shows an example on how to use Satpy 6 | to generate a Natural Color RGB composite over the European area. 7 | 8 | .. warning:: 9 | 10 | This example is currently a work in progress. Some of the below code may 11 | not work with the currently released version of Satpy. Additional updates 12 | to this example will be coming soon. 13 | 14 | .. note:: 15 | 16 | For reading compressed data, a decompression library is 17 | needed. Either install the FCIDECOMP library (see the `FCI L1 Product User 18 | Guide `_, or the 19 | ``hdf5plugin`` package with:: 20 | 21 | pip install hdf5plugin 22 | 23 | or:: 24 | 25 | conda install hdf5plugin -c conda-forge 26 | 27 | If you use ``hdf5plugin``, make sure to add the line ``import hdf5plugin`` 28 | at the top of your script. 29 | 30 | .. code-block:: python 31 | 32 | from satpy.scene import Scene 33 | from satpy import find_files_and_readers 34 | 35 | # define path to FCI test data folder 36 | path_to_data = 'your/path/to/FCI/data/folder/' 37 | 38 | # find files and assign the FCI reader 39 | files = find_files_and_readers(base_dir=path_to_data, reader='fci_l1c_nc') 40 | 41 | # create an FCI scene from the selected files 42 | scn = Scene(filenames=files) 43 | 44 | # print available dataset names for this scene (e.g. 'vis_04', 'vis_05','ir_38',...) 45 | print(scn.available_dataset_names()) 46 | 47 | # print available composite names for this scene (e.g. 'natural_color', 'airmass', 'convection',...) 48 | print(scn.available_composite_names()) 49 | 50 | # load the datasets/composites of interest 51 | scn.load(['natural_color','vis_04'], upper_right_corner='NE') 52 | # note: the data inside the FCI files is stored upside down. The upper_right_corner='NE' argument 53 | # flips it automatically in upright position. 54 | 55 | # you can access the values of a dataset as a Numpy array with 56 | vis_04_values = scn['vis_04'].values 57 | 58 | # resample the scene to a specified area (e.g. "eurol1" for Europe in 1km resolution) 59 | scn_resampled = scn.resample("eurol", resampler='nearest', radius_of_influence=5000) 60 | 61 | # save the resampled dataset/composite to disk 62 | scn_resampled.save_dataset("natural_color", filename='./fci_natural_color_resampled.png') 63 | -------------------------------------------------------------------------------- /doc/source/examples/vii_l1b_nc.rst: -------------------------------------------------------------------------------- 1 | EPS-SG VII netCDF Example 2 | =============================== 3 | 4 | Satpy includes a reader for the EPS-SG Visible and Infrared Imager (VII) 5 | Level 1b data. The following Python code snippet shows an example on how to use 6 | Satpy to read a channel and resample and save the image over the European area. 7 | 8 | .. warning:: 9 | 10 | This example is currently a work in progress. Some of the below code may 11 | not work with the currently released version of Satpy. Additional updates 12 | to this example will be coming soon. 13 | 14 | .. code-block:: python 15 | 16 | import glob 17 | from satpy.scene import Scene 18 | 19 | # find the file/files to be read 20 | filenames = glob.glob('/path/to/VII/data/W_xx-eumetsat-darmstadt,SAT,SGA1-VII-1B-RAD_C_EUMT_20191007055100*') 21 | 22 | # create a VII scene from the selected granule(s) 23 | scn = Scene(filenames=filenames, reader='vii_l1b_nc') 24 | 25 | # print available dataset names for this scene 26 | print(scn.available_dataset_names()) 27 | 28 | # load the datasets of interest 29 | # NOTE: only radiances are supported for test data 30 | scn.load(["vii_668"], calibration="radiance") 31 | 32 | # resample the scene to a specified area (e.g. "eurol1" for Europe in 1km resolution) 33 | eur = scn.resample("eurol", resampler='nearest', radius_of_influence=5000) 34 | 35 | # save the resampled data to disk 36 | eur.save_dataset("vii_668", filename='./vii_668_eur.png') 37 | -------------------------------------------------------------------------------- /doc/source/resample.rst: -------------------------------------------------------------------------------- 1 | ========== 2 | Resampling 3 | ========== 4 | 5 | .. automodule:: satpy.resample 6 | :noindex: 7 | :no-members: 8 | :no-special-members: 9 | -------------------------------------------------------------------------------- /satpy/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2009-2019 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | """Satpy Package initializer.""" 19 | 20 | try: 21 | from satpy.version import version as __version__ # noqa 22 | except ModuleNotFoundError: 23 | raise ModuleNotFoundError( 24 | "No module named satpy.version. This could mean " 25 | "you didn't install 'satpy' properly. Try reinstalling ('pip " 26 | "install').") 27 | 28 | from satpy._config import config # noqa 29 | from satpy.dataset import DataID, DataQuery # noqa 30 | from satpy.dataset.data_dict import DatasetDict # noqa 31 | from satpy.multiscene import MultiScene # noqa 32 | from satpy.readers.core.config import available_readers # noqa 33 | from satpy.readers.core.grouping import find_files_and_readers # noqa 34 | from satpy.scene import Scene # noqa 35 | from satpy.utils import get_logger # noqa 36 | from satpy.writers import available_writers # noqa 37 | 38 | log = get_logger("satpy") 39 | -------------------------------------------------------------------------------- /satpy/_compat.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2020 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | """Backports and compatibility fixes for satpy.""" 19 | 20 | from functools import cache, cached_property # noqa 21 | 22 | try: 23 | from numpy.typing import ArrayLike, DTypeLike # noqa 24 | except ImportError: 25 | # numpy <1.20 26 | from numpy import dtype as DTypeLike # noqa 27 | from numpy import ndarray as ArrayLike # noqa 28 | -------------------------------------------------------------------------------- /satpy/area.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) 2015-2025 Satpy developers 3 | # 4 | # This file is part of satpy. 5 | # 6 | # satpy is free software: you can redistribute it and/or modify it under the 7 | # terms of the GNU General Public License as published by the Free Software 8 | # Foundation, either version 3 of the License, or (at your option) any later 9 | # version. 10 | # 11 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 12 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License along with 16 | # satpy. If not, see . 17 | """Utility functions for area definitions.""" 18 | from ._config import config_search_paths, get_config_path 19 | 20 | 21 | def get_area_file(): 22 | """Find area file(s) to use. 23 | 24 | The files are to be named `areas.yaml` or `areas.def`. 25 | """ 26 | paths = config_search_paths("areas.yaml") 27 | if paths: 28 | return paths 29 | else: 30 | return get_config_path("areas.def") 31 | 32 | 33 | def get_area_def(area_name): 34 | """Get the definition of *area_name* from file. 35 | 36 | The file is defined to use is to be placed in the $SATPY_CONFIG_PATH 37 | directory, and its name is defined in satpy's configuration file. 38 | """ 39 | try: 40 | from pyresample import parse_area_file 41 | except ImportError: 42 | from pyresample.utils import parse_area_file 43 | return parse_area_file(get_area_file(), area_name)[0] 44 | -------------------------------------------------------------------------------- /satpy/cf/__init__.py: -------------------------------------------------------------------------------- 1 | """Code for generation of CF-compliant datasets.""" 2 | -------------------------------------------------------------------------------- /satpy/cf/decoding.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2023 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | 19 | """CF decoding.""" 20 | 21 | import copy 22 | import datetime as dt 23 | import json 24 | 25 | 26 | def decode_attrs(attrs): 27 | """Decode CF-encoded attributes to Python object. 28 | 29 | Converts timestamps to datetime and strings starting with "{" to 30 | dictionary. 31 | 32 | Args: 33 | attrs (dict): Attributes to be decoded 34 | 35 | Returns (dict): Decoded attributes 36 | """ 37 | attrs = copy.deepcopy(attrs) 38 | _decode_dict_type_attrs(attrs) 39 | _decode_timestamps(attrs) 40 | return attrs 41 | 42 | 43 | def _decode_dict_type_attrs(attrs): 44 | for key, val in attrs.items(): 45 | attrs[key] = _str2dict(val) 46 | 47 | 48 | def _str2dict(val): 49 | """Convert string to dictionary.""" 50 | if isinstance(val, str) and val.startswith("{"): 51 | val = json.loads(val, object_hook=_datetime_parser_json) 52 | return val 53 | 54 | 55 | def _decode_timestamps(attrs): 56 | for key, value in attrs.items(): 57 | timestamp = _str2datetime(value) 58 | if timestamp: 59 | attrs[key] = timestamp 60 | 61 | 62 | def _datetime_parser_json(json_dict): 63 | """Traverse JSON dictionary and parse timestamps.""" 64 | for key, value in json_dict.items(): 65 | timestamp = _str2datetime(value) 66 | if timestamp: 67 | json_dict[key] = timestamp 68 | return json_dict 69 | 70 | 71 | def _str2datetime(string): 72 | """Convert string to datetime object.""" 73 | try: 74 | return dt.datetime.fromisoformat(string) 75 | except (TypeError, ValueError): 76 | return None 77 | -------------------------------------------------------------------------------- /satpy/composites/abi.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2015-2017 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | """Composite classes for the ABI instrument.""" 19 | 20 | import logging 21 | 22 | from satpy.composites import GenericCompositor 23 | 24 | LOG = logging.getLogger(__name__) 25 | 26 | 27 | class SimulatedGreen(GenericCompositor): 28 | """A single-band dataset resembling a Green (0.55 µm) band. 29 | 30 | This compositor creates a single band product by combining three 31 | other bands in various amounts. The general formula with 32 | dependencies (d) and fractions (f) is:: 33 | 34 | result = d1 * f1 + d2 * f2 + d3 * f3 35 | 36 | See the `fractions` keyword argument for more information. 37 | Common used fractions for ABI data with C01, C02, and C03 inputs include: 38 | 39 | - SatPy default (historical): (0.465, 0.465, 0.07) 40 | - `CIMSS (Kaba) `_: (0.45, 0.45, 0.10) 41 | - `EDC `_: (0.45706946, 0.48358168, 0.06038137) 42 | 43 | """ 44 | 45 | def __init__(self, name, fractions=(0.465, 0.465, 0.07), **kwargs): # noqa: D417 46 | """Initialize fractions for input channels. 47 | 48 | Args: 49 | name (str): Name of this composite 50 | fractions (Iterable): Fractions of each input band to include in the result. 51 | 52 | """ 53 | self.fractions = fractions 54 | super(SimulatedGreen, self).__init__(name, **kwargs) 55 | 56 | def __call__(self, projectables, optional_datasets=None, **attrs): 57 | """Generate the single band composite.""" 58 | c01, c02, c03 = self.match_data_arrays(projectables) 59 | res = c01 * self.fractions[0] + c02 * self.fractions[1] + c03 * self.fractions[2] 60 | res.attrs = c03.attrs.copy() 61 | return super(SimulatedGreen, self).__call__((res,), **attrs) 62 | -------------------------------------------------------------------------------- /satpy/composites/agri.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2015-2022 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | """Composite classes for the AGRI instrument.""" 19 | 20 | import logging 21 | 22 | from satpy.composites import GenericCompositor 23 | 24 | LOG = logging.getLogger(__name__) 25 | 26 | 27 | class SimulatedRed(GenericCompositor): 28 | """A single-band dataset resembling a Red (0.64 µm) band. 29 | 30 | This compositor creates a single band product by combining two 31 | other bands by preset amounts. The general formula with 32 | dependencies (d) and fractions (f) is:: 33 | 34 | result = (f1 * d1 - f2 * d2) / f3 35 | 36 | See the `fractions` keyword argument for more information. 37 | The default setup is to use: 38 | 39 | - f1 = 1.0 40 | - f2 = 0.13 41 | - f3 = 0.87 42 | 43 | """ 44 | 45 | def __init__(self, name, fractions=(1.0, 0.13, 0.87), **kwargs): # noqa: D417 46 | """Initialize fractions for input channels. 47 | 48 | Args: 49 | name (str): Name of this composite 50 | fractions (Iterable): Fractions of each input band to include in the result. 51 | 52 | """ 53 | self.fractions = fractions 54 | super(SimulatedRed, self).__init__(name, **kwargs) 55 | 56 | def __call__(self, projectables, optional_datasets=None, **attrs): 57 | """Generate the single band composite.""" 58 | c1, c2 = self.match_data_arrays(projectables) 59 | res = (c1 * self.fractions[0] - c2 * self.fractions[1]) / self.fractions[2] 60 | res.attrs = c1.attrs.copy() 61 | return super(SimulatedRed, self).__call__((res,), **attrs) 62 | -------------------------------------------------------------------------------- /satpy/composites/ahi.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022- Satpy developers 2 | # 3 | # This file is part of satpy. 4 | # 5 | # satpy is free software: you can redistribute it and/or modify it under the 6 | # terms of the GNU General Public License as published by the Free Software 7 | # Foundation, either version 3 of the License, or (at your option) any later 8 | # version. 9 | # 10 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 11 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 12 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License along with 15 | # satpy. If not, see . 16 | """Composite classes for AHI.""" 17 | -------------------------------------------------------------------------------- /satpy/conftest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2021 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | """Pytest configuration and setup functions.""" 19 | import pytest 20 | 21 | 22 | def pytest_configure(config): 23 | """Set test configuration.""" 24 | from satpy import aux_download 25 | aux_download.RUNNING_TESTS = True 26 | 27 | 28 | def pytest_unconfigure(config): 29 | """Undo previous configurations.""" 30 | from satpy import aux_download 31 | aux_download.RUNNING_TESTS = False 32 | 33 | 34 | @pytest.fixture(scope="session") 35 | def session_tmp_path(tmp_path_factory): 36 | """Generate a single temp path to use for the entire session.""" 37 | return tmp_path_factory.mktemp("data") 38 | -------------------------------------------------------------------------------- /satpy/dataset/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2016-2019 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | """Classes and functions related to data identification and querying.""" 19 | 20 | from .anc_vars import dataset_walker, replace_anc # noqa 21 | from .data_dict import DatasetDict, get_key # noqa 22 | from .dataid import DataID, DataQuery, ModifierTuple, WavelengthRange, create_filtered_query # noqa 23 | from .metadata import combine_metadata # noqa 24 | -------------------------------------------------------------------------------- /satpy/dataset/anc_vars.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2015-2020 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | """Utilities for dealing with ancillary variables.""" 19 | 20 | from .dataid import DataID, default_id_keys_config 21 | 22 | 23 | def dataset_walker(datasets): 24 | """Walk through *datasets* and their ancillary data. 25 | 26 | Yields datasets and their parent. 27 | """ 28 | for dataset in datasets: 29 | yield dataset, None 30 | for anc_ds in dataset.attrs.get("ancillary_variables", []): 31 | try: 32 | anc_ds.attrs 33 | yield anc_ds, dataset 34 | except AttributeError: 35 | continue 36 | 37 | 38 | def replace_anc(dataset, parent_dataset): 39 | """Replace *dataset* the *parent_dataset*'s `ancillary_variables` field.""" 40 | if parent_dataset is None: 41 | return 42 | id_keys = parent_dataset.attrs.get( 43 | "_satpy_id_keys", 44 | dataset.attrs.get( 45 | "_satpy_id_keys", 46 | default_id_keys_config)) 47 | current_dataid = DataID(id_keys, **dataset.attrs) 48 | for idx, ds in enumerate(parent_dataset.attrs["ancillary_variables"]): 49 | if current_dataid == DataID(id_keys, **ds.attrs): 50 | parent_dataset.attrs["ancillary_variables"][idx] = dataset 51 | return 52 | -------------------------------------------------------------------------------- /satpy/demo/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2019-2021 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | """Demo data download helper functions. 19 | 20 | Each ``get_*`` function below downloads files to a local directory and returns 21 | a list of paths to those files. Some (not all) functions have multiple options 22 | for how the data is downloaded (via the ``method`` keyword argument) 23 | including: 24 | 25 | - gcsfs: 26 | Download data from a public google cloud storage bucket using the 27 | ``gcsfs`` package. 28 | - unidata_thredds: 29 | Access data using OpenDAP or similar method from Unidata's 30 | public THREDDS server 31 | (https://thredds.unidata.ucar.edu/thredds/catalog.html). 32 | - uwaos_thredds: 33 | Access data using OpenDAP or similar method from the 34 | University of Wisconsin - Madison's AOS department's THREDDS server. 35 | - http: 36 | A last resort download method when nothing else is available of a 37 | tarball or zip file from one or more servers available to the Satpy 38 | project. 39 | - uw_arcdata: 40 | A network mount available on many servers at the Space Science 41 | and Engineering Center (SSEC) at the University of Wisconsin - Madison. 42 | This is method is mainly meant when tutorials are taught at the SSEC 43 | using a Jupyter Hub server. 44 | 45 | To use these functions, do: 46 | 47 | >>> from satpy import Scene, demo 48 | >>> filenames = demo.get_us_midlatitude_cyclone_abi() 49 | >>> scn = Scene(reader='abi_l1b', filenames=filenames) 50 | 51 | """ 52 | 53 | from .abi_l1b import get_hurricane_florence_abi # noqa: F401, I001 54 | from .abi_l1b import get_us_midlatitude_cyclone_abi # noqa: F401 55 | from .ahi_hsd import download_typhoon_surigae_ahi # noqa: F401 56 | from .fci import download_fci_test_data # noqa: F401 57 | from .seviri_hrit import download_seviri_hrit_20180228_1500 # noqa: F401 58 | from .viirs_sdr import get_viirs_sdr_20170128_1229 # noqa: F401 59 | -------------------------------------------------------------------------------- /satpy/demo/ahi_hsd.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2021 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | """Demo data download helper functions for AHI HSD data.""" 19 | import os 20 | 21 | from satpy import config 22 | 23 | 24 | def download_typhoon_surigae_ahi(base_dir=None, 25 | channels=(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), 26 | segments=(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)): 27 | """Download Himawari 8 data. 28 | 29 | This scene shows the Typhoon Surigae. 30 | """ 31 | import s3fs 32 | base_dir = base_dir or config.get("demo_data_dir", ".") 33 | channel_resolution = {1: 10, 34 | 2: 10, 35 | 3: 5, 36 | 4: 10} 37 | data_files = [] 38 | for channel in channels: 39 | resolution = channel_resolution.get(channel, 20) 40 | for segment in segments: 41 | data_files.append(f"HS_H08_20210417_0500_B{channel:02d}_FLDK_R{resolution:02d}_S{segment:02d}10.DAT.bz2") 42 | 43 | subdir = os.path.join(base_dir, "ahi_hsd", "20210417_0500_typhoon_surigae") 44 | os.makedirs(subdir, exist_ok=True) 45 | fs = s3fs.S3FileSystem(anon=True) 46 | 47 | result = [] 48 | for filename in data_files: 49 | destination_filename = os.path.join(subdir, filename) 50 | result.append(destination_filename) 51 | if os.path.exists(destination_filename): 52 | continue 53 | to_get = "noaa-himawari8/AHI-L1b-FLDK/2021/04/17/0500/" + filename 54 | fs.get_file(to_get, destination_filename) 55 | 56 | return result 57 | -------------------------------------------------------------------------------- /satpy/demo/fci.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2021 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | """Demo FCI data download.""" 19 | 20 | import pathlib 21 | import tarfile 22 | import tempfile 23 | 24 | from satpy import config 25 | 26 | from . import utils 27 | 28 | _fci_uncompressed_nominal = ( 29 | "https://sftp.eumetsat.int/public/folder/UsCVknVOOkSyCdgpMimJNQ/" 30 | "User-Materials/Test-Data/MTG/MTG_FCI_L1C_Enhanced-NonN_TD-272_May2020/" 31 | "FCI_1C_UNCOMPRESSED_NOMINAL.tar.gz") 32 | 33 | 34 | def download_fci_test_data(base_dir=None): 35 | """Download FCI test data. 36 | 37 | Download the nominal FCI test data from July 2020. 38 | """ 39 | subdir = get_fci_test_data_dir(base_dir=base_dir) 40 | with tempfile.TemporaryDirectory() as td: 41 | nm = pathlib.Path(td) / "fci-test-data.tar.gz" 42 | utils.download_url(_fci_uncompressed_nominal, nm) 43 | return _unpack_tarfile_to(nm, subdir) 44 | 45 | 46 | def get_fci_test_data_dir(base_dir=None): 47 | """Get directory for FCI test data.""" 48 | base_dir = base_dir or config.get("demo_data_dir", ".") 49 | return pathlib.Path(base_dir) / "fci" / "test_data" 50 | 51 | 52 | def _unpack_tarfile_to(filename, subdir): 53 | """Unpack content of tarfile in filename to subdir.""" 54 | with tarfile.open(filename, mode="r:gz") as tf: 55 | contents = tf.getnames() 56 | tf.extractall(path=subdir) # nosec 57 | return contents 58 | -------------------------------------------------------------------------------- /satpy/demo/utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2021 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | """Utilities for demo data download.""" 19 | 20 | import requests 21 | 22 | 23 | def download_url(source, target): 24 | """Download a url in stream mode.""" 25 | with requests.get(source, stream=True, timeout=10) as r: 26 | r.raise_for_status() 27 | with open(target, "wb") as f: 28 | for chunk in r.iter_content(chunk_size=8192): 29 | f.write(chunk) 30 | -------------------------------------------------------------------------------- /satpy/enhancements/abi.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) 2019 Satpy developers 3 | # 4 | # This file is part of satpy. 5 | # 6 | # satpy is free software: you can redistribute it and/or modify it under the 7 | # terms of the GNU General Public License as published by the Free Software 8 | # Foundation, either version 3 of the License, or (at your option) any later 9 | # version. 10 | # 11 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 12 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License along with 16 | # satpy. If not, see . 17 | """Enhancement functions specific to the ABI sensor.""" 18 | 19 | from satpy.enhancements import exclude_alpha, using_map_blocks 20 | 21 | 22 | def cimss_true_color_contrast(img, **kwargs): 23 | """Scale data based on CIMSS True Color recipe for AWIPS.""" 24 | _cimss_true_color_contrast(img.data) 25 | 26 | 27 | @exclude_alpha 28 | @using_map_blocks 29 | def _cimss_true_color_contrast(img_data): 30 | """Perform per-chunk enhancement. 31 | 32 | Code ported from Kaba Bah's AWIPS python plugin for creating the 33 | CIMSS Natural (True) Color image in AWIPS. AWIPS provides that python 34 | code the image data on a 0-255 scale. Satpy gives this function the 35 | data on a 0-1.0 scale (assuming linear stretching and sqrt 36 | enhancements have already been applied). 37 | 38 | """ 39 | max_value = 1.0 40 | acont = (255.0 / 10.0) / 255.0 41 | amax = (255.0 + 4.0) / 255.0 42 | amid = 1.0 / 2.0 43 | afact = (amax * (acont + max_value) / (max_value * (amax - acont))) 44 | aband = (afact * (img_data - amid) + amid) 45 | aband[aband <= 10 / 255.0] = 0 46 | aband[aband >= 1.0] = 1.0 47 | return aband 48 | -------------------------------------------------------------------------------- /satpy/enhancements/viirs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) 2018-2019 Satpy developers 3 | # 4 | # This file is part of satpy. 5 | # 6 | # satpy is free software: you can redistribute it and/or modify it under the 7 | # terms of the GNU General Public License as published by the Free Software 8 | # Foundation, either version 3 of the License, or (at your option) any later 9 | # version. 10 | # 11 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 12 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License along with 16 | # satpy. If not, see . 17 | """Enhancements specific to the VIIRS instrument.""" 18 | import numpy as np 19 | from trollimage.colormap import Colormap 20 | 21 | from satpy.enhancements import exclude_alpha, using_map_blocks 22 | 23 | 24 | def water_detection(img, **kwargs): 25 | """Palettizes images from VIIRS flood data. 26 | 27 | This modifies the image's data so the correct colors 28 | can be applied to it, and then palettizes the image. 29 | """ 30 | palette = kwargs["palettes"] 31 | palette["colors"] = tuple(map(tuple, palette["colors"])) 32 | 33 | _water_detection(img.data) 34 | cm = Colormap(*palette["colors"]) 35 | img.palettize(cm) 36 | 37 | 38 | @exclude_alpha 39 | @using_map_blocks 40 | def _water_detection(img_data): 41 | data = np.asarray(img_data).copy() 42 | data[data == 150] = 31 43 | data[data == 199] = 18 44 | data[data >= 200] = data[data >= 200] - 100 45 | 46 | return data 47 | -------------------------------------------------------------------------------- /satpy/etc/composites/amsr2.yaml: -------------------------------------------------------------------------------- 1 | sensor_name: amsr2 2 | 3 | composites: 4 | rgb_color: 5 | compositor: !!python/name:satpy.composites.RGBCompositor 6 | prerequisites: 7 | - name: 'btemp_10.7h' 8 | - name: 'btemp_36.5h' 9 | - name: 'btemp_89.0ah' 10 | -------------------------------------------------------------------------------- /satpy/etc/composites/atms.yaml: -------------------------------------------------------------------------------- 1 | sensor_name: atms 2 | 3 | composites: 4 | mw183_humidity: 5 | compositor: !!python/name:satpy.composites.RGBCompositor 6 | prerequisites: 7 | - name: '22' 8 | - name: '20' 9 | - name: '18' 10 | standard_name: mw183_humidity 11 | 12 | mw183_humidity_surface: 13 | compositor: !!python/name:satpy.composites.RGBCompositor 14 | prerequisites: 15 | - name: '16' 16 | - name: '17' 17 | - name: '22' 18 | standard_name: mw183_humidity_surface 19 | -------------------------------------------------------------------------------- /satpy/etc/composites/avhrr-3.yaml: -------------------------------------------------------------------------------- 1 | sensor_name: visir/avhrr-3 2 | 3 | composites: 4 | 5 | nwc_pps_ct_masked_ir: 6 | compositor: !!python/name:satpy.composites.MaskingCompositor 7 | prerequisites: 8 | - 10.8 9 | - ct 10 | standard_name: nwc_pps_ct_masked_ir 11 | # Default is opaque (transparency = 0) 12 | conditions: 13 | - method: equal 14 | value: Cloud-free_land 15 | transparency: 100 16 | - method: equal 17 | value: Cloud-free_sea 18 | transparency: 100 19 | - method: equal 20 | value: Snow_over_land 21 | transparency: 100 22 | - method: equal 23 | value: Sea_ice 24 | transparency: 100 25 | - method: equal 26 | value: Fractional_clouds 27 | transparency: 45 28 | -------------------------------------------------------------------------------- /satpy/etc/composites/ec_msi.yaml: -------------------------------------------------------------------------------- 1 | sensor_name: visir/ec_msi 2 | 3 | 4 | modifiers: 5 | sunz_corrected: 6 | modifier: !!python/name:satpy.modifiers.SunZenithCorrector 7 | 8 | rayleigh_corrected: 9 | modifier: !!python/name:satpy.modifiers.PSPRayleighReflectance 10 | atmosphere: us-standard 11 | aerosol_type: rayleigh_only 12 | prerequisites: 13 | - name: VIS 14 | modifiers: [sunz_corrected] 15 | optional_prerequisites: 16 | - satellite_azimuth_angle 17 | - satellite_zenith_angle 18 | - solar_azimuth_angle 19 | - solar_zenith_angle 20 | 21 | composites: 22 | natural_color_nocorr: 23 | compositor: !!python/name:satpy.composites.GenericCompositor 24 | prerequisites: 25 | - SWIR1 26 | - NIR 27 | - VIS 28 | standard_name: natural_color 29 | 30 | natural_color: 31 | compositor: !!python/name:satpy.composites.GenericCompositor 32 | prerequisites: 33 | - name: SWIR1 34 | modifiers: [sunz_corrected] 35 | - name: NIR 36 | modifiers: [sunz_corrected] 37 | - name: VIS 38 | modifiers: [sunz_corrected] 39 | standard_name: natural_color 40 | -------------------------------------------------------------------------------- /satpy/etc/composites/epic.yaml: -------------------------------------------------------------------------------- 1 | sensor_name: visir/epic 2 | 3 | modifiers: 4 | sunz_corrected: 5 | modifier: !!python/name:satpy.modifiers.SunZenithCorrector 6 | optional_prerequisites: 7 | - solar_zenith_angle 8 | 9 | rayleigh_corrected: 10 | modifier: !!python/name:satpy.modifiers.PSPRayleighReflectance 11 | atmosphere: us-standard 12 | aerosol_type: rayleigh_only 13 | prerequisites: 14 | - name: B680 15 | modifiers: [sunz_corrected] 16 | optional_prerequisites: 17 | - satellite_azimuth_angle 18 | - satellite_zenith_angle 19 | - solar_azimuth_angle 20 | - solar_zenith_angle 21 | 22 | composites: 23 | true_color: 24 | compositor: !!python/name:satpy.composites.GenericCompositor 25 | prerequisites: 26 | - name: B680 27 | modifiers: [sunz_corrected, rayleigh_corrected] 28 | - name: B551 29 | modifiers: [sunz_corrected, rayleigh_corrected] 30 | - name: B443 31 | modifiers: [sunz_corrected, rayleigh_corrected] 32 | standard_name: true_color 33 | 34 | true_color_raw: 35 | compositor: !!python/name:satpy.composites.GenericCompositor 36 | prerequisites: 37 | - name: B680 38 | - name: B551 39 | - name: B443 40 | standard_name: true_color 41 | -------------------------------------------------------------------------------- /satpy/etc/composites/ghi.yaml: -------------------------------------------------------------------------------- 1 | sensor_name: visir/ghi 2 | 3 | composites: 4 | true_color: 5 | compositor: !!python/name:satpy.composites.SelfSharpenedRGB 6 | prerequisites: 7 | - name: C04 8 | modifiers: [sunz_corrected, rayleigh_corrected] 9 | - name: C03 10 | modifiers: [sunz_corrected, rayleigh_corrected] 11 | - name: C02 12 | modifiers: [sunz_corrected, rayleigh_corrected] 13 | standard_name: true_color 14 | 15 | true_color_nocorr: 16 | compositor: !!python/name:satpy.composites.SelfSharpenedRGB 17 | prerequisites: 18 | - name: C04 19 | - name: C03 20 | - name: C02 21 | standard_name: true_color 22 | -------------------------------------------------------------------------------- /satpy/etc/composites/glm.yaml: -------------------------------------------------------------------------------- 1 | sensor_name: visir/glm 2 | composites: 3 | C14_flash_extent_density: 4 | compositor: !!python/name:satpy.composites.BackgroundCompositor 5 | standard_name: c14_flash_extent_density 6 | prerequisites: 7 | - flash_extent_density 8 | - C14 9 | C14_yellow_lightning: 10 | compositor: !!python/name:satpy.composites.glm.HighlightCompositor 11 | standard_name: c14_yellow_lightning 12 | prerequisites: 13 | - flash_extent_density 14 | - highlight_C14 15 | -------------------------------------------------------------------------------- /satpy/etc/composites/goes_imager.yaml: -------------------------------------------------------------------------------- 1 | # XXX arb 2 | sensor_name: visir/goes_imager 3 | 4 | composites: 5 | overview: 6 | compositor: !!python/name:satpy.composites.GenericCompositor 7 | prerequisites: 8 | - '00_7' 9 | - '00_7' 10 | - '10_7' 11 | standard_name: overview 12 | -------------------------------------------------------------------------------- /satpy/etc/composites/hsaf.yaml: -------------------------------------------------------------------------------- 1 | sensor_name: hsaf 2 | 3 | composites: 4 | instantaneous_rainrate_3: 5 | compositor: !!python/name:satpy.composites.GenericCompositor 6 | prerequisites: 7 | - name: h03 8 | standard_name: instantaneous_rainrate_3 9 | instantaneous_rainrate_3b: 10 | compositor: !!python/name:satpy.composites.GenericCompositor 11 | prerequisites: 12 | - name: h03B 13 | standard_name: instantaneous_rainrate_3b 14 | accum_rainrate_5: 15 | compositor: !!python/name:satpy.composites.GenericCompositor 16 | prerequisites: 17 | - name: h05 18 | standard_name: accum_rainrate_5 19 | accum_rainrate_5b: 20 | compositor: !!python/name:satpy.composites.GenericCompositor 21 | prerequisites: 22 | - name: h05B 23 | standard_name: accum_rainrate_5b 24 | -------------------------------------------------------------------------------- /satpy/etc/composites/insat3d_img.yaml: -------------------------------------------------------------------------------- 1 | sensor_name: visir/insat_img 2 | 3 | composites: 4 | cloud_phase_distinction: 5 | description: > 6 | Day Cloud Phase Distinction RGB, for GOESR: NASA, NOAA 7 | Cloud Type RGB, for EUMETSAT (https://www.eumetsat.int/website/home/Images/ImageLibrary/DAT_3958037.html) 8 | references: 9 | CIRA Quick Guide: https://rammb.cira.colostate.edu/training/visit/quick_guides/QuickGuide_DayCloudPhaseDistinction_final_v2.pdf 10 | Cloud Type recipe and typical colours: https://www.eumetsat.int/fr/media/45659 11 | ## it uses the default used in etc/enhancements/generic.yaml 12 | compositor: !!python/name:satpy.composites.GenericCompositor 13 | prerequisites: 14 | - wavelength: 10.8 15 | - wavelength: 0.64 16 | modifiers: [ sunz_corrected, rayleigh_corrected ] 17 | - wavelength: 1.6 18 | modifiers: [ sunz_corrected ] 19 | standard_name: cloud_phase_distinction 20 | 21 | cloud_phase_distinction_raw: 22 | description: > 23 | same as cloud_phase_distinction 24 | compositor: !!python/name:satpy.composites.GenericCompositor 25 | prerequisites: 26 | - wavelength: 10.8 27 | - wavelength: 0.64 28 | - wavelength: 1.6 29 | standard_name: cloud_phase_distinction 30 | -------------------------------------------------------------------------------- /satpy/etc/composites/mersi-1.yaml: -------------------------------------------------------------------------------- 1 | sensor_name: visir/mersi-1 2 | 3 | modifiers: 4 | rayleigh_corrected: 5 | modifier: !!python/name:satpy.modifiers.PSPRayleighReflectance 6 | atmosphere: us-standard 7 | aerosol_type: rayleigh_only 8 | prerequisites: 9 | - name: '3' 10 | modifiers: [sunz_corrected] 11 | optional_prerequisites: 12 | - name: satellite_azimuth_angle 13 | - name: satellite_zenith_angle 14 | - name: solar_azimuth_angle 15 | - name: solar_zenith_angle 16 | 17 | sunz_corrected: 18 | modifier: !!python/name:satpy.modifiers.SunZenithCorrector 19 | prerequisites: 20 | - name: solar_zenith_angle 21 | 22 | nir_reflectance: 23 | modifier: !!python/name:satpy.modifiers.NIRReflectance 24 | prerequisites: 25 | - name: '24' 26 | optional_prerequisites: 27 | - solar_zenith_angle 28 | 29 | 30 | composites: 31 | colorized_ir: 32 | compositor: !!python/name:satpy.composites.SingleBandCompositor 33 | prerequisites: 34 | - name: '5' 35 | standard_name: colorized_ir_clouds 36 | 37 | true_color: 38 | compositor: !!python/name:satpy.composites.GenericCompositor 39 | prerequisites: 40 | - name: '3' 41 | modifiers: [sunz_corrected, rayleigh_corrected] 42 | - name: '2' 43 | modifiers: [sunz_corrected, rayleigh_corrected] 44 | - name: '1' 45 | modifiers: [sunz_corrected, rayleigh_corrected] 46 | standard_name: true_color 47 | 48 | true_color_uncorr: 49 | compositor: !!python/name:satpy.composites.GenericCompositor 50 | prerequisites: 51 | - name: '3' 52 | modifiers: [sunz_corrected] 53 | - name: '2' 54 | modifiers: [sunz_corrected] 55 | - name: '1' 56 | modifiers: [sunz_corrected] 57 | standard_name: true_color 58 | 59 | natural_color: 60 | compositor: !!python/name:satpy.composites.RatioSharpenedRGB 61 | prerequisites: 62 | - name: '6' 63 | modifiers: [sunz_corrected] 64 | - name: '16' 65 | modifiers: [sunz_corrected] 66 | - name: '3' 67 | modifiers: [sunz_corrected] 68 | optional_prerequisites: 69 | - name: '4' 70 | modifiers: [sunz_corrected] 71 | high_resolution_band: green 72 | neutral_resolution_band: blue 73 | standard_name: natural_color 74 | 75 | overview: 76 | compositor: !!python/name:satpy.composites.GenericCompositor 77 | prerequisites: 78 | - name: '3' 79 | modifiers: [sunz_corrected] 80 | - name: '4' 81 | modifiers: [sunz_corrected] 82 | - name: '5' 83 | standard_name: overview 84 | -------------------------------------------------------------------------------- /satpy/etc/composites/mersi-rm.yaml: -------------------------------------------------------------------------------- 1 | sensor_name: visir/mersi-rm 2 | 3 | modifiers: 4 | rayleigh_corrected: 5 | modifier: !!python/name:satpy.modifiers.PSPRayleighReflectance 6 | atmosphere: us-standard 7 | aerosol_type: rayleigh_only 8 | prerequisites: 9 | - name: '1' 10 | modifiers: [sunz_corrected] 11 | optional_prerequisites: 12 | - name: satellite_azimuth_angle 13 | - name: satellite_zenith_angle 14 | - name: solar_azimuth_angle 15 | - name: solar_zenith_angle 16 | sunz_corrected: 17 | modifier: !!python/name:satpy.modifiers.SunZenithCorrector 18 | prerequisites: 19 | - solar_zenith_angle 20 | 21 | nir_reflectance: 22 | modifier: !!python/name:satpy.modifiers.NIRReflectance 23 | prerequisites: 24 | - name: '7' 25 | optional_prerequisites: 26 | - solar_zenith_angle 27 | 28 | 29 | composites: 30 | natural_color: 31 | compositor: !!python/name:satpy.composites.RatioSharpenedRGB 32 | prerequisites: 33 | - name: '5' 34 | modifiers: [sunz_corrected] 35 | - name: '3' 36 | modifiers: [sunz_corrected] 37 | - name: '1' 38 | modifiers: [sunz_corrected] 39 | standard_name: natural_color 40 | 41 | overview_raw: 42 | compositor: !!python/name:satpy.composites.GenericCompositor 43 | prerequisites: 44 | - name: '1' 45 | - name: '2' 46 | - name: '7' 47 | standard_name: overview 48 | 49 | overview: 50 | compositor: !!python/name:satpy.composites.GenericCompositor 51 | prerequisites: 52 | - name: '1' 53 | modifiers: [sunz_corrected] 54 | - name: '2' 55 | modifiers: [sunz_corrected] 56 | - name: '7' 57 | standard_name: overview 58 | 59 | cloudtop: 60 | compositor: !!python/name:satpy.composites.GenericCompositor 61 | prerequisites: 62 | - name: '7' 63 | - name: '8' 64 | - name: '9' 65 | standard_name: cloudtop 66 | 67 | day_microphysics: 68 | compositor: !!python/name:satpy.composites.GenericCompositor 69 | prerequisites: 70 | - name: '2' 71 | modifiers: [sunz_corrected] 72 | - name: '7' 73 | modifiers: [nir_reflectance] 74 | - name: '8' 75 | standard_name: day_microphysics 76 | 77 | night_fog: 78 | compositor: !!python/name:satpy.composites.GenericCompositor 79 | prerequisites: 80 | - compositor: !!python/name:satpy.composites.DifferenceCompositor 81 | prerequisites: 82 | - name: '8' 83 | - name: '7' 84 | - compositor: !!python/name:satpy.composites.DifferenceCompositor 85 | prerequisites: 86 | - name: '7' 87 | - name: '6' 88 | - name: '7' 89 | standard_name: night_fog 90 | -------------------------------------------------------------------------------- /satpy/etc/composites/mhs.yaml: -------------------------------------------------------------------------------- 1 | sensor_name: mhs 2 | 3 | composites: 4 | mw183_humidity: 5 | compositor: !!python/name:satpy.composites.RGBCompositor 6 | prerequisites: 7 | - name: '3' 8 | - name: '4' 9 | - name: '5' 10 | standard_name: mw183_humidity 11 | 12 | mw183_humidity_surface: 13 | compositor: !!python/name:satpy.composites.RGBCompositor 14 | prerequisites: 15 | - name: '1' 16 | - name: '2' 17 | - name: '3' 18 | standard_name: mw183_humidity_surface 19 | -------------------------------------------------------------------------------- /satpy/etc/composites/microwave.yaml: -------------------------------------------------------------------------------- 1 | sensor_name: microwave 2 | -------------------------------------------------------------------------------- /satpy/etc/composites/msu-gs.yaml: -------------------------------------------------------------------------------- 1 | sensor_name: visir/msu-gs 2 | 3 | composites: 4 | overview_raw: 5 | compositor: !!python/name:satpy.composites.RGBCompositor 6 | prerequisites: 7 | - 00_9 8 | - 00_9 9 | - 10.8 10 | standard_name: overview 11 | overview: 12 | compositor: !!python/name:satpy.composites.RGBCompositor 13 | prerequisites: 14 | - name: 00_9 15 | modifiers: [sunz_corrected] 16 | - name: 00_9 17 | modifiers: [sunz_corrected] 18 | - 10.8 19 | standard_name: overview 20 | -------------------------------------------------------------------------------- /satpy/etc/composites/msu_gsa.yaml: -------------------------------------------------------------------------------- 1 | sensor_name: visir/msu_gsa 2 | 3 | composites: 4 | overview_raw: 5 | compositor: !!python/name:satpy.composites.RGBCompositor 6 | prerequisites: 7 | - name: C01 8 | - name: C03 9 | - name: C09 10 | standard_name: overview 11 | overview: 12 | compositor: !!python/name:satpy.composites.RGBCompositor 13 | prerequisites: 14 | - name: C01 15 | modifiers: [sunz_corrected] 16 | - name: C03 17 | modifiers: [sunz_corrected] 18 | - name: C09 19 | standard_name: overview 20 | msugsa_color: 21 | compositor: !!python/name:satpy.composites.RGBCompositor 22 | prerequisites: 23 | - name: C03 24 | modifiers: [sunz_corrected] 25 | - name: C02 26 | modifiers: [sunz_corrected] 27 | - name: C01 28 | modifiers: [sunz_corrected] 29 | standard_name: natural_color 30 | msugsa_color_raw: 31 | compositor: !!python/name:satpy.composites.RGBCompositor 32 | prerequisites: 33 | - name: C03 34 | - name: C02 35 | - name: C01 36 | standard_name: natural_color 37 | 38 | night_ir_alpha: 39 | compositor: !!python/name:satpy.composites.GenericCompositor 40 | standard_name: night_ir_alpha 41 | prerequisites: 42 | - 3.8 43 | - 10.8 44 | - 11.9 45 | - 10.8 46 | 47 | day_color_with_night_ir: 48 | compositor: !!python/name:satpy.composites.DayNightCompositor 49 | standard_name: day_color_with_night_ir 50 | lim_low: 90.0 51 | lim_high: 100.0 52 | prerequisites: 53 | - msugsa_color_raw 54 | - night_ir_with_background 55 | 56 | day_color_with_night_ir_hires: 57 | compositor: !!python/name:satpy.composites.DayNightCompositor 58 | standard_name: day_color_with_night_ir 59 | lim_low: 90.0 60 | lim_high: 100.0 61 | prerequisites: 62 | - msugsa_color_raw 63 | - night_ir_with_background_hires 64 | 65 | night_ir_with_background: 66 | compositor: !!python/name:satpy.composites.BackgroundCompositor 67 | standard_name: night_ir_with_background 68 | prerequisites: 69 | - night_ir_alpha 70 | - _night_background 71 | 72 | night_ir_with_background_hires: 73 | compositor: !!python/name:satpy.composites.BackgroundCompositor 74 | standard_name: night_ir_with_background_hires 75 | prerequisites: 76 | - night_ir_alpha 77 | - _night_background_hires 78 | -------------------------------------------------------------------------------- /satpy/etc/composites/mwr.yaml: -------------------------------------------------------------------------------- 1 | sensor_name: microwave/mwr 2 | 3 | composites: 4 | mw183_humidity: 5 | standard_name: mw183_humidity 6 | compositor: !!python/name:satpy.composites.GenericCompositor 7 | prerequisites: 8 | - name: '11' 9 | - name: '13' 10 | - name: '15' 11 | 12 | mw183_humidity_surface: 13 | compositor: !!python/name:satpy.composites.RGBCompositor 14 | prerequisites: 15 | - name: '9' 16 | - name: '10' 17 | - name: '12' 18 | standard_name: mw_humidity_surface 19 | 20 | mw325_humidity_surface: 21 | compositor: !!python/name:satpy.composites.RGBCompositor 22 | prerequisites: 23 | - name: '9' 24 | - name: '10' 25 | - name: '19' 26 | standard_name: mw_humidity_surface 27 | 28 | mw325_humidity: 29 | compositor: !!python/name:satpy.composites.RGBCompositor 30 | prerequisites: 31 | - name: '16' 32 | - name: '18' 33 | - name: '19' 34 | standard_name: mw_humidity_surface 35 | 36 | ch1_tbs_colors: 37 | compositor: !!python/name:satpy.composites.SingleBandCompositor 38 | prerequisites: 39 | - name: '1' 40 | standard_name: tbs_colors 41 | 42 | ch10_tbs_colors: 43 | compositor: !!python/name:satpy.composites.SingleBandCompositor 44 | prerequisites: 45 | - name: '10' 46 | standard_name: tbs_colors 47 | -------------------------------------------------------------------------------- /satpy/etc/composites/oci.yaml: -------------------------------------------------------------------------------- 1 | sensor_name: visir/oci 2 | -------------------------------------------------------------------------------- /satpy/etc/composites/sar-c.yaml: -------------------------------------------------------------------------------- 1 | sensor_name: sar/sar-c 2 | -------------------------------------------------------------------------------- /satpy/etc/composites/scatterometer.yaml: -------------------------------------------------------------------------------- 1 | sensor_name: visir/scatterometer 2 | 3 | composites: 4 | scat_wind_speed: 5 | compositor: !!python/name:satpy.composites.GenericCompositor 6 | prerequisites: 7 | - name: wind_speed_selection 8 | standard_name: scat_wind_speed 9 | 10 | soil_moisture: 11 | compositor: !!python/name:satpy.composites.GenericCompositor 12 | prerequisites: 13 | - name: surface_soil_moisture 14 | standard_name: soil_moisture 15 | -------------------------------------------------------------------------------- /satpy/etc/composites/slstr.yaml: -------------------------------------------------------------------------------- 1 | sensor_name: visir/slstr 2 | composite_identification_keys: 3 | name: 4 | required: true 5 | resolution: 6 | transitive: true 7 | view: 8 | enum: 9 | - nadir 10 | - oblique 11 | transitive: true 12 | stripe: 13 | enum: 14 | - a 15 | - b 16 | - i 17 | 18 | modifiers: 19 | nir_reflectance: 20 | modifier: !!python/name:satpy.modifiers.NIRReflectance 21 | prerequisites: 22 | - S8 23 | optional_prerequisites: 24 | - solar_zenith_angle 25 | - 13.4 26 | sunz_threshold: 85.0 27 | 28 | composites: 29 | 30 | overview: 31 | compositor: !!python/name:satpy.composites.GenericCompositor 32 | prerequisites: 33 | - name: S2 34 | modifiers: [sunz_corrected] 35 | - name: S3 36 | modifiers: [sunz_corrected] 37 | - S8 38 | standard_name: overview 39 | 40 | natural_color: 41 | compositor: !!python/name:satpy.composites.GenericCompositor 42 | prerequisites: 43 | - name: S5 44 | modifiers: [sunz_corrected] 45 | - name: S3 46 | modifiers: [sunz_corrected] 47 | - name: S2 48 | modifiers: [sunz_corrected] 49 | standard_name: natural_color 50 | 51 | day_microphysics: 52 | compositor: !!python/name:satpy.composites.GenericCompositor 53 | prerequisites: 54 | - name: S3 55 | modifiers: [sunz_corrected] 56 | - name: S7 57 | modifiers: [nir_reflectance] 58 | - S8 59 | standard_name: day_microphysics 60 | -------------------------------------------------------------------------------- /satpy/etc/composites/tropomi.yaml: -------------------------------------------------------------------------------- 1 | sensor_name: tropomi 2 | 3 | composites: 4 | 5 | no2_tropospheric_clean: 6 | compositor: !!python/name:satpy.composites.GenericCompositor 7 | prerequisites: 8 | - nitrogendioxide_tropospheric_column 9 | standard_name: no2_tropospheric_clean 10 | 11 | no2_tropospheric_polluted: 12 | compositor: !!python/name:satpy.composites.GenericCompositor 13 | prerequisites: 14 | - nitrogendioxide_tropospheric_column 15 | standard_name: no2_tropospheric_polluted 16 | -------------------------------------------------------------------------------- /satpy/etc/composites/virr.yaml: -------------------------------------------------------------------------------- 1 | sensor_name: visir/virr 2 | 3 | modifiers: 4 | sunz_corrected: 5 | modifier: !!python/name:satpy.modifiers.SunZenithCorrector 6 | prerequisites: 7 | - name: solar_zenith_angle 8 | 9 | rayleigh_corrected: 10 | modifier: !!python/name:satpy.modifiers.PSPRayleighReflectance 11 | atmosphere: us-standard 12 | aerosol_type: rayleigh_only 13 | prerequisites: 14 | - name: '1' 15 | modifiers: [sunz_corrected] 16 | optional_prerequisites: 17 | - name: satellite_azimuth_angle 18 | - name: satellite_zenith_angle 19 | - name: solar_azimuth_angle 20 | - name: solar_zenith_angle 21 | 22 | composites: 23 | true_color_raw: 24 | compositor: !!python/name:satpy.composites.GenericCompositor 25 | prerequisites: 26 | - name: '1' 27 | modifiers: [sunz_corrected] 28 | - name: '9' 29 | modifiers: [sunz_corrected] 30 | - name: '7' 31 | modifiers: [sunz_corrected] 32 | standard_name: true_color 33 | 34 | true_color: 35 | compositor: !!python/name:satpy.composites.GenericCompositor 36 | prerequisites: 37 | - name: '1' 38 | modifiers: [sunz_corrected, rayleigh_corrected] 39 | - name: '9' 40 | modifiers: [sunz_corrected, rayleigh_corrected] 41 | - name: '7' 42 | modifiers: [sunz_corrected, rayleigh_corrected] 43 | standard_name: true_color 44 | -------------------------------------------------------------------------------- /satpy/etc/enhancements/ahi.yaml: -------------------------------------------------------------------------------- 1 | enhancements: 2 | airmass: 3 | # matches ABI 4 | standard_name: airmass 5 | operations: 6 | - name: stretch 7 | method: !!python/name:satpy.enhancements.stretch 8 | kwargs: 9 | stretch: crude 10 | min_stretch: [-26.2, -43.2, 243.9] 11 | max_stretch: [0.6, 6.7, 208.5] 12 | 13 | day_severe_storms: 14 | standard_name: day_severe_storms 15 | sensor: ahi 16 | operations: 17 | - name: stretch 18 | method: !!python/name:satpy.enhancements.stretch 19 | kwargs: 20 | stretch: crude 21 | min_stretch: [-36, -1, -80] 22 | max_stretch: [5, 61, 26] 23 | - name: gamma 24 | method: !!python/name:satpy.enhancements.gamma 25 | kwargs: 26 | gamma: [1.0, 0.5, 0.95] 27 | 28 | night_microphysics_tropical: 29 | standard_name: night_microphysics_tropical 30 | sensor: ahi 31 | operations: 32 | - name: stretch 33 | method: !!python/name:satpy.enhancements.stretch 34 | kwargs: 35 | stretch: crude 36 | min_stretch: [-7.1, -2.9, 273] 37 | max_stretch: [ 2.4, 1.1, 300] 38 | - name: gamma 39 | method: !!python/name:satpy.enhancements.gamma 40 | kwargs: 41 | gamma: [1.0, 1.0, 1.0] 42 | -------------------------------------------------------------------------------- /satpy/etc/enhancements/atms.yaml: -------------------------------------------------------------------------------- 1 | enhancements: 2 | 3 | mw183_humidity: 4 | standard_name: mw183_humidity 5 | operations: 6 | - name: stretch 7 | method: !!python/name:satpy.enhancements.stretch 8 | kwargs: 9 | stretch: crude 10 | min_stretch: [255.0, 255.0, 255.0] 11 | max_stretch: [230.0, 230.0, 240.0] 12 | - name: gamma 13 | method: !!python/name:satpy.enhancements.gamma 14 | kwargs: {gamma: 1.2} 15 | 16 | mw183_humidity_surface: 17 | standard_name: mw183_humidity_surface 18 | operations: 19 | - name: stretch 20 | method: !!python/name:satpy.enhancements.stretch 21 | kwargs: 22 | stretch: crude 23 | min_stretch: [260.0, 260.0, 255.0] 24 | max_stretch: [180.0, 200.0, 230.0] 25 | - name: gamma 26 | method: !!python/name:satpy.enhancements.gamma 27 | kwargs: {gamma: 1.2} 28 | -------------------------------------------------------------------------------- /satpy/etc/enhancements/epic.yaml: -------------------------------------------------------------------------------- 1 | enhancements: 2 | true_color: 3 | standard_name: true_color 4 | operations: 5 | - name: stretch 6 | method: !!python/name:satpy.enhancements.stretch 7 | kwargs: 8 | stretch: crude 9 | min_stretch: [0, 0, 0] 10 | max_stretch: [100, 100, 100] 11 | -------------------------------------------------------------------------------- /satpy/etc/enhancements/glm.yaml: -------------------------------------------------------------------------------- 1 | enhancements: 2 | flash_extent_density: 3 | name: flash_extent_density 4 | operations: 5 | - name: colorize 6 | method: !!python/name:satpy.enhancements.colorize 7 | kwargs: 8 | palettes: 9 | - {colors: ylorrd, min_value: 0, max_value: 20} 10 | # Requires C14 from ABI 11 | c14_flash_extent_density: 12 | standard_name: c14_flash_extent_density 13 | operations: 14 | - name: stretch 15 | method: !!python/name:satpy.enhancements.stretch 16 | kwargs: 17 | stretch: crude 18 | min_stretch: [0, 0, 0] 19 | max_stretch: [1, 1, 1] 20 | c14_yellow_lightning: 21 | standard_name: c14_yellow_lightning 22 | operations: 23 | - name: stretch 24 | method: !!python/name:satpy.enhancements.stretch 25 | kwargs: 26 | stretch: crude 27 | min_stretch: [0, 0, 0, 0] 28 | max_stretch: [1, 1, 1, 1] 29 | -------------------------------------------------------------------------------- /satpy/etc/enhancements/mersi-2.yaml: -------------------------------------------------------------------------------- 1 | enhancements: 2 | default: 3 | operations: 4 | - name: stretch 5 | method: !!python/name:satpy.enhancements.stretch 6 | kwargs: {stretch: linear} 7 | 8 | cloudtop_default: 9 | standard_name: cloudtop 10 | operations: 11 | - name: stretch 12 | method: !!python/name:satpy.enhancements.stretch 13 | kwargs: 14 | stretch: crude 15 | min_stretch: [320, 310, 310] 16 | max_stretch: [220, 220, 220] 17 | - name: gamma 18 | method: !!python/name:satpy.enhancements.gamma 19 | kwargs: 20 | gamma: [1.4, 1.4, 1.2] 21 | -------------------------------------------------------------------------------- /satpy/etc/enhancements/mhs.yaml: -------------------------------------------------------------------------------- 1 | enhancements: 2 | 3 | mw183_humidity: 4 | standard_name: mw183_humidity 5 | operations: 6 | - name: inverse 7 | method: !!python/name:satpy.enhancements.invert 8 | args: 9 | - [true, true, true] 10 | - name: stretch 11 | method: !!python/name:satpy.enhancements.stretch 12 | kwargs: {stretch: linear} 13 | - name: gamma 14 | method: !!python/name:satpy.enhancements.gamma 15 | kwargs: {gamma: 1.2} 16 | 17 | mw183_humidity_surface: 18 | standard_name: mw183_humidity_surface 19 | operations: 20 | - name: inverse 21 | method: !!python/name:satpy.enhancements.invert 22 | args: 23 | - [true, true, true] 24 | - name: stretch 25 | method: !!python/name:satpy.enhancements.stretch 26 | kwargs: {stretch: linear} 27 | - name: gamma 28 | method: !!python/name:satpy.enhancements.gamma 29 | kwargs: {gamma: 1.2} 30 | -------------------------------------------------------------------------------- /satpy/etc/enhancements/mwr.yaml: -------------------------------------------------------------------------------- 1 | enhancements: 2 | 3 | mw_humidity_surface: 4 | standard_name: mw_humidity_surface 5 | operations: 6 | - name: inverse 7 | method: !!python/name:satpy.enhancements.invert 8 | args: 9 | - [true, true, true] 10 | - name: stretch 11 | method: !!python/name:satpy.enhancements.stretch 12 | kwargs: {stretch: linear} 13 | - name: gamma 14 | method: !!python/name:satpy.enhancements.gamma 15 | kwargs: {gamma: 1.2} 16 | 17 | tbs_colors: 18 | standard_name: tbs_colors 19 | operations: 20 | - name: colorize 21 | method: !!python/name:satpy.enhancements.colorize 22 | kwargs: 23 | palettes: 24 | - {colors: spectral, min_value: 280, max_value: 180} 25 | -------------------------------------------------------------------------------- /satpy/etc/enhancements/olci.yaml: -------------------------------------------------------------------------------- 1 | enhancements: 2 | mask: 3 | name: mask 4 | operations: [] 5 | -------------------------------------------------------------------------------- /satpy/etc/enhancements/scatterometer.yaml: -------------------------------------------------------------------------------- 1 | enhancements: 2 | 3 | scat_wind_speed: 4 | name: scat_wind_speed 5 | operations: 6 | - name: colorize 7 | method: !!python/name:satpy.enhancements.colorize 8 | kwargs: 9 | palettes: 10 | - {colors: spectral, min_value: 0, max_value: 25} 11 | 12 | soil_moisture: 13 | standard_name: soil_moisture 14 | operations: 15 | - name: colorize 16 | method: !!python/name:satpy.enhancements.colorize 17 | kwargs: 18 | palettes: 19 | - {colors: rdbu, min_value: 0, max_value: 100} 20 | -------------------------------------------------------------------------------- /satpy/etc/enhancements/seviri.yaml: -------------------------------------------------------------------------------- 1 | enhancements: 2 | 3 | hrv: 4 | standard_name: hrv 5 | operations: 6 | - name: stretch 7 | method: !!python/name:satpy.enhancements.stretch 8 | kwargs: 9 | stretch: crude 10 | min_stretch: [0, ] 11 | max_stretch: [100, ] 12 | 13 | ir108: 14 | standard_name: ir108 15 | operations: 16 | - name: stretch 17 | method: !!python/name:satpy.enhancements.stretch 18 | kwargs: 19 | stretch: crude 20 | min_stretch: [300, ] 21 | max_stretch: [215, ] 22 | 23 | vis06_filled_hrv: 24 | standard_name: vis06_filled_hrv 25 | operations: 26 | - name: stretch 27 | method: !!python/name:satpy.enhancements.stretch 28 | kwargs: 29 | stretch: crude 30 | min_stretch: [0, ] 31 | max_stretch: [100, ] 32 | 33 | vis_with_ir: 34 | standard_name: vis_with_ir 35 | operations: 36 | - name: stretch 37 | method: !!python/name:satpy.enhancements.stretch 38 | kwargs: 39 | stretch: crude 40 | min_stretch: [0, ] 41 | max_stretch: [1, ] 42 | 43 | vis_with_ir_cloud_overlay: 44 | standard_name: vis_with_ir_cloud_overlay 45 | operations: 46 | - name: stretch 47 | method: !!python/name:satpy.enhancements.stretch 48 | kwargs: 49 | stretch: crude 50 | min_stretch: [0, 0] 51 | max_stretch: [1, 1] 52 | 53 | ct: 54 | standard_name: ct 55 | operations: 56 | - name: stretch 57 | method: !!python/name:satpy.enhancements.stretch 58 | kwargs: 59 | stretch: crude 60 | min_stretch: [0, ] 61 | max_stretch: [255, ] 62 | -------------------------------------------------------------------------------- /satpy/etc/enhancements/tropomi.yaml: -------------------------------------------------------------------------------- 1 | enhancements: 2 | 3 | no2_tropospheric_clean: 4 | standard_name: no2_tropospheric_clean 5 | operations: 6 | - name: colorize_no2_tropospheric_clean 7 | method: !!python/name:satpy.enhancements.colorize 8 | kwargs: 9 | palettes: 10 | # 0 to 50 10e-6 mol/m2 11 | - {colors: ylgnbu, min_value: 0.0, max_value: 0.00005, reverse: true} 12 | # 50 to 90 10e-6 mol/m2 13 | - {colors: ylorrd, min_value: 0.00005, max_value: 0.00009} 14 | 15 | no2_tropospheric_polluted: 16 | standard_name: no2_tropospheric_polluted 17 | operations: 18 | - name: colorize_no2_tropospheric_poulluted 19 | method: !!python/name:satpy.enhancements.colorize 20 | kwargs: 21 | palettes: 22 | # 0 to 120 10e-6 mol/m2 23 | - {colors: ylgnbu, min_value: 0.0, max_value: 0.00012, reverse: true} 24 | # 120 to 600 10e-6 mol/m2 25 | - {colors: ylorrd, min_value: 0.00012, max_value: 0.0006} 26 | -------------------------------------------------------------------------------- /satpy/etc/ninjo-cmd.yaml: -------------------------------------------------------------------------------- 1 | # sample config file holding NinJo Tiff metadata 2 | # to be passed to the convert_to_ninjotif.py script 3 | # as an alternative to the command line input 4 | chan_id : 662626 5 | sat_id : 1622 6 | data_cat : GPRN 7 | data_src : EUMETCAST 8 | area : nrEURO1km_NPOL_COALeqc 9 | ph_unit : CELSIUS 10 | -------------------------------------------------------------------------------- /satpy/etc/readers/acspo.yaml: -------------------------------------------------------------------------------- 1 | reader: 2 | name: acspo 3 | short_name: ACSPO SST 4 | long_name: NOAA Level 2 ACSPO SST data in netCDF4 format 5 | description: NOAA Level 2 Product (L2P) ACSPO SST File Reader 6 | status: Nominal 7 | supports_fsspec: false 8 | reader: !!python/name:satpy.readers.core.yaml_reader.FileYAMLReader 9 | sensors: [viirs,modis,avhrr] 10 | default_datasets: 11 | 12 | file_types: 13 | acspo_sst: 14 | file_reader: !!python/name:satpy.readers.acspo.ACSPOFileHandler 15 | file_patterns: ['{start_time:%Y%m%d%H%M%S}-{rdac:4s}-L2P_GHRSST-{dataset_name}-{sensor_id}-ACSPO_V{version}-v{gds_version}-fv{file_version}.nc'] 16 | 17 | datasets: 18 | longitude: 19 | name: longitude 20 | file_type: acspo_sst 21 | file_key: lon 22 | latitude: 23 | name: latitude 24 | file_type: acspo_sst 25 | file_key: lat 26 | sst: 27 | name: sst 28 | coordinates: [longitude, latitude] 29 | file_type: acspo_sst 30 | file_key: sea_surface_temperature 31 | cloud_clear: True 32 | satellite_zenith_angle: 33 | name: satellite_zenith_angle 34 | coordinates: [longitude, latitude] 35 | file_type: acspo_sst 36 | sea_ice_fraction: 37 | name: sea_ice_fraction 38 | coordinates: [longitude, latitude] 39 | file_type: acspo_sst 40 | wind_speed: 41 | name: wind_speed 42 | coordinates: [longitude, latitude] 43 | file_type: acspo_sst 44 | -------------------------------------------------------------------------------- /satpy/etc/readers/amsr2_l2.yaml: -------------------------------------------------------------------------------- 1 | reader: 2 | name: amsr2_l2 3 | short_name: AMSR2 Level 2 4 | long_name: GCOM-W1 AMSR2 Level 2 (HDF5) 5 | description: > 6 | HDF5 reader for GCOM-W1 AMSR2 Level 2 files from JAXA. See 7 | https://suzaku.eorc.jaxa.jp/GCOM_W/data/data_w_product-2.html for more 8 | information. 9 | status: Beta 10 | supports_fsspec: false 11 | reader: !!python/name:satpy.readers.core.yaml_reader.FileYAMLReader 12 | sensors: [amsr2] 13 | 14 | file_types: 15 | amsr2_l2_ssw: 16 | file_reader: !!python/name:satpy.readers.amsr2_l2.AMSR2L2FileHandler 17 | file_patterns: ['{platform_shortname:3s}{instrument_shortname:3s}_{start_time:%Y%m%d%H%M}_{path_number:3d}{orbit_direction:1s}_L2{process_kind:2s}SSW{resolution_id:1s}{dev_id:1s}{product_version:1s}{algorithm_version:3d}{parameter_version:3d}.h5'] 18 | 19 | datasets: 20 | longitude_ssw: 21 | name: longitude_ssw 22 | file_type: amsr2_l2_ssw 23 | standard_name: longitude 24 | resolution: 15000 25 | units: degrees_east 26 | file_key: 'Longitude of Observation Point' 27 | fill_value: -9999.0 28 | 29 | latitude_ssw: 30 | name: latitude_ssw 31 | file_type: amsr2_l2_ssw 32 | standard_name: latitude 33 | resolution: 15000 34 | units: degrees_north 35 | file_key: 'Latitude of Observation Point' 36 | fill_value: -9999.0 37 | 38 | #https://suzaku.eorc.jaxa.jp/GCOM_W/data/data_w_product-2.html 39 | ssw: 40 | name: ssw 41 | standard_name: wind_speed 42 | file_type: amsr2_l2_ssw 43 | file_key: 'Geophysical Data' 44 | fill_value: -32768 45 | resolution: 15000 46 | coordinates: 47 | - longitude_ssw 48 | - latitude_ssw 49 | -------------------------------------------------------------------------------- /satpy/etc/readers/ascat_l2_soilmoisture_bufr.yaml: -------------------------------------------------------------------------------- 1 | reader: 2 | name: ascat_l2_soilmoisture_bufr 3 | short_name: ASCAT L2 SOILMOISTURE BUFR 4 | long_name: METOP ASCAT Level 2 SOILMOISTURE BUFR 5 | description: > 6 | Reader for ASCAT L2 SOIL MOISUTRE FILES 7 | status: Defunct 8 | supports_fsspec: false 9 | sensors: [scatterometer] 10 | reader: !!python/name:satpy.readers.core.yaml_reader.FileYAMLReader 11 | default_datasets: 12 | 13 | file_types: 14 | ascat_l2_soilmoisture_bufr: 15 | file_reader: !!python/name:satpy.readers.ascat_l2_soilmoisture_bufr.AscatSoilMoistureBufr 16 | file_patterns: ["W_XX-EUMETSAT-{reception_location},SOUNDING+SATELLITE,{platform}+{instrument}_C_{header}_{start_time:%Y%m%d%H%M%S}_{perigee}_eps_o_{species}_ssm_l2.bin"] 17 | 18 | datasets: 19 | 20 | latitude: 21 | name: latitude 22 | file_type: ascat_l2_soilmoisture_bufr 23 | standard_name: latitude 24 | units: "degrees" 25 | resolution: 12000 26 | key: 'latitude' 27 | fill_value: -1.e+100 28 | 29 | longitude: 30 | name: longitude 31 | file_type: ascat_l2_soilmoisture_bufr 32 | standard_name: longitude 33 | units: "degrees" 34 | resolution: 12000 35 | key: 'longitude' 36 | fill_value: -1.e+100 37 | 38 | surface_soil_moisture: 39 | name: surface_soil_moisture 40 | file_type: ascat_l2_soilmoisture_bufr 41 | units: 'percent' 42 | coordinates: [longitude, latitude] 43 | key: surfaceSoilMoisture 44 | fill_value: -1.e+100 45 | sensor: scatterometer 46 | 47 | 48 | soil_moisture_quality: 49 | name: soil_moisture_quality 50 | file_type: ascat_l2_soilmoisture_bufr 51 | coordinates: [longitude, latitude] 52 | key: soilMoistureQuality 53 | fill_value: -1.e+100 54 | -------------------------------------------------------------------------------- /satpy/etc/readers/caliop_l2_cloud.yaml: -------------------------------------------------------------------------------- 1 | reader: 2 | name: caliop_l2_cloud 3 | short_name: CALIOP l2 4 | long_name: Callipso Caliop Level 2 Cloud Layer data (v3) in EOS-hdf4 format 5 | description: CALIOP Level 2 Cloud Layer Version 3 HDF4 reader 6 | status: Alpha 7 | supports_fsspec: false 8 | reader: !!python/name:satpy.readers.core.yaml_reader.FileYAMLReader 9 | default_datasets: [] 10 | sensors: [caliop] 11 | 12 | datasets: 13 | elevation: 14 | file_type: hdf4_caliop 15 | name: Lidar_Surface_Elevation 16 | resolution: 1000 17 | coordinates: [Longitude, Latitude] 18 | 19 | layer_top_altitude: 20 | file_type: hdf4_caliop 21 | name: Layer_Top_Altitude 22 | resolution: 1000 23 | coordinates: [Longitude, Latitude] 24 | units: km 25 | 26 | longitude: 27 | file_type: hdf4_caliop 28 | name: Longitude 29 | resolution: 1000 30 | standard_name: longitude 31 | units: degree 32 | 33 | latitude: 34 | file_type: hdf4_caliop 35 | name: Latitude 36 | resolution: 1000 37 | standard_name: latitude 38 | units: degree 39 | 40 | file_types: 41 | hdf4_caliop: 42 | file_patterns: 43 | - 'CAL_LID_L2_0{resolution:1s}kmCLay-ValStage1-V3-30.{start_time:%Y-%m-%dT%H-%M-%S}ZN.hdf' 44 | file_reader: !!python/name:satpy.readers.caliop_l2_cloud.HDF4BandReader 45 | -------------------------------------------------------------------------------- /satpy/etc/readers/clavrx.yaml: -------------------------------------------------------------------------------- 1 | reader: 2 | name: clavrx 3 | short_name: CLAVR-X 4 | long_name: The Clouds from AVHRR Extended (CLAVR-x) 5 | description: CLAVR-X Reader 6 | status: Nominal 7 | supports_fsspec: false 8 | reader: !!python/name:satpy.readers.core.yaml_reader.FileYAMLReader 9 | sensors: [viirs, modis, avhrr, ahi, abi] 10 | 11 | file_types: 12 | clavrx_hdf4: 13 | # clavrx_npp_d20170520_t2055235_e2056477_b28822.level2.hdf' 14 | # clavrx_H08_20180719_1300.level2.hdf 15 | file_reader: !!python/name:satpy.readers.clavrx.CLAVRXHDF4FileHandler 16 | file_patterns: 17 | - 'clavrx_{platform_shortname}_d{start_time:%Y%m%d_t%H%M%S%f}_e{end_time:%H%M%S%f}_b{orbit:5d}.level2.hdf' 18 | - 'clavrx_{platform_shortname}.{start_time:%y%j.%H%M}.{resolution:s}.level2.hdf' 19 | - 'clavrx_hrpt_{platform_shortname}_{start_time:%Y%m%d_%H%M}_{orbit}.level2.hdf' 20 | - 'clavrx_{platform_shortname}_{start_time:%Y%m%d_%H%M}.level2.hdf' 21 | - 'clavrx_OR_{sensor}-L1b-Rad{sector}-{mode}C{channel_number}_{platform_shortname}_s{start_time:%Y%j%H%M%S%f}.level2.hdf' 22 | clavrx_nc: 23 | # clavrx_OR_ABI-L1b-RadF-M6C01_G16_s20211101600189.level2.nc 24 | # clavrx_H08_20210322_0300_B01_FLDK_R.level2.nc 25 | file_reader: !!python/name:satpy.readers.clavrx.CLAVRXNetCDFFileHandler 26 | file_patterns: 27 | - 'clavrx_OR_{sensor}-L1b-Rad{sector}-{mode}C{channel_number}_{platform_shortname}_s{start_time:%Y%j%H%M%S%f}.level2.nc' 28 | - 'clavrx_{platform_shortname}_{start_time:%Y%m%d_%H%M}_B{channel_number}_{sector}_R.level2.nc' 29 | - 'clavrx_{platform_shortname}_{start_time:%Y%m%d_%H%M}_B{channel_number}_{sector}_DK_R{resolution}_S{segment}.DAT.level2.nc' 30 | 31 | #datasets: 32 | # longitude: 33 | # name: longitude 34 | # resolution: 0 35 | # file_type: level2 36 | # latitude: 37 | # name: latitude 38 | # resolution: 0 39 | # file_type: level2 40 | # # resolution come from file 41 | # cld_temp_acha: 42 | # name: Solar_Zenith 43 | # resolution: 0 44 | # coordinates: [longitude, latitude] 45 | # file_type: level2 46 | -------------------------------------------------------------------------------- /satpy/etc/readers/cmsaf-claas2_l2_nc.yaml: -------------------------------------------------------------------------------- 1 | reader: 2 | name: cmsaf-claas2_l2_nc 3 | short_name: CMSAF CLAAS-2 data 4 | long_name: CMSAF CLAAS-2 data for SEVIRI-derived cloud products 5 | description: > 6 | Reader for Spinning Enhanced Visible and Infrared Imager (SEVIRI) 7 | L2 data as produced by the Climate Monitoring Satellite Application 8 | Facility (CMSAF) in its CLoud property dAtAset using SEVIRI (CLAAS) 9 | dataset, edition 2, doi:10.5676/EUM_SAF_CM/CLAAS/V002. Information on 10 | CMSAF and its products can be found at https://www.cmsaf.eu/. 11 | status: Beta 12 | supports_fsspec: false 13 | sensors: [seviri] 14 | doi: doi:10.5676/EUM_SAF_CM/CLAAS/V002. 15 | default_channels: [] 16 | reader: !!python/name:satpy.readers.core.yaml_reader.FileYAMLReader 17 | 18 | # CMSAF naming convention: 19 | # https://www.cmsaf.eu/EN/Products/NamingConvention/Naming_Convention_node.html 20 | 21 | file_types: 22 | cmsaf-claas2: 23 | file_reader: !!python/name:satpy.readers.cmsaf_claas2.CLAAS2 24 | file_patterns: ['{product:3s}in{start_time:%Y%m%d%H%M}{version:>03d}05SVMSG{proc_level:2s}MD.nc'] 25 | -------------------------------------------------------------------------------- /satpy/etc/readers/fci_l2_grib.yaml: -------------------------------------------------------------------------------- 1 | reader: 2 | name: fci_l2_grib 3 | short_name: FCI L2 GRIB2 4 | long_name: MTG FCI L2 data in GRIB2 format 5 | description: Reader for EUMETSAT MTG FCI L2 files in GRIB2 format. 6 | status: Nominal 7 | supports_fsspec: false 8 | sensors: [fci] 9 | reader: !!python/name:satpy.readers.core.yaml_reader.GEOFlippableFileYAMLReader 10 | 11 | file_types: 12 | grib_fci_clm: 13 | file_reader: !!python/name:satpy.readers.eum_l2_grib.EUML2GribFileHandler 14 | file_patterns: 15 | - '{pflag}_{location_indicator},{data_designator},MTI{spacecraft_id:1d}+FCI-2-CLM-{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' 16 | 17 | 18 | datasets: 19 | cloud_mask: 20 | name: cloud_mask 21 | long_name: Cloud Classification 22 | standard_name: cloud_classification 23 | resolution: 2000 24 | file_type: grib_fci_clm 25 | parameter_number: 7 26 | units: "1" 27 | flag_values: [0, 1, 2, 3] 28 | flag_meanings: ['clear sky over water','clear sky over land', 'cloudy', 'undefined' ] 29 | -------------------------------------------------------------------------------- /satpy/etc/readers/generic_image.yaml: -------------------------------------------------------------------------------- 1 | reader: 2 | name: generic_image 3 | short_name: Generic Image 4 | long_name: Generic Images e.g. GeoTIFF 5 | description: generic image reader 6 | status: Nominal 7 | supports_fsspec: true 8 | reader: !!python/name:satpy.readers.core.yaml_reader.FileYAMLReader 9 | sensors: [images] 10 | default_channels: [image] 11 | 12 | datasets: 13 | image: 14 | name: image 15 | file_type: graphic 16 | 17 | file_types: 18 | graphic: 19 | file_reader: !!python/name:satpy.readers.generic_image.GenericImageFileHandler 20 | file_patterns: 21 | - '{start_time:%Y%m%d_%H%M}{filename}.png' 22 | - '{start_time:%Y%m%d_%H%M}{filename}.PNG' 23 | - '{start_time:%Y%m%d_%H%M}{filename}.jpg' 24 | - '{start_time:%Y%m%d_%H%M}{filename}.jpeg' 25 | - '{start_time:%Y%m%d_%H%M}{filename}.JPG' 26 | - '{start_time:%Y%m%d_%H%M}{filename}.JPEG' 27 | - '{start_time:%Y%m%d_%H%M}{filename}.tif' 28 | - '{start_time:%Y%m%d_%H%M}{filename}.tiff' 29 | - '{start_time:%Y%m%d_%H%M}{filename}.TIF' 30 | - '{start_time:%Y%m%d_%H%M}{filename}.TIFF' 31 | - '{filename}{start_time:%Y%m%d_%H%M}.png' 32 | - '{filename}{start_time:%Y%m%d_%H%M}.PNG' 33 | - '{filename}{start_time:%Y%m%d_%H%M}.jpg' 34 | - '{filename}{start_time:%Y%m%d_%H%M}.jpeg' 35 | - '{filename}{start_time:%Y%m%d_%H%M}.JPG' 36 | - '{filename}{start_time:%Y%m%d_%H%M}.JPEG' 37 | - '{filename}{start_time:%Y%m%d_%H%M}.tif' 38 | - '{filename}{start_time:%Y%m%d_%H%M}.tiff' 39 | - '{filename}{start_time:%Y%m%d_%H%M}.TIF' 40 | - '{filename}{start_time:%Y%m%d_%H%M}.TIFF' 41 | - '{filename}.png' 42 | - '{filename}.PNG' 43 | - '{filename}.jpg' 44 | - '{filename}.jpeg' 45 | - '{filename}.JPG' 46 | - '{filename}.JPEG' 47 | - '{filename}.tif' 48 | - '{filename}.tiff' 49 | - '{filename}.TIF' 50 | - '{filename}.TIFF' 51 | -------------------------------------------------------------------------------- /satpy/etc/readers/gerb_l2_hr_h5.yaml: -------------------------------------------------------------------------------- 1 | reader: 2 | name: gerb_l2_hr_h5 3 | short_name: GERB HR 4 | long_name: Meteosat Second Generation Geostationary Earth Radiation Budget L2 High-Resolution 5 | description: Reader for the HR product of the Geostationary Earth Radiation Budget instrument 6 | status: Beta 7 | supports_fsspec: false 8 | reader: !!python/name:satpy.readers.core.yaml_reader.FileYAMLReader 9 | sensors: [gerb] 10 | 11 | file_types: 12 | gerb_l2_hr_h5: 13 | file_reader: !!python/name:satpy.readers.gerb_l2_hr_h5.GERB_HR_FileHandler 14 | file_patterns: ['{sensor_name}_{seviri_name}_L20_HR_SOL_TH_{sensing_time:%Y%m%d_%H%M%S}_{gerb_version}.hdf'] 15 | 16 | datasets: 17 | Solar_Flux: 18 | name: Solar Flux 19 | sensor: gerb 20 | units: W m-2 21 | fill_value: -32767 22 | standard_name: toa_outgoing_shortwave_flux 23 | file_type: gerb_l2_hr_h5 24 | 25 | Thermal_Flux: 26 | name: Thermal Flux 27 | sensor: gerb 28 | units: W m-2 29 | fill_value: -32767 30 | standard_name: toa_outgoing_longwave_flux 31 | file_type: gerb_l2_hr_h5 32 | 33 | Solar_Radiance: 34 | name: Solar Radiance 35 | sensor: gerb 36 | units: W m-2 sr-1 37 | fill_value: -32767 38 | file_type: gerb_l2_hr_h5 39 | 40 | Thermal_Radiance: 41 | name: Thermal Radiance 42 | sensor: gerb 43 | units: W m-2 sr-1 44 | fill_value: -32767 45 | file_type: gerb_l2_hr_h5 46 | -------------------------------------------------------------------------------- /satpy/etc/readers/glm_l2.yaml: -------------------------------------------------------------------------------- 1 | reader: 2 | name: glm_l2 3 | short_name: GLM Level 2 4 | long_name: GOES-R GLM Level 2 5 | description: > 6 | NetCDF4 reader for GOES-R series GLM data. Currently only gridded L2 files 7 | output from `gltmtools `_ are 8 | supported. 9 | status: Beta 10 | supports_fsspec: false 11 | sensors: [glm] 12 | reader: !!python/name:satpy.readers.core.yaml_reader.FileYAMLReader 13 | # file pattern keys to sort files by with 'satpy.utils.group_files' 14 | group_keys: ['start_time', 'platform_shortname', 'scene_abbr'] 15 | 16 | # Typical filenames from Unidata THREDDS server: 17 | # http://thredds.unidata.ucar.edu/thredds/catalog/satellite/goes/east/ 18 | # products/GeostationaryLightningMapper/CONUS/current/catalog.html 19 | # OR_GLM-L2-GLMC-M3_G16_s20191920000000_e20191920001000_c20191920001380.nc 20 | 21 | file_types: 22 | glm_l2_imagery: 23 | file_reader: !!python/name:satpy.readers.glm_l2.NCGriddedGLML2 24 | file_patterns: ['{system_environment:s}_{mission_id:3s}-L2-GLM{scene_abbr:s}-{scan_mode:2s}_{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}.nc'] 25 | # glm_l2_lcfa - add this with glmtools 26 | 27 | datasets: 28 | # Additional datasets discovered dynamically in satpy/readers/glm_l2.py 29 | flash_extent_density: 30 | name: flash_extent_density 31 | file_type: glm_l2_imagery 32 | group_extent_density: 33 | name: group_extent_density 34 | file_type: glm_l2_imagery 35 | flash_centroid_density: 36 | name: flash_centroid_density 37 | file_type: glm_l2_imagery 38 | group_centroid_density: 39 | name: group_centroid_density 40 | file_type: glm_l2_imagery 41 | average_flash_area: 42 | name: average_flash_area 43 | file_type: glm_l2_imagery 44 | minimum_flash_area: 45 | name: minimum_flash_area 46 | file_type: glm_l2_imagery 47 | average_group_area: 48 | name: average_group_area 49 | file_type: glm_l2_imagery 50 | total_energy: 51 | name: total_energy 52 | file_type: glm_l2_imagery 53 | -------------------------------------------------------------------------------- /satpy/etc/readers/gpm_imerg.yaml: -------------------------------------------------------------------------------- 1 | reader: 2 | name: gpm_imerg 3 | short_name: GPM/IMERG l3 4 | long_name: GPM IMERG level 3 precipitation data in HDF5 format 5 | description: HDF5 reader for the GPM/IMERG data 6 | status: Nominal 7 | supports_fsspec: false 8 | sensors: [multiple] 9 | default_channels: [] 10 | reader: !!python/name:satpy.readers.core.yaml_reader.FileYAMLReader 11 | 12 | file_types: 13 | gpm_imerg_h5: 14 | file_reader: !!python/name:satpy.readers.gpm_imerg.Hdf5IMERG 15 | file_patterns: ['3B-HHR.MS.MRG.3IMERG.{date:%Y%m%d}-S{start_time:%H%M%S}-E{end_time:%H%M%S}.{sequence:4s}.{version_id:4s}.HDF5', 16 | '3B-HHR-E.MS.MRG.3IMERG.{date:%Y%m%d}-S{start_time:%H%M%S}-E{end_time:%H%M%S}.{sequence:4s}.{version_id:4s}.RT-H5', 17 | '3B-HHR-L.MS.MRG.3IMERG.{date:%Y%m%d}-S{start_time:%H%M%S}-E{end_time:%H%M%S}.{sequence:4s}.{version_id:4s}.RT-H5'] 18 | datasets: 19 | HQobservationTime: 20 | name: HQobservationTime 21 | resolution: 0.1 22 | file_type: gpm_imerg_h5 23 | units: minutes 24 | HQprecipitation: 25 | name: HQprecipitation 26 | resolution: 3000 27 | file_type: gpm_imerg_h5 28 | units: mm/hr 29 | HQprecipSource: 30 | name: HQprecipSource 31 | resolution: 0.1 32 | file_type: gpm_imerg_h5 33 | IRkalmanFilterWeight: 34 | name: IRkalmanFilterWeight 35 | resolution: 0.1 36 | file_type: gpm_imerg_h5 37 | IRprecipitation: 38 | name: IRprecipitation 39 | resolution: 0.1 40 | file_type: gpm_imerg_h5 41 | units: mm/hr 42 | precipitationCal: 43 | name: precipitationCal 44 | resolution: 0.1 45 | file_type: gpm_imerg_h5 46 | units: mm/hr 47 | precipitationQualityIndex: 48 | name: precipitationQualityIndex 49 | resolution: 0.1 50 | file_type: gpm_imerg_h5 51 | precipitationUncal: 52 | name: precipitationUncal 53 | resolution: 0.1 54 | file_type: gpm_imerg_h5 55 | units: mm/hr 56 | probabilityLiquidPrecipitation: 57 | name: probabilityLiquidPrecipitation 58 | resolution: 0.1 59 | file_type: gpm_imerg_h5 60 | units: "%" 61 | randomError: 62 | name: randomError 63 | resolution: 0.1 64 | file_type: gpm_imerg_h5 65 | units: mm/hr 66 | -------------------------------------------------------------------------------- /satpy/etc/readers/grib.yaml: -------------------------------------------------------------------------------- 1 | reader: 2 | name: grib 3 | short_name: GRIB2 4 | long_name: GRIB2 format 5 | description: GRIB2 file reader 6 | status: Beta 7 | supports_fsspec: false 8 | reader: !!python/name:satpy.readers.core.yaml_reader.FileYAMLReader 9 | sensors: [unknown] 10 | data_identification_keys: 11 | name: 12 | required: true 13 | level: 14 | resolution: 15 | modifiers: 16 | default: [] 17 | type: !!python/name:satpy.dataset.dataid.ModifierTuple 18 | 19 | file_types: 20 | grib: 21 | file_reader: !!python/name:satpy.readers.grib.GRIBFileHandler 22 | file_patterns: 23 | # NOAA NCEP: 24 | # gfs.t18z.sfluxgrbf106.grib2 25 | - '{stem}.grib2' 26 | - 'gfs{stem}.f{forecast_time:3d}' 27 | - 'gdas{stem}.f{forecast_time:3d}' 28 | # EUMETSAT: 29 | # S-OSI_-NOR_-MULT-AHLDLI_FIELD-201805011200Z.grb.gz 30 | - '{stem}.grb' 31 | - '{stem}.grb2' 32 | # NWCSAF input file name format: 33 | # S_NWC_NWP_2017-03-14T00:00:00Z_002.grib 34 | - 'S_NWC_NWP_{start_time:%Y-%m-%dT%H:%M:%S}Z_{forecast_time:3d}.grib' 35 | # grib_ncep: 36 | # file_reader: !!python/name:satpy.readers.grib.GRIBFileHandler 37 | # file_patterns: 38 | # # NOAA NCEP: 39 | # # gfs.t18z.sfluxgrbf106.grib2 40 | # - '{model_name}.t{model_hour:2d}z.{field_set}.grib2' 41 | # keys: 42 | # shortName: 43 | # id_key: name 44 | # values: ['gh', 't', 'u', 'v', 'r', 'icaht'] 45 | # level: 46 | # id_key: level 47 | # values: [0, 100, 125, 150, 175, 200, 225, 250, 275, 300, 350, 400, 450, 500, 600, 700, 750, 850] 48 | -------------------------------------------------------------------------------- /satpy/etc/readers/hsaf_grib.yaml: -------------------------------------------------------------------------------- 1 | reader: 2 | name: hsaf_grib 3 | short_name: Hydrology SAF 4 | long_name: Hydrology SAF products in GRIB format 5 | description: Reader for Hydrology SAF products 6 | status: Beta, only h03, h03b, h05 and h05b currently supported 7 | supports_fsspec: false 8 | reader: !!python/name:satpy.readers.core.yaml_reader.FileYAMLReader 9 | sensors: [hsaf] 10 | 11 | file_types: 12 | hsafgrib: 13 | file_reader: !!python/name:satpy.readers.hsaf_grib.HSAFFileHandler 14 | file_patterns: ['h03_{sensing_time:%Y%m%d_%H%M}_{region:3s}.grb', 15 | 'h05_{sensing_time:%Y%m%d_%H%M}_{accum_time:2s}_{region:3s}.grb', 16 | 'h03B_{sensing_time:%Y%m%d_%H%M}_{region:3s}.grb', 17 | 'S-HSAF-h03B_{sensing_time:%Y%m%d_%H%M}_{region:3s}.grb', 18 | 'h05B_{sensing_time:%Y%m%d_%H%M}_{accum_time:2s}_{region:3s}.grb', 19 | 'S-HSAF-h05B_{sensing_time:%Y%m%d_%H%M}_{accum_time:2s}_{region:3s}.grb'] 20 | datasets: 21 | h03: 22 | name: h03 23 | msg_name: irrate 24 | sensor: hsaf 25 | resolution: 3000 26 | standard_name: instantaneous_rainfall_rate 27 | units: kg m-2 s-1 28 | file_type: hsafgrib 29 | h03B: 30 | name: h03B 31 | msg_name: irrate 32 | sensor: hsaf 33 | resolution: 3000 34 | standard_name: instantaneous_rainfall_rate 35 | units: kg m-2 s-1 36 | file_type: hsafgrib 37 | h05: 38 | name: h05 39 | msg_name: accumrain 40 | sensor: hsaf 41 | resolution: 3000 42 | standard_name: accumulated_rainfall_rate 43 | units: kg m-2 44 | file_type: hsafgrib 45 | h05B: 46 | name: h05B 47 | msg_name: accumrain 48 | sensor: hsaf 49 | resolution: 3000 50 | standard_name: accumulated_rainfall_rate 51 | units: kg m-2 52 | file_type: hsafgrib 53 | -------------------------------------------------------------------------------- /satpy/etc/readers/hsaf_h5.yaml: -------------------------------------------------------------------------------- 1 | reader: 2 | name: hsaf_h5 3 | short_name: Hydrology SAF 4 | long_name: Hydrology SAF products in HDF5 format 5 | description: Reader for Hydrology SAF products 6 | status: Beta, only h10 currently supported 7 | supports_fsspec: false 8 | reader: !!python/name:satpy.readers.core.yaml_reader.FileYAMLReader 9 | sensors: [hsaf] 10 | 11 | file_types: 12 | hsafh5: 13 | file_reader: !!python/name:satpy.readers.hsaf_h5.HSAFFileHandler 14 | file_patterns: ['S-HSAF-h10_{sensing_time:%Y%m%d}_day_merged.H5', 15 | 'h10_{sensing_time:%Y%m%d}_day_merged.H5'] 16 | datasets: 17 | SC: 18 | name: SC 19 | sensor: hsaf 20 | resolution: 3000 21 | standard_name: seviri_snow_cover 22 | units: class 23 | file_type: hsafh5 24 | 25 | SC_pal: 26 | name: SC_pal 27 | resolution: 3000 28 | file_type: hsafh5 29 | -------------------------------------------------------------------------------- /satpy/etc/readers/iasi_l2_cdr_nc.yaml: -------------------------------------------------------------------------------- 1 | reader: 2 | name: iasi_l2_cdr_nc 3 | short_name: IASI l2 CDR 4 | long_name: IASI All Sky Temperature and Humidity Profiles - Climate Data Record Release 1.1 - Metop-A and -B 5 | description: > 6 | Reader for IASI All Sky Temperature and Humidity Profiles - Climate Data 7 | Record Release 1.1 - Metop-A and -B. Data and documentation are available 8 | from http://doi.org/10.15770/EUM_SEC_CLM_0063. Data are also available 9 | from the EUMETSAT Data Store under ID EO:EUM:DAT:0576. 10 | status: Alpha 11 | supports_fsspec: True 12 | reader: !!python/name:satpy.readers.core.yaml_reader.FileYAMLReader 13 | sensors: [iasi] 14 | default_datasets: 15 | 16 | file_types: 17 | iasi_l2_cdr_nc: 18 | file_reader: !!python/name:satpy.readers.iasi_l2.IASIL2CDRNC 19 | # see https://www.eumetsat.int/media/49059 §4.8 for file pattern 20 | file_patterns: ["W_XX-EUMETSAT-Darmstadt,{sounding_method},{satellite}+{product}+{instrument}_C_{originator}_{start_time:%Y%m%d%H%M%S}Z_{end_time:%Y%m%d%H%M%S}Z_eps_r_l2_{version}.nc"] 21 | -------------------------------------------------------------------------------- /satpy/etc/readers/iasi_ng_l2_nc.yaml: -------------------------------------------------------------------------------- 1 | reader: 2 | name: iasi_ng_l2_nc 3 | short_name: IASI-NG L2 NC Reader 4 | long_name: IASI-NG Level-2 NetCDF Reader 5 | description: Reader for IASI-NG Level-2 NetCDF files 6 | sensors: [iasi] 7 | reader: !!python/name:satpy.readers.core.yaml_reader.FileYAMLReader 8 | status: Alpha 9 | supports_fsspec: false 10 | 11 | file_types: 12 | iasi_ng_l2_nc: 13 | file_reader: !!python/name:satpy.readers.iasi_ng_l2_nc.IASINGL2NCFileHandler 14 | file_patterns: 15 | [ 16 | "{pflag}_{country}-{organization}-{location},{data_designator},{spacecraft}-{instrument}-{processing_level}-{product_type:3s}_{oflag}_{originator}_{generation_time}_{mission_type}_{environment}_{sensing_start_time:%Y%m%d%H%M%S}_{sensing_end_time:%Y%m%d%H%M%S}_{disposition_mode}_{processing_mode}_{free_text1}_{free_text2}_{free_text3}_{extension}.nc", 17 | ] 18 | 19 | # keeping optimal_estimation folder for the moment due to feature freeze, 20 | # but it might be necessary to re-introduce this in a near future. 21 | # So keeping this reference entry here for now. 22 | # ignored_patterns: 23 | # - /optimal_estimation/ # cf. eum respase2 task2 issue #4 24 | 25 | dataset_aliases: 26 | "/optimal_estimation/(.+)$": "${VAR_NAME}_oem" 27 | -------------------------------------------------------------------------------- /satpy/etc/readers/mcd12q1.yaml: -------------------------------------------------------------------------------- 1 | reader: 2 | name: mcd12q1 3 | short_name: MCD12Q1 4 | long_name: MODIS Level 3 (mcd12Q1) data in HDF-EOS format 5 | description: MODIS HDF-EOS MCD12Q1 L3 Reader 6 | status: Beta 7 | supports_fsspec: false 8 | reader: !!python/name:satpy.readers.core.yaml_reader.FileYAMLReader 9 | sensors: [modis] 10 | 11 | file_types: 12 | modis_mcd12q1_hdf_eos: 13 | file_patterns: ['MCD12Q1.A{start_time:%Y%j}.{tile_id}.{collection:03d}.{production_time:%Y%j%H%M%S}.hdf'] 14 | file_reader: !!python/name:satpy.readers.mcd12q1.MCD12Q1HDFFileHandler 15 | 16 | datasets: 17 | LC_Type1: 18 | name: LC_Type1 19 | resolution: 500 20 | file_type: modis_mcd12q1_hdf_eos 21 | 22 | LC_Type2: 23 | name: LC_Type2 24 | resolution: 500 25 | file_type: modis_mcd12q1_hdf_eos 26 | LC_Type3: 27 | name: LC_Type3 28 | resolution: 500 29 | file_type: modis_mcd12q1_hdf_eos 30 | LC_Type4: 31 | name: LC_Type4 32 | resolution: 500 33 | file_type: modis_mcd12q1_hdf_eos 34 | LC_Type5: 35 | name: LC_Type5 36 | resolution: 500 37 | file_type: modis_mcd12q1_hdf_eos 38 | LC_Prop1: 39 | name: LC_Prop1 40 | resolution: 500 41 | file_type: modis_mcd12q1_hdf_eos 42 | LC_Prop2: 43 | name: LC_Prop2 44 | resolution: 500 45 | file_type: modis_mcd12q1_hdf_eos 46 | LC_Prop3: 47 | name: LC_Prop3 48 | resolution: 500 49 | file_type: modis_mcd12q1_hdf_eos 50 | -------------------------------------------------------------------------------- /satpy/etc/readers/mimicTPW2_comp.yaml: -------------------------------------------------------------------------------- 1 | reader: 2 | name: mimicTPW2_comp 3 | short_name: MIMIC TPW v2 4 | long_name: MIMIC Total Precipitable Water Product Reader in netCDF format 5 | description: NetCDF4 reader for the MIMIC TPW Version 2.0 product 6 | status: Beta 7 | supports_fsspec: false 8 | sensors: [mimic] 9 | reader: !!python/name:satpy.readers.core.yaml_reader.FileYAMLReader 10 | 11 | file_types: 12 | mimicTPW2_comp: 13 | file_reader: !!python/name:satpy.readers.mimic_TPW2_nc.MimicTPW2FileHandler 14 | file_patterns: ['comp{start_time:%Y%m%d.%H%M%S}.nc'] 15 | sensor: ['mimic'] 16 | platform_name: ['microwave'] 17 | -------------------------------------------------------------------------------- /satpy/etc/readers/modis_l3.yaml: -------------------------------------------------------------------------------- 1 | reader: 2 | name: modis_l3 3 | short_name: MODIS l3 4 | long_name: MODIS Level 3 (mcd43) data in HDF-EOS format 5 | description: MODIS HDF-EOS L3 Reader 6 | status: Beta 7 | supports_fsspec: false 8 | reader: !!python/name:satpy.readers.core.yaml_reader.FileYAMLReader 9 | sensors: [modis] 10 | 11 | file_types: 12 | modis_l3_cmg_hdf: 13 | file_patterns: 14 | - 'MCD43C{prod_type}.A{start_time:%Y%j}.{collection:03d}.{production_time:%Y%j%H%M%S}.hdf' 15 | - 'M{platform_indicator:1s}D09CMG.A{start_time:%Y%j}.{collection:03d}.{production_time:%Y%j%H%M%S}.hdf' 16 | file_reader: !!python/name:satpy.readers.modis_l3.ModisL3GriddedHDFFileHandler 17 | -------------------------------------------------------------------------------- /satpy/etc/readers/oci_l2_bgc.yaml: -------------------------------------------------------------------------------- 1 | reader: 2 | name: oci_l2_bgc 3 | short_name: PACE OCI L2 BGC 4 | long_name: PACE OCI L2 Biogeochemical in NetCDF format 5 | description: PACE OCI L2 Biogeochemical Reader 6 | status: Beta 7 | supports_fsspec: false 8 | reader: !!python/name:satpy.readers.core.yaml_reader.FileYAMLReader 9 | sensors: [oci] 10 | 11 | file_types: 12 | bgc_nc: 13 | file_patterns: 14 | # Example: PACE_OCI.20240907T191809.L2.OC_BGC.V2_0.NRT.nc4 15 | - '{platform:s}_{sensor:s}.{start_time:%Y%m%dT%H%M%S}.L2.OC_BGC.V{sw_version:s}.{processing_type:s}nc{nc_version}' 16 | file_reader: !!python/name:satpy.readers.seadas_l2.SEADASL2NetCDFFileHandler 17 | geo_resolution: 1000 18 | 19 | datasets: 20 | longitude: 21 | name: longitude 22 | file_type: [bgc_nc] 23 | file_key: ["navigation_data/longitude", "longitude"] 24 | resolution: 1000 25 | 26 | latitude: 27 | name: latitude 28 | file_type: [bgc_nc] 29 | file_key: ["navigation_data/latitude", "latitude"] 30 | resolution: 1000 31 | 32 | chlor_a: 33 | name: chlor_a 34 | file_type: [bgc_nc] 35 | file_key: ["geophysical_data/chlor_a", "chlor_a"] 36 | resolution: 1000 37 | coordinates: [longitude, latitude] 38 | -------------------------------------------------------------------------------- /satpy/etc/readers/satpy_cf_nc.yaml: -------------------------------------------------------------------------------- 1 | reader: 2 | name: satpy_cf_nc 3 | short_name: Satpy CF 4 | long_name: Reader for CF conform netCDF files written with Satpy 5 | description: Reader for Satpy's NC/CF files 6 | status: Nominal 7 | supports_fsspec: false 8 | reader: !!python/name:satpy.readers.core.yaml_reader.FileYAMLReader 9 | sensors: [many] 10 | default_channels: [] 11 | 12 | #datasets: 13 | 14 | file_types: 15 | graphic: 16 | file_reader: !!python/name:satpy.readers.satpy_cf_nc.SatpyCFFileHandler 17 | file_patterns: 18 | - '{platform_name}-{sensor}-{resolution_type}-{start_time:%Y%m%d%H%M%S}-{end_time:%Y%m%d%H%M%S}.nc' 19 | - '{platform_name}-{sensor}-{start_time:%Y%m%d%H%M%S}-{end_time:%Y%m%d%H%M%S}.nc' 20 | -------------------------------------------------------------------------------- /satpy/etc/readers/scatsat1_l2b.yaml: -------------------------------------------------------------------------------- 1 | reader: 2 | name: scatsat1_l2b 3 | short_name: Scatsat-1 l2b 4 | long_name: Scatsat-1 Level 2b Wind field data in HDF5 format 5 | description: Generic Eumetsat Scatsat-1 L2B Wind field Reader 6 | reader: !!python/name:satpy.readers.core.yaml_reader.FileYAMLReader 7 | status: defunct 8 | supports_fsspec: false 9 | sensors: [scatterometer] 10 | default_datasets: 11 | 12 | datasets: 13 | longitude: 14 | name: longitude 15 | resolution: 25000 16 | file_type: scatsat 17 | standard_name: longitude 18 | units: degree 19 | 20 | latitude: 21 | name: latitude 22 | resolution: 25000 23 | file_type: scatsat 24 | standard_name: latitude 25 | units: degree 26 | 27 | wind_speed: 28 | name: wind_speed 29 | sensor: Scatterometer 30 | resolution: 25000 31 | coordinates: [longitude, latitude] 32 | file_type: scatsat 33 | standard_name: wind_speed 34 | 35 | wind_direction: 36 | name: wind_direction 37 | resolution: 25000 38 | coordinates: [longitude, latitude] 39 | file_type: scatsat 40 | standard_name: wind_direction 41 | 42 | 43 | file_types: 44 | scatsat: 45 | file_reader: !!python/name:satpy.readers.scatsat1_l2b.SCATSAT1L2BFileHandler 46 | file_patterns: ['S1L2B{start_date:%Y%j}_{start_orbit}_{end_orbit}_{direction}_{cell_spacing}_{prod_date}T{prod_time}_{version}.h5'] 47 | -------------------------------------------------------------------------------- /satpy/etc/readers/seadas_l2.yaml: -------------------------------------------------------------------------------- 1 | reader: 2 | name: seadas_l2 3 | short_name: MODIS/VIIRS SEADAS 4 | long_name: SEADAS L2 Chlorphyll A product in HDF4 format 5 | description: MODIS and VIIRS SEADAS Reader 6 | status: Beta 7 | supports_fsspec: false 8 | reader: !!python/name:satpy.readers.core.yaml_reader.FileYAMLReader 9 | sensors: [modis, viirs] 10 | 11 | file_types: 12 | chlora_seadas: 13 | file_patterns: 14 | # IMAPP-style filenames: 15 | - '{platform_indicator:1s}1.{start_time:%y%j.%H%M}.seadas.hdf' 16 | file_reader: !!python/name:satpy.readers.seadas_l2.SEADASL2HDFFileHandler 17 | geo_resolution: 1000 18 | chlora_seadas_nc: 19 | file_patterns: 20 | # IMAPP-style filenames: 21 | - '{platform_indicator:1s}1.{start_time:%y%j.%H%M}.seadas.nc' 22 | file_reader: !!python/name:satpy.readers.seadas_l2.SEADASL2NetCDFFileHandler 23 | geo_resolution: 1000 24 | chlora_seadas_viirs: 25 | # SEADAS_npp_d20211118_t1728125_e1739327.hdf 26 | file_patterns: 27 | - 'SEADAS_{platform_indicator:s}_d{start_time:%Y%m%d_t%H%M%S%f}_e{end_time:%H%M%S%f}.hdf' 28 | file_reader: !!python/name:satpy.readers.seadas_l2.SEADASL2HDFFileHandler 29 | geo_resolution: 750 30 | chlora_seadas_viirs_nc: 31 | # SEADAS_npp_d20211118_t1728125_e1739327.nc 32 | file_patterns: 33 | - 'SEADAS_{platform_indicator:s}_d{start_time:%Y%m%d_t%H%M%S%f}_e{end_time:%H%M%S%f}.nc' 34 | file_reader: !!python/name:satpy.readers.seadas_l2.SEADASL2NetCDFFileHandler 35 | geo_resolution: 750 36 | 37 | datasets: 38 | longitude: 39 | name: longitude 40 | file_type: [chlora_seadas_viirs_nc, chlora_seadas_nc, seadas_hdf_viirs, chlora_sedas] 41 | file_key: ["navigation_data/longitude", "longitude"] 42 | resolution: 43 | 1000: 44 | file_type: [chlora_seadas_nc, chlora_seadas] 45 | 750: 46 | file_type: [chlora_seadas_viirs_nc, chlora_seadas_viirs] 47 | 48 | latitude: 49 | name: latitude 50 | file_type: [chlora_seadas_viirs_nc, chlora_seadas_nc, seadas_hdf_viirs, chlora_sedas] 51 | file_key: ["navigation_data/latitude", "latitude"] 52 | resolution: 53 | 1000: 54 | file_type: [chlora_seadas_nc, chlora_seadas] 55 | 750: 56 | file_type: [chlora_seadas_viirs_nc, chlora_seadas_viirs] 57 | 58 | chlor_a: 59 | name: chlor_a 60 | file_type: [chlora_seadas_viirs_nc, chlora_seadas_nc, seadas_hdf_viirs, chlora_sedas] 61 | file_key: ["geophysical_data/chlor_a", "chlor_a"] 62 | resolution: 63 | 1000: 64 | file_type: [chlora_seadas_nc, chlora_seadas] 65 | 750: 66 | file_type: [chlora_seadas_viirs_nc, chlora_seadas_viirs] 67 | coordinates: [longitude, latitude] 68 | -------------------------------------------------------------------------------- /satpy/etc/readers/smos_l2_wind.yaml: -------------------------------------------------------------------------------- 1 | reader: 2 | name: smos_l2_wind 3 | short_name: SMOS l2 4 | long_name: SMOS level 2 wind data in NetCDF4 format 5 | description: SMOS Level 2 Wind NetCDF reader 6 | status: Beta 7 | supports_fsspec: false 8 | reader: !!python/name:satpy.readers.core.yaml_reader.FileYAMLReader 9 | sensors: [smos] 10 | 11 | file_types: 12 | smos_l2_wind: 13 | # Ex: SM_OPER_MIR_SCNFSW_20200420T021649_20200420T035013_110_001_7.nc 14 | file_reader: !!python/name:satpy.readers.smos_l2_wind.SMOSL2WINDFileHandler 15 | file_patterns: 16 | - '{platform_shortname:2s}_{file_class:4s}_{file_category:4s}{semantic_descriptor:6s}_{start_time:%Y%m%dT%H%M%S}_{end_time:%Y%m%dT%H%M%S}_{version:3s}_{counter:3s}_{site_id:1s}.nc' 17 | -------------------------------------------------------------------------------- /satpy/etc/readers/viirs_edr_flood.yaml: -------------------------------------------------------------------------------- 1 | reader: 2 | name: viirs_edr_flood 3 | short_name: VIIRS flood 4 | long_name: VIIRS EDR Flood data in HDF4 format 5 | description: VIIRS flood HDF4 reader 6 | status: Beta 7 | supports_fsspec: false 8 | reader: !!python/name:satpy.readers.core.yaml_reader.FileYAMLReader 9 | sensors: [viirs] 10 | 11 | file_types: 12 | viirs_edr: 13 | file_reader: !!python/name:satpy.readers.viirs_edr_flood.VIIRSEDRFlood 14 | file_patterns: 15 | - 'WATER_VIIRS_Prj_SVI_{platform_shortname}_d{start_time:%Y%m%d_t%H%M%S%f}_e{end_time:%H%M%S%f}_b{orbit:5d}_{source:8s}_{dim0:d}_{dim1:d}_01.hdf' 16 | - 'WATER_VIIRS_Prj_SVI_{platform_shortname}_d{start_time:%Y%m%d_t%H%M%S%f}_e{end_time:%H%M%S%f}_b{orbit:5d}_{source:8s}_{aoi:3s}_{dim0:d}_{dim1:d}_01.hdf' 17 | - 'WATER_COM_VIIRS_Prj_SVI_d{start_time:%Y%m%d}_d{end_time:%Y%m%d}_{dim0:d}_{dim1:d}_{unknown1:2d}_{total_days:3d}day_{tile_num:3d}.hdf' 18 | 19 | datasets: 20 | water_detection: 21 | name: 'WaterDetection' 22 | file_type: viirs_edr 23 | -------------------------------------------------------------------------------- /satpy/etc/writers/cf.yaml: -------------------------------------------------------------------------------- 1 | writer: 2 | name: cf 3 | description: Generic netCDF4/CF Writer 4 | writer: !!python/name:satpy.writers.cf_writer.CFWriter 5 | filename: '{platform_name}-{sensor}-{start_time:%Y%m%d%H%M%S}-{end_time:%Y%m%d%H%M%S}.nc' 6 | compress: DEFLATE 7 | zlevel: 6 8 | -------------------------------------------------------------------------------- /satpy/etc/writers/geotiff.yaml: -------------------------------------------------------------------------------- 1 | writer: 2 | name: geotiff 3 | description: Generic GeoTIFF Writer 4 | writer: !!python/name:satpy.writers.geotiff.GeoTIFFWriter 5 | filename: '{name}_{start_time:%Y%m%d_%H%M%S}.tif' 6 | compress: DEFLATE 7 | zlevel: 6 8 | -------------------------------------------------------------------------------- /satpy/etc/writers/mitiff.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | writer: 3 | name: mitiff 4 | description: Generic MITIFF Writer 5 | writer: !!python/name:satpy.writers.mitiff.MITIFFWriter 6 | filename: '{name:s}_{start_time:%Y%m%d_%H%M%S}.mitiff' 7 | compress: DEFLATE 8 | zlevel: 6 9 | -------------------------------------------------------------------------------- /satpy/etc/writers/ninjogeotiff.yaml: -------------------------------------------------------------------------------- 1 | writer: 2 | name: ninjogeotiff 3 | description: GeoTIFF Writer with NinJo tags in GDALMetaData 4 | writer: !!python/name:satpy.writers.ninjogeotiff.NinJoGeoTIFFWriter 5 | filename: '{name}_{start_time:%Y%m%d_%H%M%S}.tif' 6 | compress: DEFLATE 7 | zlevel: 6 8 | -------------------------------------------------------------------------------- /satpy/etc/writers/ninjotiff.yaml: -------------------------------------------------------------------------------- 1 | writer: 2 | name: ninjotiff 3 | description: NinjoTIFF Writer 4 | writer: !!python/name:satpy.writers.ninjotiff.NinjoTIFFWriter 5 | filename: '{name}_{start_time:%Y%m%d_%H%M%S}.tif' 6 | compress: DEFLATE 7 | zlevel: 6 8 | -------------------------------------------------------------------------------- /satpy/etc/writers/simple_image.yaml: -------------------------------------------------------------------------------- 1 | writer: 2 | name: simple_image 3 | description: Generic Image Writer 4 | writer: !!python/name:satpy.writers.simple_image.PillowWriter 5 | filename: '{name}_{start_time:%Y%m%d_%H%M%S}.png' 6 | -------------------------------------------------------------------------------- /satpy/modifiers/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2020 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | """Modifier classes and other related utilities.""" 19 | 20 | # file deepcode ignore W0611: Ignore unused imports in init module 21 | 22 | from .base import ModifierBase # noqa: F401, isort: skip 23 | from .atmosphere import CO2Corrector # noqa: F401, I001 24 | from .atmosphere import PSPAtmosphericalCorrection # noqa: F401 25 | from .atmosphere import PSPRayleighReflectance # noqa: F401 26 | from .geometry import EffectiveSolarPathLengthCorrector # noqa: F401 27 | from .geometry import SunZenithCorrector # noqa: F401 28 | from .geometry import SunZenithReducer # noqa: F401 29 | from .spectral import NIREmissivePartFromReflectance # noqa: F401 30 | from .spectral import NIRReflectance # noqa: F401 31 | -------------------------------------------------------------------------------- /satpy/modifiers/base.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2020 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | """Base modifier classes and utilities.""" 19 | 20 | from satpy.composites import CompositeBase 21 | 22 | 23 | class ModifierBase(CompositeBase): 24 | """Base class for all modifiers. 25 | 26 | A modifier in Satpy is a class that takes one input DataArray to be 27 | changed along with zero or more other input DataArrays used to perform 28 | these changes. The result of a modifier typically has a lot of the same 29 | metadata (name, units, etc) as the original DataArray, but the data is 30 | different. A modified DataArray can be differentiated from the original 31 | DataArray by the `modifiers` property of its `DataID`. 32 | 33 | See the :class:`~satpy.composites.CompositeBase` class for information 34 | on the similar concept of "compositors". 35 | 36 | """ 37 | 38 | def __call__(self, datasets, optional_datasets=None, **info): 39 | """Generate a modified copy of the first provided dataset.""" 40 | raise NotImplementedError() 41 | -------------------------------------------------------------------------------- /satpy/modifiers/filters.py: -------------------------------------------------------------------------------- 1 | """Tests for image filters.""" 2 | import logging 3 | 4 | import xarray as xr 5 | 6 | from satpy.modifiers import ModifierBase 7 | 8 | logger = logging.getLogger(__name__) 9 | 10 | 11 | class Median(ModifierBase): 12 | """Apply a median filter to the band.""" 13 | 14 | def __init__(self, median_filter_params, **kwargs): # noqa: D417 15 | """Create the instance. 16 | 17 | Args: 18 | median_filter_params: The arguments to pass to dask-image's median_filter function. For example, {size: 3} 19 | makes give the median filter a kernel of size 3. 20 | 21 | """ 22 | self.median_filter_params = median_filter_params 23 | super().__init__(**kwargs) 24 | 25 | def __call__(self, arrays, **info): 26 | """Get the median filtered band.""" 27 | from dask_image.ndfilters import median_filter 28 | 29 | data = arrays[0] 30 | logger.debug(f"Apply median filtering with parameters {self.median_filter_params}.") 31 | res = xr.DataArray(median_filter(data.data, **self.median_filter_params), 32 | dims=data.dims, attrs=data.attrs, coords=data.coords) 33 | self.apply_modifier_info(data, res) 34 | return res 35 | -------------------------------------------------------------------------------- /satpy/multiscene/__init__.py: -------------------------------------------------------------------------------- 1 | """Functions and classes related to MultiScene functionality.""" 2 | 3 | from ._blend_funcs import stack, temporal_rgb, timeseries # noqa 4 | from ._multiscene import MultiScene # noqa 5 | -------------------------------------------------------------------------------- /satpy/py.typed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pytroll/satpy/ecd39317058a38f6fae734cb48c51f68bbf8517c/satpy/py.typed -------------------------------------------------------------------------------- /satpy/readers/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) 2015-2025 Satpy developers 3 | # 4 | # This file is part of satpy. 5 | # 6 | # satpy is free software: you can redistribute it and/or modify it under the 7 | # terms of the GNU General Public License as published by the Free Software 8 | # Foundation, either version 3 of the License, or (at your option) any later 9 | # version. 10 | # 11 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 12 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License along with 16 | # satpy. If not, see . 17 | 18 | """Shared objects of the various reader classes.""" 19 | 20 | from __future__ import annotations 21 | 22 | from typing import Any 23 | 24 | from satpy.utils import _import_and_warn_new_location 25 | 26 | IMPORT_PATHS = { 27 | "FSFile": "satpy.readers.core.remote", 28 | "open_file_or_filename": "satpy.readers.core.remote", 29 | "group_files": "satpy.readers.core.grouping", 30 | "find_files_and_readers": "satpy.readers.core.grouping", 31 | "read_reader_config": "satpy.readers.core.config", 32 | "configs_for_reader": "satpy.readers.core.config", 33 | "available_readers": "satpy.readers.core.config", 34 | "get_valid_reader_names": "satpy.readers.core.config", 35 | "OLD_READER_NAMES": "satpy.readers.core.config", 36 | "PENDING_OLD_READER_NAMES": "satpy.readers.core.config", 37 | "load_readers": "satpy.readers.core.loading", 38 | "load_reader": "satpy.readers.core.loading", 39 | } 40 | 41 | def __getattr__(name: str) -> Any: 42 | new_module = IMPORT_PATHS.get(name) 43 | 44 | if new_module is None: 45 | raise AttributeError(f"module {__name__} has no attribute '{name}'") 46 | 47 | return _import_and_warn_new_location(new_module, name) 48 | -------------------------------------------------------------------------------- /satpy/readers/abi_base.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) 2016-2025 Satpy developers 3 | # 4 | # This file is part of satpy. 5 | # 6 | # satpy is free software: you can redistribute it and/or modify it under the 7 | # terms of the GNU General Public License as published by the Free Software 8 | # Foundation, either version 3 of the License, or (at your option) any later 9 | # version. 10 | # 11 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 12 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License along with 16 | # satpy. If not, see . 17 | 18 | """Advance Baseline Imager reader base class for the Level 1b and l2+ reader.""" 19 | 20 | from __future__ import annotations 21 | 22 | from typing import Any 23 | 24 | from satpy.utils import _import_and_warn_new_location 25 | 26 | 27 | def __getattr__(name: str) -> Any: 28 | new_module = "satpy.readers.core.abi" 29 | 30 | return _import_and_warn_new_location(new_module, name) 31 | -------------------------------------------------------------------------------- /satpy/readers/amsr2_l2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2020 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | """Reader for AMSR2 L2 files in HDF5 format.""" 19 | 20 | from satpy.readers.amsr2_l1b import AMSR2L1BFileHandler 21 | 22 | 23 | class AMSR2L2FileHandler(AMSR2L1BFileHandler): 24 | """AMSR2 level 2 file handler.""" 25 | 26 | def mask_dataset(self, ds_info, data): 27 | """Mask data with the fill value.""" 28 | fill_value = ds_info.get("fill_value", 65535) 29 | return data.where(data != fill_value) 30 | 31 | def scale_dataset(self, var_path, data): 32 | """Scale data with the scale factor attribute.""" 33 | return data * self[var_path + "/attr/SCALE FACTOR"] 34 | 35 | def get_dataset(self, ds_id, ds_info): 36 | """Get output data and metadata of specified dataset.""" 37 | var_path = ds_info["file_key"] 38 | 39 | data = self[var_path].squeeze() 40 | data = self.mask_dataset(ds_info, data) 41 | data = self.scale_dataset(var_path, data) 42 | 43 | if ds_info.get("name") == "ssw": 44 | data = data.rename({"dim_0": "y", "dim_1": "x"}) 45 | metadata = self.get_metadata(ds_id, ds_info) 46 | data.attrs.update(metadata) 47 | return data 48 | -------------------------------------------------------------------------------- /satpy/readers/core/__init__.py: -------------------------------------------------------------------------------- 1 | """Reader core package.""" 2 | -------------------------------------------------------------------------------- /satpy/readers/core/vii.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2020 Satpy developers 5 | # 6 | # satpy is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # satpy is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with satpy. If not, see . 18 | 19 | """Utilities for the management of VII products.""" 20 | 21 | 22 | # PLANCK COEFFICIENTS FOR CALIBRATION AS DEFINED BY EUMETSAT 23 | C1 = 1.191062e+8 # [W/m2·sr-1·µm4] 24 | C2 = 1.4387863e+4 # [K·µm] 25 | 26 | # CONSTANTS DEFINING THE TIE POINTS 27 | TIE_POINTS_FACTOR = 8 # Sub-sampling factor of tie points wrt pixel points 28 | SCAN_ALT_TIE_POINTS = 4 # Number of tie points along the satellite track for each scan 29 | 30 | # MEAN EARTH RADIUS AS DEFINED BY IUGG 31 | MEAN_EARTH_RADIUS = 6371008.7714 # [m] 32 | -------------------------------------------------------------------------------- /satpy/readers/eum_base.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) 2016-2025 Satpy developers 3 | # 4 | # This file is part of satpy. 5 | # 6 | # satpy is free software: you can redistribute it and/or modify it under the 7 | # terms of the GNU General Public License as published by the Free Software 8 | # Foundation, either version 3 of the License, or (at your option) any later 9 | # version. 10 | # 11 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 12 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License along with 16 | # satpy. If not, see . 17 | 18 | """Common functionality for EUM data readers.""" 19 | 20 | from __future__ import annotations 21 | 22 | from typing import Any 23 | 24 | from satpy.utils import _import_and_warn_new_location 25 | 26 | 27 | def __getattr__(name: str) -> Any: 28 | new_module = "satpy.readers.core.eum" 29 | 30 | return _import_and_warn_new_location(new_module, name) 31 | -------------------------------------------------------------------------------- /satpy/readers/fci_base.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) 2016-2025 Satpy developers 3 | # 4 | # This file is part of satpy. 5 | # 6 | # satpy is free software: you can redistribute it and/or modify it under the 7 | # terms of the GNU General Public License as published by the Free Software 8 | # Foundation, either version 3 of the License, or (at your option) any later 9 | # version. 10 | # 11 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 12 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License along with 16 | # satpy. If not, see . 17 | 18 | """Common functionality for FCI data readers.""" 19 | 20 | from __future__ import annotations 21 | 22 | from typing import Any 23 | 24 | from satpy.utils import _import_and_warn_new_location 25 | 26 | 27 | def __getattr__(name: str) -> Any: 28 | new_module = "satpy.readers.core.fci" 29 | 30 | return _import_and_warn_new_location(new_module, name) 31 | -------------------------------------------------------------------------------- /satpy/readers/file_handlers.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) 2014-2025 Satpy developers 3 | # 4 | # This file is part of satpy. 5 | # 6 | # satpy is free software: you can redistribute it and/or modify it under the 7 | # terms of the GNU General Public License as published by the Free Software 8 | # Foundation, either version 3 of the License, or (at your option) any later 9 | # version. 10 | # 11 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 12 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License along with 16 | # satpy. If not, see . 17 | """Interface for BaseFileHandlers.""" 18 | 19 | from __future__ import annotations 20 | 21 | from typing import Any 22 | 23 | from satpy.utils import _import_and_warn_new_location 24 | 25 | 26 | def __getattr__(name: str) -> Any: 27 | new_module = "satpy.readers.core.file_handlers" 28 | 29 | return _import_and_warn_new_location(new_module, name) 30 | -------------------------------------------------------------------------------- /satpy/readers/fy4_base.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) 2016-2025 Satpy developers 3 | # 4 | # This file is part of satpy. 5 | # 6 | # satpy is free software: you can redistribute it and/or modify it under the 7 | # terms of the GNU General Public License as published by the Free Software 8 | # Foundation, either version 3 of the License, or (at your option) any later 9 | # version. 10 | # 11 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 12 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License along with 16 | # satpy. If not, see . 17 | 18 | """Base reader for the L1 HDF data from the AGRI and GHI instruments aboard the FengYun-4A/B satellites. 19 | 20 | The files read by this reader are described in the official Real Time Data Service: 21 | 22 | http://fy4.nsmc.org.cn/data/en/data/realtime.html 23 | 24 | """ 25 | 26 | from __future__ import annotations 27 | 28 | from typing import Any 29 | 30 | from satpy.utils import _import_and_warn_new_location 31 | 32 | 33 | def __getattr__(name: str) -> Any: 34 | new_module = "satpy.readers.core.fy4" 35 | 36 | return _import_and_warn_new_location(new_module, name) 37 | -------------------------------------------------------------------------------- /satpy/readers/gms/__init__.py: -------------------------------------------------------------------------------- 1 | """GMS reader module.""" 2 | -------------------------------------------------------------------------------- /satpy/readers/hdf4_utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) 2016-2025 Satpy developers 3 | # 4 | # This file is part of satpy. 5 | # 6 | # satpy is free software: you can redistribute it and/or modify it under the 7 | # terms of the GNU General Public License as published by the Free Software 8 | # Foundation, either version 3 of the License, or (at your option) any later 9 | # version. 10 | # 11 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 12 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License along with 16 | # satpy. If not, see . 17 | """Helpers for reading hdf4-based files.""" 18 | 19 | from __future__ import annotations 20 | 21 | from typing import Any 22 | 23 | from satpy.utils import _import_and_warn_new_location 24 | 25 | 26 | def __getattr__(name: str) -> Any: 27 | new_module = "satpy.readers.core.hdf4" 28 | 29 | return _import_and_warn_new_location(new_module, name) 30 | -------------------------------------------------------------------------------- /satpy/readers/hdf5_utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) 2016-2025 Satpy developers 3 | # 4 | # This file is part of satpy. 5 | # 6 | # satpy is free software: you can redistribute it and/or modify it under the 7 | # terms of the GNU General Public License as published by the Free Software 8 | # Foundation, either version 3 of the License, or (at your option) any later 9 | # version. 10 | # 11 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 12 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License along with 16 | # satpy. If not, see . 17 | """Helpers for reading hdf5-based files.""" 18 | 19 | from __future__ import annotations 20 | 21 | from typing import Any 22 | 23 | from satpy.utils import _import_and_warn_new_location 24 | 25 | 26 | def __getattr__(name: str) -> Any: 27 | new_module = "satpy.readers.core.hdf5" 28 | 29 | return _import_and_warn_new_location(new_module, name) 30 | -------------------------------------------------------------------------------- /satpy/readers/hdfeos_base.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) 2016-2025 Satpy developers 3 | # 4 | # This file is part of satpy. 5 | # 6 | # satpy is free software: you can redistribute it and/or modify it under the 7 | # terms of the GNU General Public License as published by the Free Software 8 | # Foundation, either version 3 of the License, or (at your option) any later 9 | # version. 10 | # 11 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 12 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License along with 16 | # satpy. If not, see . 17 | """Base HDF-EOS reader.""" 18 | 19 | from __future__ import annotations 20 | 21 | from typing import Any 22 | 23 | from satpy.utils import _import_and_warn_new_location 24 | 25 | 26 | def __getattr__(name: str) -> Any: 27 | new_module = "satpy.readers.core.hdfeos" 28 | 29 | return _import_and_warn_new_location(new_module, name) 30 | -------------------------------------------------------------------------------- /satpy/readers/hrit_base.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) 2016-2025 Satpy developers 3 | # 4 | # This file is part of satpy. 5 | # 6 | # satpy is free software: you can redistribute it and/or modify it under the 7 | # terms of the GNU General Public License as published by the Free Software 8 | # Foundation, either version 3 of the License, or (at your option) any later 9 | # version. 10 | # 11 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 12 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License along with 16 | # satpy. If not, see . 17 | """HRIT/LRIT format reader. 18 | 19 | This module is the base module for all HRIT-based formats. Here, you will find 20 | the common building blocks for hrit reading. 21 | 22 | One of the features here is the on-the-fly decompression of hrit files when 23 | compressed hrit files are encountered (files finishing with `.C_`). 24 | """ 25 | 26 | from __future__ import annotations 27 | 28 | from typing import Any 29 | 30 | from satpy.utils import _import_and_warn_new_location 31 | 32 | 33 | def __getattr__(name: str) -> Any: 34 | new_module = "satpy.readers.core.hrit" 35 | 36 | return _import_and_warn_new_location(new_module, name) 37 | -------------------------------------------------------------------------------- /satpy/readers/li_base_nc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) 2016-2025 Satpy developers 3 | # 4 | # This file is part of satpy. 5 | # 6 | # satpy is free software: you can redistribute it and/or modify it under the 7 | # terms of the GNU General Public License as published by the Free Software 8 | # Foundation, either version 3 of the License, or (at your option) any later 9 | # version. 10 | # 11 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 12 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License along with 16 | # satpy. If not, see . 17 | """Base class used for the MTG Lighting Imager netCDF4 readers.""" 18 | 19 | from __future__ import annotations 20 | 21 | from typing import Any 22 | 23 | from satpy.utils import _import_and_warn_new_location 24 | 25 | 26 | def __getattr__(name: str) -> Any: 27 | new_module = "satpy.readers.core.li_nc" 28 | 29 | return _import_and_warn_new_location(new_module, name) 30 | -------------------------------------------------------------------------------- /satpy/readers/netcdf_utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) 2014-2025 Satpy developers 3 | # 4 | # This file is part of satpy. 5 | # 6 | # satpy is free software: you can redistribute it and/or modify it under the 7 | # terms of the GNU General Public License as published by the Free Software 8 | # Foundation, either version 3 of the License, or (at your option) any later 9 | # version. 10 | # 11 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 12 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License along with 16 | # satpy. If not, see . 17 | """Helpers for reading netcdf-based files.""" 18 | 19 | from __future__ import annotations 20 | 21 | from typing import Any 22 | 23 | from satpy.utils import _import_and_warn_new_location 24 | 25 | 26 | def __getattr__(name: str) -> Any: 27 | new_module = "satpy.readers.core.netcdf" 28 | 29 | return _import_and_warn_new_location(new_module, name) 30 | -------------------------------------------------------------------------------- /satpy/readers/seviri_base.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) 2014-2025 Satpy developers 3 | # 4 | # This file is part of satpy. 5 | # 6 | # satpy is free software: you can redistribute it and/or modify it under the 7 | # terms of the GNU General Public License as published by the Free Software 8 | # Foundation, either version 3 of the License, or (at your option) any later 9 | # version. 10 | # 11 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 12 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License along with 16 | # satpy. If not, see . 17 | """Common functionality for SEVIRI L1.5 data readers.""" 18 | 19 | from __future__ import annotations 20 | 21 | from typing import Any 22 | 23 | from satpy.utils import _import_and_warn_new_location 24 | 25 | 26 | def __getattr__(name: str) -> Any: 27 | new_module = "satpy.readers.core.seviri" 28 | 29 | return _import_and_warn_new_location(new_module, name) 30 | -------------------------------------------------------------------------------- /satpy/readers/utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) 2014-2025 Satpy developers 3 | # 4 | # This file is part of satpy. 5 | # 6 | # satpy is free software: you can redistribute it and/or modify it under the 7 | # terms of the GNU General Public License as published by the Free Software 8 | # Foundation, either version 3 of the License, or (at your option) any later 9 | # version. 10 | # 11 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 12 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License along with 16 | # satpy. If not, see . 17 | """Helper functions for satpy readers.""" 18 | 19 | from __future__ import annotations 20 | 21 | from typing import Any 22 | 23 | from satpy.utils import _import_and_warn_new_location 24 | 25 | 26 | def __getattr__(name: str) -> Any: 27 | new_module = "satpy.readers.core.utils" 28 | 29 | return _import_and_warn_new_location(new_module, name) 30 | -------------------------------------------------------------------------------- /satpy/readers/vii_base_nc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) 2014-2025 Satpy developers 3 | # 4 | # This file is part of satpy. 5 | # 6 | # satpy is free software: you can redistribute it and/or modify it under the 7 | # terms of the GNU General Public License as published by the Free Software 8 | # Foundation, either version 3 of the License, or (at your option) any later 9 | # version. 10 | # 11 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 12 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License along with 16 | # satpy. If not, see . 17 | """EUMETSAT EPS-SG Visible/Infrared Imager (VII) readers base class.""" 18 | 19 | from __future__ import annotations 20 | 21 | from typing import Any 22 | 23 | from satpy.utils import _import_and_warn_new_location 24 | 25 | 26 | def __getattr__(name: str) -> Any: 27 | new_module = "satpy.readers.core.vii_nc" 28 | 29 | return _import_and_warn_new_location(new_module, name) 30 | -------------------------------------------------------------------------------- /satpy/readers/vii_l2_nc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2020 Satpy developers 5 | # 6 | # satpy is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # satpy is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with satpy. If not, see . 18 | 19 | """EUMETSAT EPS-SG Visible/Infrared Imager (VII) Level 2 products reader.""" 20 | 21 | import logging 22 | 23 | import xarray as xr 24 | 25 | from satpy.readers.core.vii_nc import ViiNCBaseFileHandler 26 | 27 | logger = logging.getLogger(__name__) 28 | 29 | 30 | class ViiL2NCFileHandler(ViiNCBaseFileHandler): 31 | """Reader class for VII L2 products in netCDF format.""" 32 | 33 | def _perform_orthorectification(self, variable: xr.DataArray, orthorect_data_name: str) -> xr.DataArray: 34 | """Perform the orthorectification. 35 | 36 | Args: 37 | variable: DataArray containing the dataset to correct for orthorectification. 38 | orthorect_data_name: name of the orthorectification correction data in the product. 39 | 40 | Returns: 41 | array containing the corrected values and all the original metadata. 42 | 43 | """ 44 | try: 45 | orthorect_data = self[orthorect_data_name] 46 | variable += orthorect_data 47 | except KeyError: 48 | logger.warning("Required dataset %s for orthorectification not available, skipping", orthorect_data_name) 49 | return variable 50 | -------------------------------------------------------------------------------- /satpy/readers/vii_utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) 2014-2025 Satpy developers 3 | # 4 | # This file is part of satpy. 5 | # 6 | # satpy is free software: you can redistribute it and/or modify it under the 7 | # terms of the GNU General Public License as published by the Free Software 8 | # Foundation, either version 3 of the License, or (at your option) any later 9 | # version. 10 | # 11 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 12 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License along with 16 | # satpy. If not, see . 17 | """Utilities for the management of VII products.""" 18 | 19 | from __future__ import annotations 20 | 21 | from typing import Any 22 | 23 | from satpy.utils import _import_and_warn_new_location 24 | 25 | 26 | def __getattr__(name: str) -> Any: 27 | new_module = "satpy.readers.core.vii" 28 | 29 | return _import_and_warn_new_location(new_module, name) 30 | -------------------------------------------------------------------------------- /satpy/readers/viirs_atms_sdr_base.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) 2014-2025 Satpy developers 3 | # 4 | # This file is part of satpy. 5 | # 6 | # satpy is free software: you can redistribute it and/or modify it under the 7 | # terms of the GNU General Public License as published by the Free Software 8 | # Foundation, either version 3 of the License, or (at your option) any later 9 | # version. 10 | # 11 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 12 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License along with 16 | # satpy. If not, see . 17 | """Common utilities for reading VIIRS and ATMS SDR data.""" 18 | 19 | from __future__ import annotations 20 | 21 | from typing import Any 22 | 23 | from satpy.utils import _import_and_warn_new_location 24 | 25 | 26 | def __getattr__(name: str) -> Any: 27 | new_module = "satpy.readers.core.viirs_atms_sdr" 28 | 29 | return _import_and_warn_new_location(new_module, name) 30 | -------------------------------------------------------------------------------- /satpy/readers/xmlformat.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) 2014-2025 Satpy developers 3 | # 4 | # This file is part of satpy. 5 | # 6 | # satpy is free software: you can redistribute it and/or modify it under the 7 | # terms of the GNU General Public License as published by the Free Software 8 | # Foundation, either version 3 of the License, or (at your option) any later 9 | # version. 10 | # 11 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 12 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License along with 16 | # satpy. If not, see . 17 | """Reads a format from an xml file to create dtypes and scaling factor arrays.""" 18 | 19 | from __future__ import annotations 20 | 21 | from typing import Any 22 | 23 | from satpy.utils import _import_and_warn_new_location 24 | 25 | 26 | def __getattr__(name: str) -> Any: 27 | new_module = "satpy.readers.core.xmlformat" 28 | 29 | return _import_and_warn_new_location(new_module, name) 30 | -------------------------------------------------------------------------------- /satpy/readers/yaml_reader.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Copyright (c) 2014-2025 Satpy developers 3 | # 4 | # This file is part of satpy. 5 | # 6 | # satpy is free software: you can redistribute it and/or modify it under the 7 | # terms of the GNU General Public License as published by the Free Software 8 | # Foundation, either version 3 of the License, or (at your option) any later 9 | # version. 10 | # 11 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 12 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 13 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License along with 16 | # satpy. If not, see . 17 | """Base classes and utilities for all readers configured by YAML files.""" 18 | 19 | from __future__ import annotations 20 | 21 | from typing import Any 22 | 23 | from satpy.utils import _import_and_warn_new_location 24 | 25 | 26 | def __getattr__(name: str) -> Any: 27 | new_module = "satpy.readers.core.yaml_reader" 28 | 29 | return _import_and_warn_new_location(new_module, name) 30 | -------------------------------------------------------------------------------- /satpy/resample/ewa.py: -------------------------------------------------------------------------------- 1 | """EWA resamplers.""" 2 | 3 | from pyresample.ewa import DaskEWAResampler, LegacyDaskEWAResampler 4 | 5 | 6 | def get_resampler_classes(): 7 | """Get bucket resampler classes.""" 8 | return { 9 | "ewa": DaskEWAResampler, 10 | "ewa_legacy": LegacyDaskEWAResampler, 11 | } 12 | -------------------------------------------------------------------------------- /satpy/testing.py: -------------------------------------------------------------------------------- 1 | """Testing helpers for satpy.""" 2 | 3 | from contextlib import contextmanager 4 | from unittest import mock 5 | 6 | import pytest 7 | 8 | import satpy.scene 9 | 10 | 11 | @contextmanager 12 | def fake_satpy_reading(scene_dict): 13 | """Fake the satpy reading and populate the returned scene with the contents of *scene_dict*. 14 | 15 | This allows users to test their programs that use satpy without actually needing to read files, eg:: 16 | 17 | scene_dict = {channel: somedata} 18 | 19 | with fake_satpy_reading(scene_dict): 20 | scene = Scene(input_files, reader="dummy_reader") 21 | scene.load([channel]) 22 | 23 | """ 24 | with pytest.MonkeyPatch().context() as monkeypatch: 25 | reader_instance = mock.Mock() 26 | reader_instance.sensor_names = ["dummy_sensor"] 27 | fake_load_readers = mock.Mock() 28 | fake_load_readers.return_value = {"dummy_reader": reader_instance} 29 | monkeypatch.setattr(satpy.scene, "load_readers", fake_load_readers) 30 | 31 | def fake_load(self, channels): 32 | for channel in channels: 33 | self[channel] = scene_dict[channel] 34 | 35 | 36 | monkeypatch.setattr(satpy.scene.Scene, "load", fake_load) 37 | yield 38 | -------------------------------------------------------------------------------- /satpy/tests/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2014-2020 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | """The tests package.""" 19 | -------------------------------------------------------------------------------- /satpy/tests/behave/features/image_comparison.feature: -------------------------------------------------------------------------------- 1 | Feature: Image Comparison 2 | 3 | Scenario Outline: Compare generated image with reference image 4 | Given I have a reference image file from resampled to 5 | When I generate a new image file from case with for resampling with with clipping 6 | Then the generated image should be the same as the reference image 7 | 8 | Examples: 9 | |satellite | case | composite | reader | area | resampler | clip | 10 | |Meteosat-12 | scan_night | cloudtop | fci_l1c_nc | sve | gradient_search | True | 11 | |Meteosat-12 | scan_night | night_microphysics | fci_l1c_nc | sve | gradient_search | True | 12 | |Meteosat-12 | mali_day | essl_colorized_low_level_moisture | fci_l1c_nc | mali | gradient_search | False | 13 | |Meteosat-12 | spain_day | colorized_low_level_moisture_with_vis06 | fci_l1c_nc,fci_l2_nc | spain | nearest | False | 14 | |GOES17 | americas_night | airmass | abi_l1b | null | null | null | 15 | |GOES16 | americas_night | airmass | abi_l1b | null | null | null | 16 | |GOES16 | americas_night | ash | abi_l1b | null | null | null | 17 | |GOES17 | americas_night | ash | abi_l1b | null | null | null | 18 | -------------------------------------------------------------------------------- /satpy/tests/cf_tests/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2017-2023 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | """The CF dataset tests package.""" 19 | -------------------------------------------------------------------------------- /satpy/tests/cf_tests/test_attrs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2017-2023 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | """Tests for CF-compatible attributes encoding.""" 19 | import json 20 | 21 | 22 | class TestCFAttributeEncoding: 23 | """Test case for CF attribute encodings.""" 24 | 25 | def test__encode_nc_attrs(self): 26 | """Test attributes encoding.""" 27 | from satpy.cf.attrs import encode_attrs_to_cf 28 | from satpy.tests.cf_tests._test_data import get_test_attrs 29 | from satpy.tests.utils import assert_dict_array_equality 30 | 31 | attrs, expected, _ = get_test_attrs() 32 | 33 | # Test encoding 34 | encoded = encode_attrs_to_cf(attrs) 35 | assert_dict_array_equality(expected, encoded) 36 | 37 | # Test decoding of json-encoded attributes 38 | raw_md_roundtrip = {"recarray": [[0, 0], [0, 0], [0, 0]], 39 | "flag": "true", 40 | "dict": {"a": 1, "b": [1, 2, 3]}} 41 | assert json.loads(encoded["raw_metadata"]) == raw_md_roundtrip 42 | assert json.loads(encoded["array_3d"]) == [[[1, 2], [3, 4]], [[1, 2], [3, 4]]] 43 | assert json.loads(encoded["nested_dict"]) == {"l1": {"l2": {"l3": [1, 2, 3]}}} 44 | assert json.loads(encoded["nested_list"]) == ["1", ["2", [3]]] 45 | -------------------------------------------------------------------------------- /satpy/tests/cf_tests/test_decoding.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2023 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | 19 | """Tests for CF decoding.""" 20 | 21 | import datetime as dt 22 | 23 | import pytest 24 | 25 | import satpy.cf.decoding 26 | 27 | 28 | class TestDecodeAttrs: 29 | """Test decoding of CF-encoded attributes.""" 30 | 31 | @pytest.fixture 32 | def attrs(self): 33 | """Get CF-encoded attributes.""" 34 | return { 35 | "my_integer": 0, 36 | "my_float": 0.0, 37 | "my_list": [1, 2, 3], 38 | "my_timestamp1": "2000-01-01", 39 | "my_timestamp2": "2000-01-01 12:15:33", 40 | "my_timestamp3": "2000-01-01 12:15:33.123456", 41 | "my_dict": '{"a": {"b": [1, 2, 3]}, "c": {"d": "2000-01-01 12:15:33.123456"}}' 42 | } 43 | 44 | @pytest.fixture 45 | def expected(self): 46 | """Get expected decoded results.""" 47 | return { 48 | "my_integer": 0, 49 | "my_float": 0.0, 50 | "my_list": [1, 2, 3], 51 | "my_timestamp1": dt.datetime(2000, 1, 1), 52 | "my_timestamp2": dt.datetime(2000, 1, 1, 12, 15, 33), 53 | "my_timestamp3": dt.datetime(2000, 1, 1, 12, 15, 33, 123456), 54 | "my_dict": {"a": {"b": [1, 2, 3]}, 55 | "c": {"d": dt.datetime(2000, 1, 1, 12, 15, 33, 123456)}} 56 | } 57 | 58 | def test_decoding(self, attrs, expected): 59 | """Test decoding of CF-encoded attributes.""" 60 | res = satpy.cf.decoding.decode_attrs(attrs) 61 | assert res == expected 62 | 63 | def test_decoding_doesnt_modify_original(self, attrs): 64 | """Test that decoding doesn't modify the original attributes.""" 65 | satpy.cf.decoding.decode_attrs(attrs) 66 | assert isinstance(attrs["my_dict"], str) 67 | -------------------------------------------------------------------------------- /satpy/tests/compositor_tests/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2018 - 2020 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | """Tests for compositors.""" 16 | -------------------------------------------------------------------------------- /satpy/tests/compositor_tests/test_ahi.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2018 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | """Tests for AHI compositors.""" 19 | 20 | import unittest 21 | 22 | 23 | class TestAHIComposites(unittest.TestCase): 24 | """Test AHI-specific composites.""" 25 | 26 | def test_load_composite_yaml(self): 27 | """Test loading the yaml for this sensor.""" 28 | from satpy.composites.config_loader import load_compositor_configs_for_sensors 29 | load_compositor_configs_for_sensors(["ahi"]) 30 | -------------------------------------------------------------------------------- /satpy/tests/conftest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2021 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | """Shared preparation and utilities for testing. 19 | 20 | This module is executed automatically by pytest. 21 | 22 | """ 23 | import os 24 | 25 | import pytest 26 | 27 | import satpy 28 | 29 | TEST_ETC_DIR = os.path.join(os.path.dirname(__file__), "etc") 30 | 31 | 32 | @pytest.fixture(autouse=True) 33 | def _reset_satpy_config(tmpdir): 34 | """Set satpy config to logical defaults for tests.""" 35 | test_config = { 36 | "cache_dir": str(tmpdir / "cache"), 37 | "data_dir": str(tmpdir / "data"), 38 | "config_path": [], 39 | "cache_lonlats": False, 40 | "cache_sensor_angles": False, 41 | } 42 | with satpy.config.set(test_config): 43 | yield 44 | 45 | 46 | @pytest.fixture(autouse=True) 47 | def _clear_function_caches(): 48 | """Clear out global function-level caches that may cause conflicts between tests.""" 49 | from satpy.composites.config_loader import load_compositor_configs_for_sensor 50 | load_compositor_configs_for_sensor.cache_clear() 51 | 52 | 53 | @pytest.fixture 54 | def include_test_etc(): 55 | """Tell Satpy to use the config 'etc' directory from the tests directory.""" 56 | with satpy.config.set(config_path=[TEST_ETC_DIR]): 57 | yield TEST_ETC_DIR 58 | -------------------------------------------------------------------------------- /satpy/tests/enhancement_tests/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2018 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | """The enhancements tests package.""" 19 | -------------------------------------------------------------------------------- /satpy/tests/enhancement_tests/test_abi.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2019 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | """Unit testing for the ABI enhancement functions.""" 19 | 20 | import unittest 21 | 22 | import dask.array as da 23 | import numpy as np 24 | import xarray as xr 25 | 26 | 27 | class TestABIEnhancement(unittest.TestCase): 28 | """Test the ABI enhancement functions.""" 29 | 30 | def setUp(self): 31 | """Create fake data for the tests.""" 32 | data = da.linspace(0, 1, 16).reshape((4, 4)) 33 | self.da = xr.DataArray(data, dims=("y", "x"), attrs={"test": "test"}) 34 | 35 | def test_cimss_true_color_contrast(self): 36 | """Test the cimss_true_color_contrast enhancement.""" 37 | from trollimage.xrimage import XRImage 38 | 39 | from satpy.enhancements.abi import cimss_true_color_contrast 40 | 41 | expected = np.array([[ 42 | [0., 0., 0.05261956, 0.13396146], 43 | [0.21530335, 0.29664525, 0.37798715, 0.45932905], 44 | [0.54067095, 0.62201285, 0.70335475, 0.78469665], 45 | [0.86603854, 0.94738044, 1., 1.], 46 | ]]) 47 | img = XRImage(self.da) 48 | cimss_true_color_contrast(img) 49 | np.testing.assert_almost_equal(img.data.compute(), expected) 50 | -------------------------------------------------------------------------------- /satpy/tests/enhancement_tests/test_enhancer.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2025 Satpy developers 2 | # 3 | # This file is part of satpy. 4 | # 5 | # satpy is free software: you can redistribute it and/or modify it under the 6 | # terms of the GNU General Public License as published by the Free Software 7 | # Foundation, either version 3 of the License, or (at your option) any later 8 | # version. 9 | # 10 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 11 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 12 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License along with 15 | # satpy. If not, see . 16 | """Test enhancer class.""" 17 | from __future__ import annotations 18 | 19 | import pytest 20 | 21 | from satpy.enhancements.enhancer import Enhancer 22 | 23 | 24 | class TestEnhancer: 25 | """Test basic `Enhancer` functionality with builtin configs.""" 26 | 27 | def test_basic_init_no_args(self): 28 | """Test Enhancer init with no arguments passed.""" 29 | e = Enhancer() 30 | assert e.enhancement_tree is not None 31 | 32 | def test_basic_init_no_enh(self): 33 | """Test Enhancer init requesting no enhancements.""" 34 | e = Enhancer(enhancement_config_file=False) 35 | assert e.enhancement_tree is None 36 | 37 | def test_basic_init_provided_enh(self): 38 | """Test Enhancer init with string enhancement configs.""" 39 | e = Enhancer(enhancement_config_file=["""enhancements: 40 | enh1: 41 | standard_name: toa_bidirectional_reflectance 42 | operations: 43 | - name: stretch 44 | method: !!python/name:satpy.enhancements.stretch 45 | kwargs: {stretch: linear} 46 | """]) 47 | assert e.enhancement_tree is not None 48 | 49 | def test_init_nonexistent_enh_file(self): 50 | """Test Enhancer init with a nonexistent enhancement configuration file.""" 51 | with pytest.raises(ValueError, match="YAML file doesn't exist or string is not YAML dict:.*"): 52 | Enhancer(enhancement_config_file="is_not_a_valid_filename_?.yaml") 53 | 54 | def test_print_tree(self, capsys): 55 | """Test enhancement decision tree printing.""" 56 | enh = Enhancer() 57 | enh.enhancement_tree.print_tree() 58 | stdout = capsys.readouterr().out 59 | lines = stdout.splitlines() 60 | assert lines[0].startswith("name=") 61 | # make sure lines are indented 62 | assert lines[1].startswith(" reader=") 63 | assert lines[2].startswith(" platform_name=") 64 | -------------------------------------------------------------------------------- /satpy/tests/etc/readers/fake1_1ds.yaml: -------------------------------------------------------------------------------- 1 | reader: 2 | name: fake1_1ds 3 | description: Fake reader used for easier testing with only one dataset 4 | reader: !!python/name:satpy.readers.core.yaml_reader.FileYAMLReader 5 | sensors: [fake_sensor] 6 | datasets: 7 | ds1: 8 | name: ds1 9 | resolution: 250 10 | calibration: "reflectance" 11 | file_type: fake_file1 12 | file_types: 13 | fake_file1: 14 | file_reader: !!python/name:satpy.tests.utils.FakeFileHandler 15 | file_patterns: ['fake1_1ds_{file_idx:d}.txt'] 16 | sensor: fake_sensor 17 | -------------------------------------------------------------------------------- /satpy/tests/etc/readers/fake2_1ds.yaml: -------------------------------------------------------------------------------- 1 | reader: 2 | name: fake2_1ds 3 | description: Fake reader used for easier testing 4 | reader: !!python/name:satpy.readers.core.yaml_reader.FileYAMLReader 5 | sensors: [fake_sensor2] 6 | datasets: 7 | ds2: 8 | name: ds2 9 | resolution: 250 10 | calibration: "reflectance" 11 | file_type: fake_file1 12 | file_types: 13 | fake_file1: 14 | file_reader: !!python/name:satpy.tests.utils.FakeFileHandler 15 | file_patterns: ['fake2_1ds_{file_idx:d}.txt'] 16 | sensor: fake_sensor2 17 | -------------------------------------------------------------------------------- /satpy/tests/etc/readers/fake2_3ds.yaml: -------------------------------------------------------------------------------- 1 | reader: 2 | name: fake2_1ds 3 | description: Fake reader used for easier testing 4 | reader: !!python/name:satpy.readers.core.yaml_reader.FileYAMLReader 5 | sensors: [fake_sensor2] 6 | datasets: 7 | lons: 8 | name: lons 9 | resolution: [250, 500, 1000] 10 | standard_name: longitude 11 | file_type: fake_file1 12 | lats: 13 | name: lats 14 | resolution: [250, 500, 1000] 15 | standard_name: latitude 16 | file_type: fake_file1 17 | ds2: 18 | name: ds2 19 | resolution: 250 20 | calibration: "reflectance" 21 | file_type: fake_file1 22 | coordinates: [lons, lats] 23 | file_types: 24 | fake_file1: 25 | file_reader: !!python/name:satpy.tests.utils.FakeFileHandler 26 | file_patterns: ['fake2_3ds_{file_idx:d}.txt'] 27 | sensor: fake_sensor2 28 | -------------------------------------------------------------------------------- /satpy/tests/etc/readers/fake3.yaml: -------------------------------------------------------------------------------- 1 | reader: 2 | name: fake3 3 | description: Fake reader used for easier testing 4 | reader: !!python/name:satpy.readers.core.yaml_reader.FileYAMLReader 5 | sensors: [fake_sensor] 6 | datasets: 7 | duplicate1: 8 | name: duplicate1 9 | wavelength: [0.1, 0.2, 0.3] 10 | file_type: fake_file1 11 | duplicate2: 12 | name: duplicate2 13 | wavelength: [0.1, 0.2, 0.3] 14 | file_type: fake_file1 15 | file_types: 16 | fake_file1: 17 | file_reader: !!python/name:satpy.tests.utils.FakeFileHandler 18 | file_patterns: ['fake3_{file_idx:d}.txt'] 19 | sensor: fake_sensor 20 | -------------------------------------------------------------------------------- /satpy/tests/etc/readers/fake4.yaml: -------------------------------------------------------------------------------- 1 | reader: 2 | name: fake4 3 | description: Fake reader used for easier testing 4 | reader: !!python/name:satpy.readers.core.yaml_reader.FileYAMLReader 5 | sensors: [fake_sensor_4] 6 | datasets: 7 | lons: 8 | name: lons 9 | resolution: [250, 500, 1000] 10 | standard_name: longitude 11 | file_type: fake_file4 12 | lats: 13 | name: lats 14 | resolution: [250, 500, 1000] 15 | standard_name: latitude 16 | file_type: fake_file4 17 | ds4_a: 18 | name: ds4_a 19 | resolution: 1000 20 | wavelength: [0.1, 0.2, 0.3] 21 | file_type: fake_file4 22 | coordinates: [lons, lats] 23 | ds4_b: 24 | name: ds4_b 25 | resolution: 250 26 | wavelength: [0.4, 0.5, 0.6] 27 | file_type: fake_file4 28 | coordinates: [lons, lats] 29 | file_types: 30 | fake_file4: 31 | file_reader: !!python/name:satpy.tests.utils.FakeFileHandler 32 | file_patterns: ['fake4_{file_idx:d}.txt'] 33 | sensor: fake_sensor_4 34 | -------------------------------------------------------------------------------- /satpy/tests/features/feature-load.feature: -------------------------------------------------------------------------------- 1 | Feature: Simple and intuitive scene loading (sc. 1) 2 | 3 | The scientific user explores the data and prototypes new algorithms. 4 | It needs access not only to the calibrated data, 5 | but also to the raw data and probably a majority of the metadata. 6 | The user would work with data locally, and it has to be easy to tell satpy where the data is. 7 | Providing filename templates or editing config file before starting working is a pain, so it should be avoided. 8 | 9 | To load the data should be a simple 1-step procedure. 10 | At load time, the user provides the data and metadata he/she needs, 11 | and if some items are unavailable/unaccessible, 12 | the user should be informed in a gentle but clear way (ie. no crash). 13 | The data and metadata available from the file have to be explorable, 14 | so that the user don’t need to guess what the (meta)data is called. 15 | 16 | @download 17 | Scenario: 1-step data loading 18 | Given data is available 19 | When user loads the data without providing a config file 20 | Then the data is available in a scene object 21 | 22 | @download 23 | Scenario: No crash when metadata is missing 24 | Given data is available 25 | When user loads the data without providing a config file 26 | And some items are not available 27 | Then the data is available in a scene object 28 | 29 | @download 30 | Scenario: Data is explorable 31 | Given data is available 32 | When user wants to know what data is available 33 | Then available datasets is returned 34 | 35 | Scenario: Accessing datasets by name prefers less modified datasets 36 | Given datasets with the same name 37 | When a dataset is retrieved by name 38 | Then the least modified version of the dataset is returned 39 | -------------------------------------------------------------------------------- /satpy/tests/features/feature-save.feature: -------------------------------------------------------------------------------- 1 | # Created by a001673 at 2015-12-07 2 | Feature: Simple and intuitive saving 3 | 4 | Visualization of the data is important and should be an easy one-line, like eg 5 | show(my_dataset). In a similar way, saving the data to disk should be simple, 6 | for example save(dataset, filename), with sensible defaults provided depending 7 | on the filename extension (eg. geotiff for .tif, netcdf for .nc). Saving 8 | several datasets at once would be nice to have. 9 | 10 | Scenario: 1-step showing dataset 11 | Given a dataset is available 12 | When the show command is called 13 | Then an image should pop up 14 | 15 | Scenario: 1-step saving dataset 16 | Given a dataset is available 17 | When the save_dataset command is called 18 | Then a file should be saved on disk 19 | 20 | Scenario: 1-step saving all datasets 21 | Given a bunch of datasets are available 22 | When the save_datasets command is called 23 | Then a bunch of files should be saved on disk 24 | -------------------------------------------------------------------------------- /satpy/tests/modifier_tests/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2018 - 2020 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | """Tests for modifiers.""" 16 | -------------------------------------------------------------------------------- /satpy/tests/modifier_tests/test_filters.py: -------------------------------------------------------------------------------- 1 | """Implementation of some image filters.""" 2 | 3 | import logging 4 | 5 | import dask.array as da 6 | import numpy as np 7 | import xarray as xr 8 | 9 | from satpy.modifiers.filters import Median 10 | 11 | 12 | def test_median(caplog): 13 | """Test the median filter modifier.""" 14 | caplog.set_level(logging.DEBUG) 15 | dims = "y", "x" 16 | coordinates = dict(x=np.arange(6), y=np.arange(6)) 17 | attrs = dict(units="K") 18 | median_filter_params = dict(size=3) 19 | name = "median_filter" 20 | median_filter = Median(median_filter_params, name=name) 21 | array = xr.DataArray(da.arange(36).reshape((6, 6)), coords=coordinates, dims=dims, attrs=attrs) 22 | res = median_filter([array]) 23 | filtered_array = np.array([[1, 2, 3, 4, 5, 5], 24 | [6, 7, 8, 9, 10, 11], 25 | [12, 13, 14, 15, 16, 17], 26 | [18, 19, 20, 21, 22, 23], 27 | [24, 25, 26, 27, 28, 29], 28 | [30, 30, 31, 32, 33, 34]]) 29 | np.testing.assert_allclose(res, filtered_array) 30 | assert res.dims == dims 31 | assert attrs.items() <= res.attrs.items() 32 | assert res.attrs["name"] == name 33 | np.testing.assert_equal(res.coords["x"], coordinates["x"]) 34 | np.testing.assert_equal(res.coords["y"], coordinates["y"]) 35 | assert "Apply median filtering with parameters {'size': 3}" in caplog.text 36 | -------------------------------------------------------------------------------- /satpy/tests/multiscene_tests/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2018-2023 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | """Unit tests for Multiscene.""" 19 | -------------------------------------------------------------------------------- /satpy/tests/reader_tests/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2017-2018 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | """The reader tests package.""" 19 | -------------------------------------------------------------------------------- /satpy/tests/reader_tests/gms/__init__.py: -------------------------------------------------------------------------------- 1 | """Unit tests for GMS reader.""" 2 | -------------------------------------------------------------------------------- /satpy/tests/reader_tests/modis_tests/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Satpy developers 2 | # 3 | # This file is part of satpy. 4 | # 5 | # satpy is free software: you can redistribute it and/or modify it under the 6 | # terms of the GNU General Public License as published by the Free Software 7 | # Foundation, either version 3 of the License, or (at your option) any later 8 | # version. 9 | # 10 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 11 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 12 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License along with 15 | # satpy. If not, see . 16 | """Unit tests for MODIS readers. 17 | 18 | This subdirectory mostly exists to have MODIS-based pytest fixtures only loaded 19 | for MODIS tests. 20 | 21 | """ 22 | -------------------------------------------------------------------------------- /satpy/tests/reader_tests/modis_tests/conftest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2023 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | """Setup and configuration for all reader tests.""" 19 | 20 | from ._modis_fixtures import ( # noqa: F401, I001 21 | modis_l1b_imapp_1000m_file, 22 | modis_l1b_imapp_geo_file, 23 | modis_l1b_nasa_1km_mod03_files, 24 | modis_l1b_nasa_mod02hkm_file, 25 | modis_l1b_nasa_mod02qkm_file, 26 | modis_l1b_nasa_mod03_file, 27 | modis_l1b_nasa_mod021km_file, 28 | modis_l2_imapp_mask_byte1_file, 29 | modis_l2_imapp_mask_byte1_geo_files, 30 | modis_l2_imapp_snowmask_file, 31 | modis_l2_imapp_snowmask_geo_files, 32 | modis_l2_nasa_mod06_file, 33 | modis_l2_nasa_mod35_file, 34 | modis_l2_nasa_mod35_mod03_files, 35 | modis_l2_nasa_mod99_file, 36 | modis_l3_nasa_mcd12q1_file, 37 | modis_l3_nasa_mod09_file, 38 | modis_l3_nasa_mod43_file, 39 | ) 40 | -------------------------------------------------------------------------------- /satpy/tests/reader_tests/modis_tests/test_modis_l3_mcd12q1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2019 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | """Unit tests for MODIS L2 HDF reader.""" 19 | 20 | from __future__ import annotations 21 | 22 | import dask.array as da 23 | 24 | from satpy import Scene, available_readers 25 | 26 | # NOTE: 27 | # The following fixtures are not defined in this file, but are used and injected by Pytest: 28 | # - modis_l3_nasa_mcd12q1_file 29 | 30 | 31 | class TestModisL3MCD12Q1: 32 | """Test MODIS L3 MCD12Q1 reader.""" 33 | 34 | def test_available_reader(self): 35 | """Test that MODIS L3 reader is available.""" 36 | assert "mcd12q1" in available_readers() 37 | 38 | def test_metadata(self, modis_l3_nasa_mcd12q1_file): 39 | """Test some basic metadata that should exist in the file.""" 40 | scene = Scene(reader="mcd12q1", filenames=modis_l3_nasa_mcd12q1_file) 41 | ds_name = "LC_Type2" 42 | scene.load([ds_name]) 43 | assert scene[ds_name].attrs["area"].description == "Tiled sinusoidal L3 MODIS area" 44 | assert scene[ds_name].attrs["sensor"] == "modis" 45 | 46 | def test_scene_available_datasets(self, modis_l3_nasa_mcd12q1_file): 47 | """Test that datasets are available.""" 48 | scene = Scene(reader="mcd12q1", filenames=modis_l3_nasa_mcd12q1_file) 49 | available_datasets = scene.all_dataset_names() 50 | assert len(available_datasets) > 0 51 | assert "LC_Type1" in available_datasets 52 | 53 | def test_load_l3_dataset(self, modis_l3_nasa_mcd12q1_file): 54 | """Load and check an L2 variable.""" 55 | scene = Scene(reader="mcd12q1", filenames=modis_l3_nasa_mcd12q1_file) 56 | ds_name = "LC_Type1" 57 | scene.load([ds_name]) 58 | assert ds_name in scene 59 | data_arr = scene[ds_name] 60 | assert isinstance(data_arr.data, da.Array) 61 | assert data_arr.attrs.get("resolution") == 500 62 | -------------------------------------------------------------------------------- /satpy/tests/reader_tests/test_clavrx/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2017-2018 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | """The clavrx reader tests package.""" 19 | -------------------------------------------------------------------------------- /satpy/tests/reader_tests/test_fci_base.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2017 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | 19 | """FCI base reader tests package.""" 20 | 21 | from satpy.readers.core.fci import calculate_area_extent 22 | from satpy.tests.utils import make_dataid 23 | 24 | 25 | def test_calculate_area_extent(): 26 | """Test function for calculate_area_extent.""" 27 | dataset_id = make_dataid(name="dummy", resolution=2000.0) 28 | 29 | area_dict = { 30 | "nlines": 5568, 31 | "ncols": 5568, 32 | "line_step": dataset_id["resolution"], 33 | "column_step": dataset_id["resolution"], 34 | } 35 | 36 | area_extent = calculate_area_extent(area_dict) 37 | 38 | expected = (-5568000.0, 5568000.0, 5568000.0, -5568000.0) 39 | 40 | assert area_extent == expected 41 | -------------------------------------------------------------------------------- /satpy/tests/reader_tests/test_hsaf_h5.py: -------------------------------------------------------------------------------- 1 | """Tests for the H-SAF H5 reader.""" 2 | 3 | import datetime as dt 4 | import os 5 | 6 | import h5py 7 | import numpy as np 8 | import pytest 9 | 10 | from satpy import Scene 11 | from satpy.area import get_area_def 12 | 13 | # real shape is 916, 1902 14 | SHAPE_SC = (916, 1902) 15 | SHAPE_SC_COLORMAP = (256, 3) 16 | AREA_X_OFFSET = 1211 17 | AREA_Y_OFFSET = 62 18 | 19 | 20 | @pytest.fixture(scope="session") 21 | def sc_h5_file(tmp_path_factory): 22 | """Create a fake HSAF SC HDF5 file.""" 23 | filename = tmp_path_factory.mktemp("data") / "h10_20221115_day_merged.H5" 24 | h5f = h5py.File(filename, mode="w") 25 | h5f.create_dataset("SC", SHAPE_SC, dtype=np.uint8) 26 | h5f.create_dataset("colormap", SHAPE_SC_COLORMAP, dtype=np.uint8) 27 | return str(filename) 28 | 29 | 30 | def _get_scene_with_loaded_sc_datasets(filename): 31 | """Return a scene with SC and SC_pal loaded.""" 32 | loaded_scene = Scene(filenames=[filename], reader="hsaf_h5") 33 | loaded_scene.load(["SC", "SC_pal"]) 34 | return loaded_scene 35 | 36 | 37 | def test_hsaf_sc_dataset(sc_h5_file): 38 | """Test the H-SAF SC dataset.""" 39 | loaded_scene = _get_scene_with_loaded_sc_datasets(sc_h5_file) 40 | assert loaded_scene["SC"].shape == SHAPE_SC 41 | 42 | 43 | def test_hsaf_sc_colormap_dataset(sc_h5_file): 44 | """Test the H-SAF SC_pal dataset.""" 45 | loaded_scene = _get_scene_with_loaded_sc_datasets(sc_h5_file) 46 | assert loaded_scene["SC_pal"].shape == SHAPE_SC_COLORMAP 47 | 48 | 49 | def test_hsaf_sc_datetime(sc_h5_file): 50 | """Test the H-SAF reference time.""" 51 | loaded_scene = _get_scene_with_loaded_sc_datasets(sc_h5_file) 52 | fname = os.path.basename(sc_h5_file) 53 | dtstr = fname.split("_")[1] 54 | obs_time = dt.datetime.strptime(dtstr, "%Y%m%d") 55 | assert loaded_scene["SC"].attrs["data_time"] == obs_time 56 | 57 | 58 | def test_hsaf_sc_areadef(sc_h5_file): 59 | """Test the H-SAF SC area definition.""" 60 | loaded_scene = _get_scene_with_loaded_sc_datasets(sc_h5_file) 61 | fd_def = get_area_def("msg_seviri_fes_3km") 62 | hsaf_def = fd_def[AREA_Y_OFFSET:AREA_Y_OFFSET+SHAPE_SC[0], AREA_X_OFFSET:AREA_X_OFFSET+SHAPE_SC[1]] 63 | assert loaded_scene["SC"].area == hsaf_def 64 | -------------------------------------------------------------------------------- /satpy/tests/reader_tests/test_vii_utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright (c) 2020 Satpy developers 5 | # 6 | # satpy is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # satpy is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License 17 | # along with satpy. If not, see . 18 | 19 | """The vii_utils reader tests package.""" 20 | 21 | import unittest 22 | 23 | import satpy.readers.core.vii 24 | 25 | # Constants to be tested 26 | C1 = 1.191062e+8 27 | C2 = 1.4387863e+4 28 | TIE_POINTS_FACTOR = 8 29 | SCAN_ALT_TIE_POINTS = 4 30 | MEAN_EARTH_RADIUS = 6371008.7714 31 | 32 | 33 | class TestViiUtils(unittest.TestCase): 34 | """Test the vii_utils module.""" 35 | 36 | def test_constants(self): 37 | """Test the constant values.""" 38 | # Test the value of the constants 39 | assert satpy.readers.core.vii.C1 == C1 40 | assert satpy.readers.core.vii.C2 == C2 41 | assert satpy.readers.core.vii.TIE_POINTS_FACTOR == TIE_POINTS_FACTOR 42 | assert satpy.readers.core.vii.SCAN_ALT_TIE_POINTS == SCAN_ALT_TIE_POINTS 43 | assert satpy.readers.core.vii.MEAN_EARTH_RADIUS == MEAN_EARTH_RADIUS 44 | -------------------------------------------------------------------------------- /satpy/tests/reader_tests/utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2022 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | """Utilities for reader tests.""" 19 | 20 | import inspect 21 | 22 | 23 | def default_attr_processor(root, attr): 24 | """Do not change the attribute.""" 25 | return attr 26 | 27 | 28 | def fill_h5(root, contents, attr_processor=default_attr_processor): 29 | """Fill hdf5 file with the given contents. 30 | 31 | Args: 32 | root: hdf5 file rott 33 | contents: Contents to be written into the file 34 | attr_processor: A method for modifying attributes before they are 35 | written to the file. 36 | """ 37 | for key, val in contents.items(): 38 | if key in ["value", "attrs"]: 39 | continue 40 | if "value" in val: 41 | root[key] = val["value"] 42 | else: 43 | grp = root.create_group(key) 44 | fill_h5(grp, contents[key]) 45 | if "attrs" in val: 46 | for attr_name, attr_val in val["attrs"].items(): 47 | root[key].attrs[attr_name] = attr_processor(root, attr_val) 48 | 49 | 50 | def get_jit_methods(module): 51 | """Get all jit-compiled methods in a module.""" 52 | res = {} 53 | module_name = module.__name__ 54 | members = inspect.getmembers(module) 55 | for member_name, obj in members: 56 | if _is_jit_method(obj): 57 | full_name = f"{module_name}.{member_name}" 58 | res[full_name] = obj 59 | return res 60 | 61 | 62 | def _is_jit_method(obj): 63 | return hasattr(obj, "py_func") 64 | -------------------------------------------------------------------------------- /satpy/tests/scene_tests/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 Satpy developers 2 | # 3 | # This file is part of satpy. 4 | # 5 | # satpy is free software: you can redistribute it and/or modify it under the 6 | # terms of the GNU General Public License as published by the Free Software 7 | # Foundation, either version 3 of the License, or (at your option) any later 8 | # version. 9 | # 10 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 11 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 12 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 13 | # 14 | # You should have received a copy of the GNU General Public License along with 15 | # satpy. If not, see . 16 | """Tests of the Scene class.""" 17 | -------------------------------------------------------------------------------- /satpy/tests/test_cf_roundtrip.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2017-2019 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | """Test roundripping the cf writer and reader.""" 19 | 20 | import os 21 | 22 | import numpy as np 23 | 24 | from satpy import Scene 25 | from satpy.tests.reader_tests.test_viirs_compact import fake_dnb, fake_dnb_file # noqa 26 | 27 | # NOTE: 28 | # The following fixtures are not defined in this file, but are used and injected by Pytest: 29 | # - tmp_path 30 | 31 | 32 | def test_cf_roundtrip(fake_dnb_file, tmp_path): # noqa 33 | """Test the cf writing reading cycle.""" 34 | dnb_filename = os.fspath(fake_dnb_file) 35 | write_scn = Scene(filenames=[dnb_filename], reader="viirs_compact") 36 | write_scn.load(["DNB"]) 37 | 38 | satpy_cf_file = os.fspath(tmp_path / "npp-viirs-20191025061125-20191025061247.nc") 39 | write_scn.save_datasets(writer="cf", filename=satpy_cf_file) 40 | read_scn = Scene(filenames=[satpy_cf_file], reader="satpy_cf_nc") 41 | read_scn.load(["DNB"]) 42 | 43 | write_array = write_scn["DNB"] 44 | read_array = read_scn["DNB"] 45 | 46 | np.testing.assert_allclose(write_array.values, read_array.values) 47 | -------------------------------------------------------------------------------- /satpy/tests/test_crefl_utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2019 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | """Test CREFL rayleigh correction functions.""" 19 | import unittest 20 | 21 | 22 | class TestCreflUtils(unittest.TestCase): 23 | """Test crefl_utils.""" 24 | 25 | def test_get_atm_variables_abi(self): 26 | """Test getting atmospheric variables for ABI.""" 27 | import numpy as np 28 | 29 | from satpy.modifiers._crefl_utils import _ABIAtmosphereVariables 30 | atm_vars = _ABIAtmosphereVariables( 31 | 21.71342113, 77.14385758, 56.214566960, 32 | 0.17690244, 6.123234e-17, 530.61332168, 405., 33 | 0.0043149700000000004, 0.0037296, 0.014107995000000002, 0.052349, 34 | ) 35 | sphalb, rhoray, TtotraytH2O, tOG = atm_vars() 36 | assert abs(np.array(sphalb) - 0.045213532544630494) < 1e-10 37 | assert abs(rhoray - 2.2030281148621356) < 1e-10 38 | assert abs(TtotraytH2O - 0.30309880915889087) < 1e-10 39 | assert abs(tOG - 0.5969089524560548) < 1e-10 40 | -------------------------------------------------------------------------------- /satpy/tests/test_testing.py: -------------------------------------------------------------------------------- 1 | """Tests for the testing helper module.""" 2 | 3 | import numpy as np 4 | import xarray as xr 5 | 6 | from satpy import Scene 7 | from satpy.area import get_area_def 8 | from satpy.testing import fake_satpy_reading 9 | 10 | 11 | def test_fake_reading(tmp_path): 12 | """Test that the fake reading context manager populates a scene.""" 13 | input_files = [tmp_path / "my_input_file"] 14 | area = get_area_def("euro4") 15 | random = np.random.default_rng() 16 | somedata = xr.DataArray(random.uniform(size=area.shape), dims=["y", "x"]) 17 | somedata.attrs["area"] = area 18 | 19 | channel = "VIS006" 20 | 21 | scene_dict = {channel: somedata} 22 | 23 | with fake_satpy_reading(scene_dict): 24 | scene = Scene(input_files, reader="dummy_reader") 25 | scene.load([channel]) 26 | assert scene[channel] is somedata 27 | -------------------------------------------------------------------------------- /satpy/tests/writer_tests/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2017-2019 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | """The writer tests package.""" 19 | -------------------------------------------------------------------------------- /satpy/tests/writer_tests/test_utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2019 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | """Tests for writer utilities.""" 19 | 20 | import unittest 21 | 22 | import satpy.writers.utils as wutils 23 | 24 | 25 | class WriterUtilsTest(unittest.TestCase): 26 | """Test various writer utilities.""" 27 | 28 | def test_flatten_dict(self): 29 | """Test dictionary flattening.""" 30 | d = {"a": 1, "b": {"c": 1, "d": {"e": 1, "f": {"g": [1, 2]}}}} 31 | expected = {"a": 1, 32 | "b_c": 1, 33 | "b_d_e": 1, 34 | "b_d_f_g": [1, 2]} 35 | assert wutils.flatten_dict(d) == expected 36 | -------------------------------------------------------------------------------- /satpy/writers/utils.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # Copyright (c) 2019 Satpy developers 4 | # 5 | # This file is part of satpy. 6 | # 7 | # satpy is free software: you can redistribute it and/or modify it under the 8 | # terms of the GNU General Public License as published by the Free Software 9 | # Foundation, either version 3 of the License, or (at your option) any later 10 | # version. 11 | # 12 | # satpy is distributed in the hope that it will be useful, but WITHOUT ANY 13 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 14 | # A PARTICULAR PURPOSE. See the GNU General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU General Public License along with 17 | # satpy. If not, see . 18 | """Writer utilities.""" 19 | 20 | 21 | def flatten_dict(d, parent_key="", sep="_"): 22 | """Flatten a nested dictionary. 23 | 24 | Based on https://stackoverflow.com/a/6027615/5703449 25 | """ 26 | items = [] 27 | for k, v in d.items(): 28 | new_key = parent_key + sep + k if parent_key else k 29 | if isinstance(v, dict): 30 | items.extend(flatten_dict(v, parent_key=new_key, sep=sep).items()) 31 | else: 32 | items.append((new_key, v)) 33 | return dict(items) 34 | --------------------------------------------------------------------------------