Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Blending Satellite Images in a smooth way #2758

Open
akasom89 opened this issue Mar 12, 2024 · 5 comments
Open

Blending Satellite Images in a smooth way #2758

akasom89 opened this issue Mar 12, 2024 · 5 comments
Labels

Comments

@akasom89
Copy link

There is a great feature named "Multiscene" in Satpy right now, which allows for creating global coverage of different geostationary satellite images. However, the transitions between scenes are currently not smooth, and the steps from one scene to another are easily observable.

I am suggesting an enhancement to improve the visual appeal of the Multiscene feature by making the transitions between satellite images smoother. This could involve applying functions or algorithms that smooth out the transition between scenes, resulting in a more visually pleasing presentation of the data.

I also would like to know if it is currently possible at all to achieve smoother transitions between geostationary satellite images using the Multiscene feature (or combination of different features) in Satpy.

sharp_edges

@gerritholl
Copy link
Collaborator

gerritholl commented Mar 13, 2024

It should not be as discontinuous as that. Are you perhaps combining timesteps that are too far apart?

This is what our pytroll-produced world composite image looks like from a couple of days ago (IR window channels). We can see some discontinuities, but they are much less severe than in your example.

image

Note that we did not use MultiScene, but a multi-step procedure in which we first resample individual images onto the same global grid, write those individual images to NetCDF, then read those with a different reader, combine them with a composite, enhance, and ready.

@akasom89
Copy link
Author

Thanks @gerritholl for your detailed answer. Your output is truly much better than mine. Initially, I guessed the issue might be due to the way the MultiScene.blend stack function treats the process. However, some questions have arisen in my mind:

-Which compositor was used for this purpose?
-Why write and read again? Isn't it possible to pipe the Scene/XArray directly to the compositor? (Because based on my experience, it may take minutes to be done.)

Thanks in advance! I would also appreciate it if you could share the code if possible.

@gerritholl
Copy link
Collaborator

In code, it would be possible to pipe it directly, but in production we do this entirely with configuration files using pytroll-collectors and trollflow2. Our configuration is a bit too complex to post here in detail, but the approach:

  1. five instances of trollstalker and segment-gatherer (from pytroll-collectors) observe and gather incoming L1 satellite data;
  2. five instances of trollflow2 read those data and load L1 data, then resample it to a single area wcm, store it to NetCDF using the Satpy CF writer (without enhancements), then send a posttroll message;
  3. those posttroll messages are collected by another instance of segment-gatherer;
  4. a trollflow2 instance reads those NetCDF files using a custom reader world-nc-image, that uses SatpyNCFileHandler, and loads a custom composite that is based on LongitudeMaskingCompositor and MultiFiller (where we define the longitude cutoffs between the different satellites);
  5. the result is enhanced and written to the GeoTIFF image listed above.

There are various subtleties, such as dealing with the different repeat cycles (currently 2 × 15 minutes; 3 × 10 minutes; with MTG-I1 FCI it will become 1 × 15 minutes, 4 × 10 minutes), and dealing with missing or delayed data (with masking and clipping, we in this case avoid the cutoff and use the adjecent image up to the edge).

It could be done in Satpy as well, without pytroll-collectors or trollflow2. The advantage of the intermediate files is that you can then use a dedicated reader and corresponding composite to put it all together using LongitudeMaskingCompositor and MultiFiller. You could probably get satpy to recognise those configurations even without storing intermediate files, but good luck with that (we use ramfs for our intermediate files, so it doesn't hurt performance much). You would still need to define a custom reader providing a dataset for each component satellite, and a composite putting them together:

reader:
    name: world-nc-image
    description: reads intermediate NetCDF files for world composite
    reader: !!python/name:satpy.readers.yaml_reader.FileYAMLReader
    sensors: [world-images]

file_types:
    graphic_goes_east:
      file_reader:  !!python/name:satpy.readers.satpy_cf_nc.SatpyCFFileHandler
      file_patterns:
         - 'goes-east-{start_time:%Y%m%d%H%M%S}-{end_time:%Y%m%d%H%M%S}.nc'
    graphic_zds:
      file_reader: !!python/name:satpy.readers.satpy_cf_nc.SatpyCFFileHandler
      file_patterns:
         - 'zds-{start_time:%Y%m%d%H%M%S}-{end_time:%Y%m%d%H%M%S}.nc'
# similar for the others

datasets:
  image_goes_east:
    nc_store_name: C13
    name: image_goes_east
    file_type: graphic_goes_east
  image_zds:
    nc_store_name: IR_108
    name: image_zds
    file_type: graphic_zds
# similar for the others

the composite would be approximately:

  world_comp_zds_masked:
    compositor: !!python/name:satpy.composites.LongitudeMaskingCompositor
    prerequisites:
    - image_zds
    standard_name: world_comp_zds_masked
    lon_min: -37.5
    lon_max: 22.75

  world_comp_goes_east_masked:
    compositor: !!python/name:satpy.composites.LongitudeMaskingCompositor
    prerequisites:
    - image_goes_east
    standard_name: world_comp_goes_east_masked
    lon_min: -105.
    lon_max: -37.5

# similar for the others

  world_comp:
    compositor: !!python/name:satpy.composites.MultiFiller
    prerequisites:
    - name: world_comp_zds_masked
    - name: world_comp_goes_masked
    - # similar for the others
    standard_name: world_comp

Then you just need to load each component satellite, resample to a common world grid, write to NetCDF (no enhancing, and make sure the filenames match the pattern), then load world_comp from the resulting NetCDF.

@akasom89
Copy link
Author

Thanks @gerritholl for providing such a detailed and informative answer.

@djhoese
Copy link
Member

djhoese commented Mar 13, 2024

@akasom89 I agree with @gerritholl that your transitions between satellites seems extreme. You could use the MultiScene and stack them. You could go further than a basic stack and define some weights:

https://satpy.readthedocs.io/en/stable/multiscene.html#stacking-scenes-using-weights

But you're still going to have difficulties as the position of the sun on each image is going to be very different. I've seen some people (outside the pytroll community) define individual hour-wide portions of the geostationary images at local noon time and then join all of these images together.

I think there are an endless number of methods for joining geostationary satellite images together and which result is "best" will be subjective and may be dependent on the amount of complexity put into the technique.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants