satpy.modifiers.parallax module

Parallax correction.

Routines related to parallax correction using datasets involving height, such as cloud top height.

The geolocation of (geostationary) satellite imagery is calculated by agencies or in satpy readers with the assumption of a clear view from the satellite to the geoid. When a cloud blocks the view of the Earth surface or the surface is above sea level, the geolocation is not accurate for the cloud or mountain top. This module contains routines to correct imagery such that pixels are shifted or interpolated to correct for this parallax effect.

Parallax correction is currently only supported for (cloud top) height that arrives on an AreaDefinition, such as is standard for geostationary satellites. Parallax correction with data described by a SwathDefinition, such as is common for polar satellites, is not (yet) supported.

See also the Modifiers page in the documentation for an introduction to parallax correction as a modifier in Satpy.

exception satpy.modifiers.parallax.IncompleteHeightWarning[source]

Bases: UserWarning

Raised when heights only partially overlap with area to be corrected.

exception satpy.modifiers.parallax.MissingHeightError[source]

Bases: ValueError

Raised when heights do not overlap with area to be corrected.

class satpy.modifiers.parallax.ParallaxCorrection(base_area, debug_mode=False)[source]

Bases: object

Parallax correction calculations.

This class contains higher-level functionality to wrap the parallax correction calculations in get_parallax_corrected_lonlats(). The class is initialised using a base area, which is the area for which a corrected geolocation will be calculated. The resulting object is a callable. Calling the object with an array of (cloud top) heights returns a SwathDefinition describing the new , corrected geolocation. The cloud top height should cover at least the area for which the corrected geolocation will be calculated.

Note that the ctth dataset must contain satellite location metadata, such as set in the orbital_parameters dataset attribute that is set by many Satpy readers. It is essential that the datasets to be corrected are coming from the same platform as the provided cloud top height.

A note on the algorithm and the implementation. Parallax correction is inherently an inverse problem. The reported geolocation in satellite data files is the true location plus the parallax error. Therefore, this class first calculates the true geolocation (using get_parallax_corrected_lonlats()), which gives a shifted longitude and shifted latitude on an irregular grid. The difference between the original and the shifted grid is the parallax error or shift. The magnitude of this error can be estimated with get_surface_parallax_displacement(). With this difference, we need to invert the parallax correction to calculate the corrected geolocation. Due to parallax correction, high clouds shift a lot, low clouds shift a little, and cloud-free pixels shift not at all. The shift may result in zero, one, two, or more source pixel onto a destination pixel. Physically, this corresponds to the situation where a narrow but high cloud is viewed at a large angle. The cloud may occupy two or more pixels when viewed at a large angle, but only one when viewed straight from above. To accurately reproduce this perspective, the parallax correction uses the BucketResampler class, specifically the get_abs_max() method, to retain only the largest absolute shift (corresponding to the highest cloud) within each pixel. Any other resampling method at this step would yield incorrect results. When cloud moves over clear-sky, the clear-sky pixel is unshifted and the shift is located exactly in the centre of the grid box, so nearest-neighbour resampling would lead to such shifts being deselected. Other resampling methods would average large shifts with small shifts, leading to unpredictable results. Now the reprojected shifts can be applied to the original lat/lon, returning a new SwathDefinition. This is is the object returned by corrected_area().

This procedure can be configured as a modifier using the ParallaxCorrectionModifier class. However, the modifier can only be applied to one dataset at the time, which may not provide optimal performance, although dask should reuse identical calculations between multiple channels.

Initialise parallax correction class.

Parameters:
  • base_area (AreaDefinition) – Area for which calculated geolocation will be calculated.

  • debug_mode (bool) – Store diagnostic information in self.diagnostics. This attribute always apply to the most recently applied operation only.

_check_overlap(cth_dataset)[source]

Ensure cth_dataset is usable for parallax correction.

Checks the coverage of cth_dataset compared to the base_area. If the entirety of base_area is covered by cth_dataset, do nothing. If only part of base_area is covered by cth_dataset, raise a IncompleteHeightWarning. If none of base_area is covered by cth_dataset, raise a MissingHeightError.

_get_corrected_lon_lat(base_lon, base_lat, shifted_area)[source]

Calculate the corrected lon/lat based from the shifted area.

After calculating the shifted area based on get_parallax_corrected_lonlats(), we invert the parallax error and estimate where those pixels came from. For details on the algorithm, see the class docstring.

static _get_swathdef_from_lon_lat(lon, lat)[source]

Return a SwathDefinition from lon/lat.

Turn ndarrays describing lon/lat into xarray with dimensions y, x, then use these to create a SwathDefinition.

_prepare_cth_dataset(cth_dataset, resampler='nearest', radius_of_influence=50000, lonlat_chunks=1024)[source]

Prepare CTH dataset.

Set cloud top height to zero wherever lat/lon are valid but CTH is undefined. Then resample onto the base area.

corrected_area(cth_dataset, cth_resampler='nearest', cth_radius_of_influence=50000, lonlat_chunks=1024)[source]

Return the parallax corrected SwathDefinition.

Using the cloud top heights provided in cth_dataset, calculate the pyresample.geometry.SwathDefinition that estimates the geolocation for each pixel if it had been viewed from straight above (without parallax error). The cloud top height will first be resampled onto the area passed upon class initialisation in __init__(). Pixels that are invisible after parallax correction are not retained but get geolocation NaN.

Parameters:
  • cth_dataset (DataArray) – Cloud top height in meters. The variable attributes must contain an area attribute describing the geolocation in a pyresample-aware way, and they must contain satellite orbital parameters. The dimensions must be (y, x). For best performance, this should be a dask-based DataArray.

  • cth_resampler (string, optional) – Resampler to use when resampling the (cloud top) height to the base area. Defaults to “nearest”.

  • cth_radius_of_influence (number, optional) – Radius of influence to use when resampling the (cloud top) height to the base area. Defaults to 50000.

  • lonlat_chunks (int, optional) – Chunking to use when calculating lon/lats. Probably the default (1024) should be fine.

Returns:

SwathDefinition describing parallax corrected geolocation.

class satpy.modifiers.parallax.ParallaxCorrectionModifier(name, prerequisites=None, optional_prerequisites=None, **kwargs)[source]

Bases: ModifierBase

Modifier for parallax correction.

Apply parallax correction as a modifier. Uses the ParallaxCorrection class, which in turn uses the get_parallax_corrected_lonlats() function. See the documentation there for details on the behaviour.

To use this, add to composites/visir.yaml within SATPY_CONFIG_PATH something like:

sensor_name: visir

modifiers:
  parallax_corrected:
    modifier: !!python/name:satpy.modifiers.parallax.ParallaxCorrectionModifier
    prerequisites:
      - "ctth_alti"
    dataset_radius_of_influence: 50000

composites:

  parallax_corrected_VIS006:
    compositor: !!python/name:satpy.composites.SingleBandCompositor
    prerequisites:
      - name: VIS006
        modifiers: [parallax_corrected]

Here, ctth_alti is CTH provided by the nwcsaf-geo reader, so to use it one would have to pass both on scene creation:

sc = Scene({"seviri_l1b_hrit": files_l1b, "nwcsaf-geo": files_l2})
sc.load(["parallax_corrected_VIS006"])

The modifier takes optional global parameters, all of which are optional. They affect various steps in the algorithm. Setting them may impact performance:

cth_resampler

Resampler to use when resampling (cloud top) height to the base area. Defaults to “nearest”.

cth_radius_of_influence

Radius of influence to use when resampling the (cloud top) height to the base area. Defaults to 50000.

lonlat_chunks

Chunk size to use when obtaining longitudes and latitudes from the area definition. Defaults to 1024. If you set this to None, then parallax correction will involve premature calculation. Changing this may or may not make parallax correction slower or faster.

dataset_radius_of_influence

Radius of influence to use when resampling the dataset onto the swathdefinition describing the parallax-corrected area. Defaults to 50000. This always uses nearest neighbour resampling.

Alternately, you can use the lower-level API directly with the ParallaxCorrection class, which may be more efficient if multiple datasets need to be corrected. RGB Composites cannot be modified in this way (i.e. you can’t replace “VIS006” by “natural_color”). To get a parallax corrected RGB composite, create a new composite where each input has the modifier applied. The parallax calculation should only occur once, because calculations are happening via dask and dask should reuse the calculation.

Initialise the compositor.

_get_corrector(base_area)[source]
satpy.modifiers.parallax._calculate_slant_cloud_distance(height, elevation)[source]

Calculate slant cloud to ground distance.

From (cloud top) height and satellite elevation, calculate the slant cloud-to-ground distance along the line of sight of the satellite.

satpy.modifiers.parallax._get_parallax_shift_xyz(sat_lon, sat_lat, sat_alt, lon, lat, parallax_distance)[source]

Calculate the parallax shift in cartesian coordinates.

From satellite position and cloud position, get the parallax shift in cartesian coordinates:

Parameters:
  • sat_lon (number) – Satellite longitude in geodetic coordinates [degrees]

  • sat_lat (number) – Satellite latitude in geodetic coordinates [degrees]

  • sat_alt (number) – Satellite altitude above the Earth surface [m]

  • lon (array or number) – Longitudes of pixel or pixels to be corrected, in geodetic coordinates [degrees]

  • lat (array or number) – Latitudes of pixel/pixels to be corrected, in geodetic coordinates [degrees]

  • parallax_distance (array or number) – Cloud to ground distance with parallax effect [m].

Returns:

Parallax shift in cartesian coordinates in meter.

satpy.modifiers.parallax._get_satellite_elevation(sat_lon, sat_lat, sat_alt, lon, lat)[source]

Get satellite elevation.

Get the satellite elevation from satellite lon/lat/alt for positions lon/lat.

satpy.modifiers.parallax._get_satpos_from_cth(cth_dataset)[source]

Obtain satellite position from CTH dataset, height in meter.

From a CTH dataset, obtain the satellite position lon, lat, altitude/m, either directly from orbital parameters, or, when missing, from the platform name using pyorbital and skyfield.

satpy.modifiers.parallax.get_parallax_corrected_lonlats(sat_lon, sat_lat, sat_alt, lon, lat, height)[source]

Calculate parallax corrected lon/lats.

Satellite geolocation generally assumes an unobstructed view of a smooth Earth surface. In reality, this view may be obstructed by clouds or mountains.

If the view of a pixel at location (lat, lon) is blocked by a cloud at height h, this function calculates the (lat, lon) coordinates of the cloud above/in front of the invisible surface.

For scenes that are only partly cloudy, the user might set the cloud top height for clear-sky pixels to NaN. This function will return a corrected lat/lon as NaN as well. The user can use the original lat/lon for those pixels or use the higher level ParallaxCorrection class.

This function assumes a spherical Earth.

Note

Be careful with units! This code expects sat_alt and height to be in meter above the Earth’s surface. You may have to convert your input correspondingly. Cloud Top Height is usually reported in meters above the Earth’s surface, rarely in km. Satellite altitude may be reported in either m or km, but orbital parameters are usually in relation to the Earth’s centre. The Earth radius from pyresample is reported in km.

Parameters:
  • sat_lon (number) – Satellite longitude in geodetic coordinates [degrees]

  • sat_lat (number) – Satellite latitude in geodetic coordinates [degrees]

  • sat_alt (number) – Satellite altitude above the Earth surface [m]

  • lon (array or number) – Longitudes of pixel or pixels to be corrected, in geodetic coordinates [degrees]

  • lat (array or number) – Latitudes of pixel/pixels to be corrected, in geodetic coordinates [degrees]

  • height (array or number) – Heights of pixels on which the correction will be based. Typically this is the cloud top height. [m]

Returns:

Corrected geolocation

Corrected geolocation (lon, lat) in geodetic coordinates for the pixel(s) to be corrected. [degrees]

Return type:

tuple[float, float]

satpy.modifiers.parallax.get_surface_parallax_displacement(sat_lon, sat_lat, sat_alt, lon, lat, height)[source]

Calculate surface parallax displacement.

Calculate the displacement due to parallax error. Input parameters are identical to get_parallax_corrected_lonlats().

Returns:

parallax displacement in meter

Return type:

number or array