pytroll / satpy

Python package for earth-observing satellite data processing
http://satpy.readthedocs.org/en/latest/
GNU General Public License v3.0
1.07k stars 296 forks source link

Connecting VNP14IMG Swath Data with VNP03IMG Geolocation Data #2945

Open jiyeon-kim20 opened 3 weeks ago

jiyeon-kim20 commented 3 weeks ago

Hello,

I am working with VIIRS satellite data and currently have two files:

  1. VNP14IMG - Swath data without geolocation.
  2. VNP03IMG - Geolocation data.

Each file uses a different reader:

viirs_l1b for VNP03IMG viirs_edr_active_fires for VNP14IMG (for which I have already made a custom reader in the YAML file).

scn = Scene(filenames={
    'viirs_l1b': ['/content/VNP03IMG.A2023221.1124.002.2023221175939.nc'],
    'viirs_edr_active_fires': ['/content/VNP14IMG.A2023221.1124.002.2024080020549.nc']
                       })

Given these differences, how can I connect or merge the geolocation data from VNP03IMG with the swath data from VNP14IMG?

Thank you!

djhoese commented 3 weeks ago

Thanks for filing this question. There are two paths to a solution, but I need more information about these files. Mainly, are these new official fires products from NASA? Are these imagery versions of the fire detection (isn't that a waste of space?)?

To get something working I would either edit the viirs_edr_active_fires as it sounds like you've already started or update the viirs_edr reader. If this is some kind of official EDR product it might be nice to update viirs_edr to handle it if the loading resembles/matches the existing files handled by that reader.

For the viirs_edr_active_fires case, I would copy the geolocation file type definition and lon/lat definitions from viirs_l1b and place them into viirs_edr_active_fires.yaml. Or make a whole new YAML file for a new reader if you run into issues. The viirs_edr_active_fires.yaml file would point to the python code for viirs l1b and for the viirs active fires. That's fine.

Bottom line: the "connecting" of these two file types happens via duplication in the reader YAML rather than anything fancy on the Scene-level.

jiyeon-kim20 commented 3 weeks ago

/usr/local/lib/python3.10/dist-packages/satpy/etc/readers/viirs_edr_active_fires.yaml /usr/local/lib/python3.10/dist-packages/satpy/readers/viirs_edr_active_fires.py

Thank you so much!

Yes, they are all the official files (I am wondering about the purpose of this data, too haha.)

I revised viirs_edr_active_fires.yaml like below. I added swath and geolocation data under the yaml like below. vgeoi is for geolocation and fire_l2_viirs for swath data. Under datasets, I assign coordinates: [i_lon, i_lat] to fire_mask.

file_types:
    vgeoi:
        file_reader: !!python/name:satpy.readers.viirs_edr_active_fires.VIIRSActiveFiresFileHandler
        file_patterns:
            - 'VGEOI_{platform_shortname}_d{start_time:%Y%m%d_t%H%M%S}_c{creation_time:%Y%m%d%H%M%S}.nc'
            - 'V{satellite_name:2s}03IMG.A{start_time:%Y%j.%H%M}.{collection_number:3d}.{creation_time:%Y%j%H%M%S}.nc'
            - 'V{platform_shortname:2s}03IMG_NRT.A{start_time:%Y%j.%H%M}.{collection_number:3d}.nc'
            - 'V{platform_shortname:2s}03IMG_NRT.A{start_time:%Y%j.%H%M}.{collection_number:3d}.{creation_time:%Y%j%H%M%S}.nc'

    fire_l2_viirs:
        file_reader: !!python/name:satpy.readers.viirs_edr_active_fires.VIIRSActiveFiresFileHandler
        file_patterns:
            - 'V{satellite_name}14IMG.A{start_time:%Y%j.%H%M}.{collection:03d}.{production_time:%Y%j%H%M%S}.nc'

datasets:
    i_lon:
      name: i_lon
      resolution: 371
      file_type: vgeoi
      file_key: geolocation_data/longitude
      units: degrees
      standard_name: longitude

    i_lat:
      name: i_lat
      resolution: 371
      file_type: vgeoi
      file_key: geolocation_data/latitude
      units: degrees
      standard_name: latitude

    fire_mask:
      name: fire_mask
      long_name: VIIRS Fire Mask
      units: '1'
      file_key: fire mask
      flag_meanings: [
        'Missing input data',
        'Not processed',
        'Not processed',
        'Non-fire water',
        'Cloud',
        'Non-fire land',
        'Unknown',
        'low confidence',
        'nominal confidence',
        'high confidence'
        ]
      coordinates: [i_lon, i_lat]
      flag_values: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
      file_type: [fire_l2_viirs]
      standard_name: fire_mask

However, when I try to crop it like below, I got an error. What I want to do is after connecting swath with geolocation data at YAML level (as you told), to crop and extract geolocated grid data based on specific area. If I need to open new issue, please let me know. I really appreciate your help!

scn = Scene(filenames={
    'viirs_edr_active_fires': ['/content/VNP14IMG.A2023221.1124.002.2024080020549.nc',
                               '/content/VNP03IMG.A2023221.1124.002.2023221175939.nc']
                       })

scn.load(['fire_mask'])

ll_bbox = (-161.0, 18.5, -154.5, 22.5)
cropped_scn = scn.crop(ll_bbox=ll_bbox)
---------------------------------------------------------------------------
NotImplementedError                       Traceback (most recent call last)
[<ipython-input-1-bb5bfed7a33d>](https://localhost:8080/#) in <cell line: 13>()
     11 scn.load(['fire_mask', 'longitude', 'latitude', 'i_lon', 'i_lat'])
     12 
---> 13 cropped_scn = scn.crop(ll_bbox=ll_bbox)

2 frames
[/usr/local/lib/python3.10/dist-packages/satpy/scene.py](https://localhost:8080/#) in crop(self, area, ll_bbox, xy_bbox, dataset_ids)
    742         if isinstance(area, str):
    743             area = get_area_def(area)
--> 744         new_coarsest_area, min_y_slice, min_x_slice = self._slice_area_from_bbox(
    745             coarsest_area, area, ll_bbox, xy_bbox)
    746         new_target_areas = {}

[/usr/local/lib/python3.10/dist-packages/satpy/scene.py](https://localhost:8080/#) in _slice_area_from_bbox(src_area, dst_area, ll_bbox, xy_bbox)
    625                 src_area.crs, src_area.width, src_area.height,
    626                 xy_bbox)
--> 627         x_slice, y_slice = src_area.get_area_slices(dst_area)
    628         return src_area[y_slice, x_slice], y_slice, x_slice
    629 

[/usr/local/lib/python3.10/dist-packages/pyresample/geometry.py](https://localhost:8080/#) in get_area_slices(self, area_to_cover)
    620     def get_area_slices(self, area_to_cover):
    621         """Compute the slice to read based on an `area_to_cover`."""
--> 622         raise NotImplementedError
    623 
    624     @property

NotImplementedError:
djhoese commented 3 weeks ago

I'd love to see a pull request to add this new file type to the reader in Satpy! Nice job.

As for the error, cropping of swath data is not supported (scn['fire_mask'].attrs["area"] is a SwathDefinition object). This is because a swath is not necessarily gridded and we don't know how big each pixel is or where it is relative to the other pixels without looking at every single pixel. This is true for VIIRS. To get the data for a specific region you'll need to create an AreaDefinition object and do new_scn = scn.resample(my_area).