Ejemplo n.º 1
0
 def crop(self, w=DEFAULT_CROP, h=DEFAULT_CROP):
     cropped_area = create_area_def("ci_crop", {
         "proj": "lcc",
         "ellps": "WGS84",
         "lat_0": self.eye_lat,
         "lat_1": self.eye_lat,
         "lon_0": self.eye_lon
     },
                                    center=(self.eye_lon, self.eye_lat),
                                    radius=(w / 2, h / 2),
                                    units="degrees",
                                    resolution=DataArray(
                                        400, attrs={"units": "meters"}))
     print(
         cropped_area.overlap_rate(self.bb_area()) *
         (self.bb_area().get_area() / cropped_area.get_area()))
     assert cropped_area.overlap_rate(self.bb_area()) * (
         self.bb_area().get_area() / cropped_area.get_area()) > 0.8
     self.scene = self.scene.resample(self.bb_area())
     self.scene = self.scene.crop(area=cropped_area)
     self.raw_grid_I5 = self.scene["I05_mask"].values
     self.raw_grid_I4 = self.scene["I04_mask"].values
     self.zenith = self.scene["i_solar_zenith_angle"].values
     self.satz = np.cos(np.deg2rad(
         self.scene["i_satellite_zenith_angle"])).values
     self.raz = np.abs(self.scene["i_satellite_azimuth_angle"] -
                       self.scene["i_solar_azimuth_angle"]).values
Ejemplo n.º 2
0
    def test_get_bucket_indices(self):
        """Test calculation of array indices."""
        # Ensure nothing is calculated
        with dask.config.set(scheduler=CustomScheduler(max_computes=0)):
            self.resampler._get_indices()
        x_idxs, y_idxs = da.compute(self.resampler.x_idxs,
                                    self.resampler.y_idxs)
        np.testing.assert_equal(x_idxs, np.array([1710, 1710, 1707, 1705]))
        np.testing.assert_equal(y_idxs, np.array([465, 465, 459, 455]))

        # Additional small test case
        adef = create_area_def(area_id='test',
                               projection={'proj': 'latlong'},
                               width=2,
                               height=2,
                               center=(0, 0),
                               resolution=10)
        lons = da.from_array(np.array(
            [-10.0, -9.9, -0.1, 0, 0.1, 9.9, 10.0, -10.1, 0]),
                             chunks=2)
        lats = da.from_array(np.array(
            [-10.0, -9.9, -0.1, 0, 0.1, 9.9, 10.0, 0, 10.1]),
                             chunks=2)
        resampler = bucket.BucketResampler(source_lats=lats,
                                           source_lons=lons,
                                           target_area=adef)
        resampler._get_indices()
        np.testing.assert_equal(resampler.x_idxs,
                                np.array([-1, 0, 0, 1, 1, 1, -1, -1, -1]))
        np.testing.assert_equal(resampler.y_idxs,
                                np.array([-1, 1, 1, 1, 0, 0, -1, -1, -1]))
Ejemplo n.º 3
0
def join_areadefs(*areas):
    """Join one or more areadefinitions.

    For a collection of areadefinitions sharing a projection and resolution,
    create the smallest area definition that encompasses all.
    """
    # also at https://github.com/pytroll/pyresample/pull/306

    first = None
    if len(areas) == 0:
        raise TypeError("Must pass at least one area, found zero.")
    for area in areas:
        if first is None:
            first = area
            largest_extent = list(area.area_extent)
        else:
            if not area.proj_dict == first.proj_dict:
                raise ValueError("Inconsistent projections between areas")
            if not numpy.isclose(area.resolution, first.resolution).all():
                raise ValueError("Inconsistent resolution between areas")
            largest_extent[0] = min(largest_extent[0], area.area_extent[0])
            largest_extent[1] = min(largest_extent[1], area.area_extent[1])
            largest_extent[2] = max(largest_extent[2], area.area_extent[2])
            largest_extent[3] = max(largest_extent[3], area.area_extent[3])

    return pyresample.create_area_def(area_id="joint-area",
                                      projection=first.proj_dict,
                                      units=first.proj_dict["units"],
                                      area_extent=largest_extent,
                                      resolution=first.resolution)
Ejemplo n.º 4
0
def create_areadefinition_from_yaml(yamlfile, sector):
    '''Take a YAML with misc metadata and create a pyresample areadefinition
    Misc. metadata will be parsed from the YAML file and manually added to the areadefinition
    Args:
        yamlfile : string full path to YAML area definition file
        sector : string name of sector
    Returns:
        (obj) : pyresample areadefinition object
    '''
    import pyresample
    import yaml
    with open(yamlfile, 'r') as f:
        sectorfile_yaml = yaml.load(f, Loader=yaml.FullLoader)
    sector_info = sectorfile_yaml[sector]
    area_id = sector
    description = sector_info.pop('description')
    projection = sector_info.pop('projection')
    resolution = sector_info.pop('resolution')
    shape = sector_info.pop('shape')
    area_extent = sector_info.pop('area_extent')
    # Create the pyresample area definition
    shape_list = [shape['height'],shape['width']]
    extent_list = []
    extent_list.extend(area_extent['lower_left_xy'])
    extent_list.extend(area_extent['upper_right_xy'])
    area_def = pyresample.create_area_def(area_id=area_id,
                                          description=description,
                                          projection=projection,
                                          resolution=resolution,
                                          shape=shape_list,
                                          area_extent=extent_list)
    # Manually add the metadata to area_def
    for key in sector_info.keys():
        area_def.__setattr__(key, sector_info[key])
    return area_def
Ejemplo n.º 5
0
def test_area_epsg4326():
    """Test with EPSG4326 (latlong) area, which has no CRS coordinate operation."""
    from pyproj import CRS
    shp = (16, 8)
    euro4326 = create_area_def("epgs4326europa",
                               CRS.from_epsg(4326),
                               resolution=1 / 128,
                               shape=shp,
                               center=(0, 0))
    return euro4326
Ejemplo n.º 6
0
def test_area_merc():
    """Create a mercator area."""
    from pyproj import CRS
    shp = (20, 10)
    test_area = create_area_def("test-area-merc",
                                CRS("+proj=merc"),
                                units="m",
                                shape=shp,
                                resolution=1000,
                                center=(0.0, 0.0))
    return test_area
Ejemplo n.º 7
0
def test_area_weird():
    """Create a weird area (interrupted goode homolosine) to test error handling."""
    from pyproj import CRS
    shp = (20, 10)
    test_area = create_area_def("test-area-north-stereo",
                                CRS("+proj=igh"),
                                units="m",
                                shape=shp,
                                resolution=1000,
                                center=(0.0, 1500000.0))
    return test_area
Ejemplo n.º 8
0
def test_area_small_eqc_wgs84():
    """Create 50x100 test equirectangular area centered on (50, 90), wgs84."""
    shp = (50, 100)
    test_area = create_area_def("test-area-eqc-wgs84", {
        "proj": "eqc",
        "lat_0": 2.5,
        "lon_0": 1.,
        "ellps": "WGS84"
    },
                                units="m",
                                shape=shp,
                                resolution=1000,
                                center=(10000000.0, 6000000.0))
    return test_area
Ejemplo n.º 9
0
def test_area_northpole():
    """Create a 20x10 test area centered exactly on the north pole.

    This has no well-defined central meridian so needs separate testing.
    """
    shp = (20, 10)
    test_area = create_area_def("test-area-north-pole", {
        "proj": "stere",
        "lat_0": 90,
        "lat_ts": 60,
        "ellps": "WGS84"
    },
                                shape=shp,
                                resolution=1000,
                                center=(0.0, 15000000.0))
    return test_area
Ejemplo n.º 10
0
def fake_multiscene4():
    """Like fake_multiscene2, but with varying areas (none stacked)."""
    from satpy.dataset.dataid import WavelengthRange
    from satpy.tests.utils import make_dataid
    common_attrs = {}
    wl = {
        "C08": WavelengthRange(5.7, 6.2, 6.7),
        "C10": WavelengthRange(6.8, 7.3, 7.8),
        "C14": WavelengthRange(10, 11, 12)
    }
    content = {
        make_dataid(name=x, wavelength=wl.get(x)):
        numpy.arange(5 * 5).reshape(5, 5)
        for x in ("C08", "C10", "C14")
    }
    content[make_dataid(
        name="flash_extent_density")] = numpy.arange(5 * 5).reshape(5, 5) + 1
    areas = [
        pyresample.create_area_def("test-area", {
            "proj": "eqc",
            "lat_ts": 0,
            "lat_0": 0,
            "lon_0": 0,
            "x_0": 0,
            "y_0": 0,
            "ellps": "sphere",
            "units": "m",
            "no_defs": None,
            "type": "crs"
        },
                                   units="m",
                                   shape=(5, 5),
                                   resolution=1000,
                                   center=(10 * i, 20 * i)) for i in range(3)
    ]

    aids = [0, 0, 0, 0, 0, 0, 1, 1, 1, 2]
    scenes = [
        satpy.tests.utils.make_fake_scene(content.copy(),
                                          common_attrs=common_attrs,
                                          area=areas[i]) for i in aids
    ]
    for (i, sc) in enumerate(scenes):
        for da in sc.values():
            da.attrs["start_time"] = datetime.datetime(1900, 1, 1, 0, i)
            da.attrs["end_time"] = datetime.datetime(1900, 1, 1, 0, i + 1)
    return satpy.MultiScene(scenes)
Ejemplo n.º 11
0
def test_area_tiny_stereographic_wgs84():
    """Create a 20x10 test stereographic area centered near the north pole, wgs84."""
    shp = (20, 10)
    test_area = create_area_def("test-area-north-stereo", {
        "proj": "stere",
        "lat_0": 75.0,
        "lon_0": 2.0,
        "lat_ts": 60.0,
        "ellps": "WGS84",
        "units": "m",
        "type": "crs"
    },
                                units="m",
                                shape=shp,
                                resolution=1000,
                                center=(0.0, 1500000.0))
    return test_area
Ejemplo n.º 12
0
def test_area_tiny_eqc_sphere():
    """Create 10x00 test equirectangular area centered on (40, -30), spherical geoid, m."""
    shp = (10, 20)
    test_area = create_area_def("test-area-eqc-sphere", {
        "proj": "eqc",
        "lat_ts": 0.,
        "lat_0": 0.,
        "lon_0": 0.,
        "x_0": 0.,
        "y_0": 0.,
        "ellps": "sphere",
        "units": "m",
        "no_defs": None,
        "type": "crs"
    },
                                units="m",
                                shape=shp,
                                resolution=1000,
                                center=(-3330000.0, 4440000.0))
    return test_area
Ejemplo n.º 13
0
def resample(gem, variable, res, nx, ny, timestep):

    if not isinstance(variable, list):
        variable = [variable]

    # Open with xarray
    xref = gem

    # Load 2D lat and lon
    lat2d = xref.gridlat_0.values
    lon2d = xref.gridlon_0.values

    # Define the original swath required by pyresample
    orig_def = pyresample.geometry.SwathDefinition(lons=lon2d, lats=lat2d)

    ####
    # Definition of the target grid
    ###

    # Definition of the Canadian LCC projection (https://spatialreference.org/ref/esri/canada-lambert-conformal-conic/)
    proj_dict = {
        'proj': 'lcc',
        'lat_1': 50,
        'lat_2': 70,
        'lat_0': 40,
        'lon_0': -96,
        'x_0': 0,
        'y_0': 0,
        'ellps': 'GRS80',
        'datum': 'NAD83',
        'units': 'm'
    }

    #Name of the grid
    area_id = 'test_kan'

    # Coordinate of the upper left corner of the grid
    lat_upl = lat2d.max()
    lon_upl = lon2d.min()

    # Conversion from WGS84 lat/lon to coordinates in the Canadian LCC projection
    transformer = Transformer.from_crs(
        "EPSG:4326",
        "+proj=lcc +lat_1=50 +lat_2=70 +lat_0=40 +lon_0=-96 +x_0=0 +y_0=0 +ellps=GRS80 +datum=NAD83 +units=m +no_defs",
        always_xy=True)
    xupl, yupl = transformer.transform(lon_upl, lat_upl)

    # Definition of the targert grid according to pyresample
    targ_def = pyresample.create_area_def(area_id,
                                          proj_dict,
                                          shape=(nx, ny),
                                          upper_left_extent=(xupl, yupl),
                                          resolution=(res, res),
                                          description='Test LCC')

    # Get the lat and lon corresponding to targ_def grid
    # Maybe needed in the wrf_out.nc file??
    lons, lats = targ_def.get_lonlats()

    #different interp methods for the regrid

    # # Nearest neighbor interpolation
    # t_nearest = pyresample.kd_tree.resample_nearest(orig_def, tgem, \
    #         targ_def, radius_of_influence=500000, fill_value=None)

    # # Bilinear interpolation
    # t_bil = pyresample.bilinear.resample_bilinear(tgem, orig_def, targ_def)

    resampled_gem = {}

    for var in variable:
        # Load variable to be interpolated (temperature here)
        ingem = xref[var].values[timestep, :, :]
        # IDW interpolation
        wf = lambda r: 1 / r**2
        resampled_gem[var] = pyresample.kd_tree.resample_custom(
            orig_def,
            ingem,
            targ_def,
            radius_of_influence=500000,
            neighbours=10,
            weight_funcs=wf,
            fill_value=None)
        resampled_gem[var] = np.flip(resampled_gem[var], axis=0)

    return targ_def, resampled_gem
Ejemplo n.º 14
0
    def _bin_spatial(self,
                     num_lat,
                     lat_from,
                     lat_step,
                     num_lon,
                     lon_from,
                     lon_step,
                     proj=None):
        # When loading file, keep list of indexes for each data file. Then bin in chunks, with each
        # chunk becoming a layer in the result data set.

        if 'SO2_column_number_density_validity' in self._file_data:
            # Validity is not valid for gridded data.
            del self._file_data['SO2_column_number_density_validity']

        # Make sure everything is correctly typed
        num_lat = int(num_lat) - 1
        lat_from = float(lat_from)
        lat_step = float(lat_step)
        lat_to = lat_from + (num_lat * lat_step)

        num_lon = int(num_lon) - 1
        lon_from = float(lon_from)
        lon_step = float(lon_step)
        lon_to = lon_from + (num_lon * lon_step)

        if lon_to > 180:
            # Shift 360 degrees. With my changes, pyresample can cross the dateline to the
            # negitive, but not to the positive.
            lon_from -= 360
            lon_to -= 360

        # try gridding the data
        area_extent = (lon_from, lat_from, lon_to, lat_to)

        if isinstance(proj, str):
            proj = pickle.loads(bytes.fromhex(proj))

        proj_dict = proj if proj else {
            'proj': 'lonlat',
            'over': True,
            'preserve_units': False,
        }
        target_def = create_area_def("Binned",
                                     proj_dict,
                                     area_extent=area_extent,
                                     shape=(num_lat, num_lon))

        target_lons, target_lats = target_def.get_lonlats()

        # Fix "out-of-bounds" lons
        if proj is None:
            target_lons[target_lons < -180] = 180 - (
                -1 * (target_lons[target_lons < -180] + 180))

        # get "bounds"
        left_bounds = target_lons - target_def.pixel_size_x / 2
        right_bounds = target_lons + target_def.pixel_size_x / 2
        top_bounds = target_lats + target_def.pixel_size_y / 2
        bottom_bounds = target_lats - target_def.pixel_size_y / 2

        lon_bounds = numpy.stack([left_bounds, right_bounds], axis=2)
        lat_bounds = numpy.stack([bottom_bounds, top_bounds], axis=2)

        lats = numpy.repeat(lat_bounds, 2, axis=2)
        lons = numpy.stack(
            [lon_bounds, numpy.flip(lon_bounds, axis=2)], axis=2)
        lons.shape = (lon_bounds.shape[0], lon_bounds.shape[1], 4)

        # Pre-allocate memory for final result
        binned_file_data = None

        results = []
        for file_idx, stop in enumerate(self._file_idxs):
            try:
                kill = signaller.load_queue.get_nowait()
            except queue.Empty:
                pass  # Nothng to get
            else:
                if kill:
                    _TERM_FLAG.set()

            if _TERM_FLAG.is_set():
                return

            if file_idx == 0:
                start = 0
            else:
                start = self._file_idxs[file_idx - 1]

            results.append(self._bin_file((start, stop), target_def))

        for idx, binned_data in enumerate(results):
            signaller.status.emit(
                f"Stacking Data ({idx}/{len(self._file_idxs)})...", idx,
                len(self._file_idxs))
            binned_data.coords['latitude'] = (('x', 'y'), target_lats)
            binned_data.coords['longitude'] = (('x', 'y'), target_lons)
            binned_data.coords['latitude_bounds'] = (('x', 'y', 'corners'),
                                                     lats)
            binned_data.coords['longitude_bounds'] = (('x', 'y', 'corners'),
                                                      lons)

            if binned_file_data is None:
                binned_file_data = binned_data
            else:
                binned_file_data = xarray.concat(
                    [binned_file_data, binned_data], 'file')

        self._file_data = binned_file_data
Ejemplo n.º 15
0
    def colorplot_with_band(self,
                            band,
                            HSD_Dir,
                            imgFile,
                            *args,
                            axLatRange=[20, 60],
                            axLonRange=[90, 140],
                            cmap=None,
                            pixels=100,
                            **kwargs):
        """
        colorplot the variables together with radiance data.

        Parameters
        ----------
        band: int
            band number [1-16]. See band specification in
            `../doc/2018_A_Yamashita.md`
        HSD_Dir: str
            path for hosting the HSD files.
        imgFile: str
            filename of the exported image
        Keywords
        --------
        axLatRange: list
            latitude range of the plot (default: [20, 60]). [degree]
        axLonRange: list
            longitude range of the plot (default: [90, 140]). [degree]
        cmap: str
            colormap name.
        pixels: int
            resampled pixels of the band data (default: 100). Take care of
            time consumption when pixels > 1000!
        History
        -------
        2020-02-24 First version.
        """

        files = find_files_and_readers(
            start_time=(self.mTime - dt.timedelta(seconds=300)),
            end_time=(self.mTime + dt.timedelta(seconds=300)),
            base_dir=HSD_Dir,
            reader='ahi_hsd')

        matched_files = []
        for file in files['ahi_hsd']:
            if fnmatch.fnmatch(
                    os.path.basename(file),
                    'HS_H08_*_B{0:02d}_FLDK_*_S0[1234]*DAT*'.format(band)):
                matched_files.append(file)

        h8_scene = Scene(filenames=matched_files,
                         reader='ahi_hsd',
                         sensor='ahi')
        band_label = 'B{0:02d}'.format(band)
        h8_scene.load([band_label])

        roi = create_area_def('roi', {
            'proj': 'eqc',
            'ellps': 'WGS84'
        },
                              width=pixels,
                              height=pixels,
                              area_extent=[
                                  axLonRange[0], axLatRange[0], axLonRange[1],
                                  axLatRange[1]
                              ],
                              units='degrees')
        roi_scene = h8_scene.resample(roi)

        # read China boundaries
        with open(os.path.join(PROJECTDIR, 'include', 'CN-border-La.dat'),
                  'r') as fd:
            context = fd.read()
            blocks = [cnt for cnt in context.split('>') if len(cnt) > 0]
            borders = [
                np.fromstring(block, dtype=float, sep=' ') for block in blocks
            ]

        LON, LAT = np.meshgrid(self.lon, self.lat)
        fig = plt.figure(figsize=[8, 8])
        plt.tight_layout(False)

        # Set projection and plot the main figure
        ax1 = plt.axes([0.1, 0.1, 0.8, 0.8], projection=ccrs.PlateCarree())

        # Add ocean, land, rivers and lakes
        ax1.add_feature(cfeature.OCEAN.with_scale('50m'))
        ax1.add_feature(cfeature.LAND.with_scale('50m'))
        ax1.add_feature(cfeature.RIVERS.with_scale('50m'))
        ax1.add_feature(cfeature.LAKES.with_scale('50m'))

        # Plot border lines
        for line in borders:
            ax1.plot(line[0::2],
                     line[1::2],
                     '-',
                     lw=1,
                     color='k',
                     transform=ccrs.Geodetic())

        # loading colormap
        if cmap is None:
            cmap = chiljet_colormap()

        # Plot gridlines
        crs = roi.to_cartopy_crs()
        pcmesh_band = ax1.imshow(roi_scene[band_label],
                                 transform=crs,
                                 origin='upper',
                                 extent=crs.bounds,
                                 cmap='Greys')
        pcmesh = ax1.pcolormesh(LON,
                                LAT,
                                self.data,
                                vmin=kwargs['vmin'],
                                vmax=kwargs['vmax'],
                                cmap=cmap,
                                transform=ccrs.PlateCarree())

        ax1.set_xticks(
            np.linspace(axLonRange[0], axLonRange[1], 5, endpoint=True))
        ax1.set_yticks(
            np.linspace(axLatRange[0], axLatRange[1], 5, endpoint=True))
        lon_formatter = LongitudeFormatter(number_format='.1f',
                                           degree_symbol='',
                                           dateline_direction_label=True)
        lat_formatter = LatitudeFormatter(number_format='.1f',
                                          degree_symbol='')
        ax1.xaxis.set_major_formatter(lon_formatter)
        ax1.yaxis.set_major_formatter(lat_formatter)
        ax1.set_ylim(axLatRange)
        ax1.set_xlim(axLonRange)

        ax1.set_title('{0} {1}'.format(
            self.mTime.strftime('%Y-%m-%d %H:%M (Himawari-8)'),
            self.long_name))

        if 'cb_ticks' not in kwargs.keys():
            kwargs['cb_ticks'] = np.linspace(kwargs['vmin'],
                                             kwargs['vmax'],
                                             5,
                                             endpoint=True)

        cbar = fig.colorbar(pcmesh,
                            fraction=0.03,
                            ticks=kwargs['cb_ticks'],
                            orientation='vertical')
        cbar.ax.tick_params(direction='out', labelsize=15, pad=5)
        cbar.ax.set_title(self.unit, fontsize=10)

        if 'cb_ticklabels' in kwargs.keys():
            cbar.ax.set_yticklabels(kwargs['cb_ticklabels'])

        # Show figure
        # plt.show()
        plt.savefig(imgFile)
        plt.close()
Ejemplo n.º 16
0
####################
msg_area = geometry.AreaDefinition(
    'msg_full', 'Full globe MSG1 image 41.5 degrees', 'msg_full', {
        'a': '6378137.000000',
        'b': '6356752.300000',
        'h': '35785863.000000',
        'lon_0': '41.500000',
        'proj': 'geos'
    }, 3712, 3712, [
        -5570248.477339261, -5567248.074173444, 5567248.074173444,
        5570248.477339261
    ])
area_def = create_area_def('my_area', {
    'proj': 'latlong',
    'lon_0': 0
},
                           area_extent=[-180, -90, 180, 90],
                           resolution=0.1,
                           units='degrees',
                           description='Global 1x1 degree lat-lon grid')

#area_def = load_area('/home/NCMRWFTEMP/vsprasad/EXP_HY2B/validation/crr/areas.yaml', 'IndianOcean_latlon_SC300')
##########
########## Basemap
#area_def = pr.utils.load_area('areas.cfg', 'pc_world')
#####bmap = pr.plot.area_def2basemap(area_def)
###################
#area_def, cf_info = load_cf_area('/home/NCMRWFTEMP/vsprasad/EXP_HY2B/validation/crr/xxx.nc')
#x = xr.open_dataset('/home/NCMRWFTEMP/vsprasad/EXP_HY2B/validation/crr/xxx.nc')
#llon = x.lon.values
#llat = x.lat.values
#xgrid = x.lat.values.shape[0]
Ejemplo n.º 17
0
def make_fake_scene(content_dict, daskify=False, area=True, common_attrs=None):
    """Create a fake Scene.

    Create a fake Scene object from fake data.  Data are provided in
    the ``content_dict`` argument.  In ``content_dict``, keys should be
    strings or DatasetID/DataID, and values may be either numpy.ndarray
    or xarray.DataArray, in either case with exactly two dimensions.
    The function will convert each of the numpy.ndarray objects into
    an xarray.DataArray and assign those as datasets to a Scene object.
    A fake AreaDefinition will be assigned for each array, unless disabled
    by passing ``area=False``.  When areas are automatically generated,
    arrays with the same shape will get the same area.

    This function is exclusively intended for testing purposes.

    If regular ndarrays are passed and the keyword argument daskify is
    True, DataArrays will be created as dask arrays.  If False (default),
    regular DataArrays will be created.  When the user passes xarray.DataArray
    objects then this flag has no effect.

    Args:
        content_dict (Mapping): Mapping where keys correspond to objects
            accepted by ``Scene.__setitem__``, i.e. strings or DatasetID,
            and values may be either ``numpy.ndarray`` or
            ``xarray.DataArray``.
        daskify (bool): optional, to use dask when converting
            ``numpy.ndarray`` to ``xarray.DataArray`.  No effect when the
            values in ``content_dict`` are already ``xarray.DataArray`.
        area (bool or BaseDefinition): Can be ``True``, ``False``, or an
            instance of ``pyresample.geometry.BaseDefinition`` such as
            ``AreaDefinition`` or ``SwathDefinition``.  If ``True``, which is
            the default, automatically generate areas.  If ``False``, values
            will not have assigned areas.  If an instance of
            ``pyresample.geometry.BaseDefinition``, those instances will be
            used for all generated fake datasets.  Warning: Passing an area as
            a string (``area="germ"``) is not supported.
        common_attrs (Mapping): optional, additional attributes that will
            be added to every dataset in the scene.

    Returns:
        Scene object with datasets corresponding to content_dict.
    """
    import pyresample
    import satpy
    import xarray as xr
    if common_attrs is None:
        common_attrs = {}
    if daskify:
        import dask.array
    sc = satpy.Scene()
    for (did, arr) in content_dict.items():
        extra_attrs = common_attrs.copy()
        if isinstance(area, pyresample.geometry.BaseDefinition):
            extra_attrs["area"] = area
        elif area:
            extra_attrs["area"] = pyresample.create_area_def("test-area", {
                "proj": "eqc",
                "lat_ts": 0,
                "lat_0": 0,
                "lon_0": 0,
                "x_0": 0,
                "y_0": 0,
                "ellps": "sphere",
                "units": "m",
                "no_defs": None,
                "type": "crs"
            },
                                                             units="m",
                                                             shape=arr.shape,
                                                             resolution=1000,
                                                             center=(0, 0))
        if isinstance(arr, xr.DataArray):
            sc[did] = arr.copy()  # don't change attributes of input
            sc[did].attrs.update(extra_attrs)
        else:
            if daskify:
                arr = dask.array.from_array(arr)
            sc[did] = xr.DataArray(arr, dims=("y", "x"), attrs=extra_attrs)
    return sc
Ejemplo n.º 18
0
def get_scene_obj(file_list,
                  latlon_extent,
                  width=750,
                  height=750,
                  tmp_cache=False,
                  resample_method='native_bilinear'):
    """Get Scene object, apply the resample area, to a small box 
    centered on the lat lon point.

    inputs:
    file_list: list of netCDF L1b ABI files, must contain bands 1,2,3
    latlon_extent: extent of displayed region in latlon:
        [min_lon, min_lat, max_lon, max_lat]
    width: number of resampled image pixels in width (x-dimension)
    height: number of resampled image pixels in width (y-dimension)

    tmp_cache: optional keyword, set to True to copy the located files
    to a temporary dir (from tempfile) before loading.
    Note the temporary files are NOT cleaned up.
    Use this option if the data_home access is slow or limited in some
    way, which can be mitigated by copying to a temp file on the local
    filesystem

    resample_method: string keyword to specify the resampling method.
    valid options are:
    nearest: perform nearest neighbor resampling in one step
    bilinear: perform bilinear interpolation in one step
    native_nearest: perform a native interpolation first, to upsample
       lower resolution bands to the highest native resolution; 
       then perform nearest neighbor interpolation to the output grid.
    native_nearest: perform a native interpolation first, to upsample
       lower resolution bands to the highest native resolution; 
       then perform bilinear interpolation to the output grid.

    outputs: the satpy Scene object.

    """

    valid_resample_methods = [
        'nearest', 'bilinear', 'native_nearest', 'native_bilinear'
    ]

    if resample_method not in valid_resample_methods:
        raise ValueError('resample_method ' + resample_method +
                         ' is not valid')

    if tmp_cache:
        tdir = tempfile.mkdtemp()
        cached_file_list = []
        for f in file_list:
            src_f = f
            dst_f = os.path.join(tdir, os.path.split(f)[-1])
            shutil.copyfile(src_f, dst_f)
            cached_file_list.append(dst_f)
        scn = Scene(reader='abi_l1b', filenames=cached_file_list)
    else:
        scn = Scene(reader='abi_l1b', filenames=file_list)

    scn.load(['true_color'])

    my_area = pyresample.create_area_def('testC', {'proj': 'eqc'},
                                         width=width,
                                         height=height,
                                         area_extent=latlon_extent,
                                         units='degrees')

    if resample_method.startswith('native'):
        tmp_scn = scn.resample(resampler='native')
    else:
        tmp_scn = scn

    # this would split the second string str1_str2,
    # or just return the str if there is no underscore.
    # thus, it should be the resample method after the
    # optional native resampling.
    method = resample_method.split('_')[-1]
    new_scn = tmp_scn.resample(my_area, resampler=method)

    return new_scn
Ejemplo n.º 19
0
def sentinel3_olci(inpath, extent, epsg, user_list=[], resolution=300,):
    """Read an S3 OLCI image.

    Open a Sentinel-3 OLCI image based on the path to the SEN3 folder. The
    image is cropped to the extent provided as an input and reprojected to the
    given EPSG code. The user can specify a list of bands to process and a
    resolution.

    :param inpath: Path to the Sentinel-3 OLCI image
    :type inpath: pathlib.PosixPath
    :param extent: Polygon setting the extent of the Scene to process
    :type extent: osgeo.ogr.Geometry
    :param epsg: EPSG code of the projection for the image
    :type epsg: int
    :param user_list: List of bandnames to process
    :type user_list: list, optional
    :param resolution: Resolution of the image to resample the image to
    :type resolution: int, optional
    :return: The satellite data stored in a class
    :rtype: redress.inputs.products.Sat
    """
    # Open the image
    s3_prod = open_generic_product(inpath)

    # Check if the product overlaps the extent of the file
    s3_extents = gdal_ops.build_poly_from_coords(image_extents(s3_prod))
    if not gdal_ops.geom_contains(s3_extents, extent):
        raise ValueError("The chosen bounding box is not entirely inside the"
                         " provided Satellite image!")

    # If the user selects all bands, set a list containing all band names
    if not user_list:
        user_list = fetch_bandnames(s3_prod)
    else:
        # Check if bands are in the product
        if not set(user_list).issubset(fetch_bandnames(s3_prod)):
            raise ValueError("Selected bands are not in product!")

    # Load all bands for the resampling
    s3_prod.load(user_list)

    # Set parameters for the resampling stage
    image_extent = gdal_ops.corner_coords_from_poly(extent, out_epsg=2154)
    area_def = create_area_def("reprojection", "EPSG:%s" % epsg,
                               area_extent=image_extent,
                               units="metres", resolution=300,
                               )

    # Resample product
    s3_resampled = s3_prod.resample(area_def, resampler="nearest")

    # Instantiate class
    s3_data = Sat()

    # Feed the class with data
    s3_data.meta["path"] = inpath

    # Get radiance bands from product and import to the S3 class
    for band in user_list:
        # Get radiance bands
        if "Oa" in band:
            # Load radiance band
            s3_resampled.load([band])

            # Fetch data from band
            s3_data.bands[band] = s3_resampled[band]

            # Get band name
            s3_data.meta["bandlist"].append(band)

            # Get band wavelength center
            s3_data.meta["wavelengths"].append(
                s3_resampled[band].wavelength[1] * 1000)

        # Get solar and viewing bands from the S3 product
        elif band in ["satellite_azimuth_angle",
                      "satellite_zenith_angle",
                      "solar_azimuth_angle",
                      "solar_zenith_angle"]:

            # Load and import band
            s3_resampled.load([band])
            s3_data.angles[band] = s3_resampled[band]

    # Correct for the particularity of the VAA band in S3 OLCI
    # (flipped on one side of nadir)
    negative_array = \
        s3_data.angles["satellite_azimuth_angle"].where(
            s3_data.angles["satellite_azimuth_angle"] < 0)
    positive_array = \
        s3_data.angles["satellite_azimuth_angle"].where(
            s3_data.angles["satellite_azimuth_angle"] > 0)
    # Replace negative values by substracting 180 by the positive value
    negative_array = negative_array + 180

    # Merge arrays
    s3_data.angles["satellite_azimuth_angle"] = \
        positive_array.fillna(negative_array)

    # Rename angle bands for consistency
    s3_data.angles = s3_data.angles.rename({"satellite_azimuth_angle": "VAA",
                                            "satellite_zenith_angle": "VZA",
                                            "solar_azimuth_angle": "SAA",
                                            "solar_zenith_angle": "SZA"},
                                           )
    # Convert to radians
    for band in ["SZA", "SAA", "VZA", "VAA"]:
        s3_data.angles[band].data = xr.ufuncs.deg2rad(s3_data.angles[band])
        s3_data.angles[band].attrs["units"] = "radians"
        s3_data.meta["angles"].append(band)

    # Get/Set Geotransform
    ulxy = image_extents(s3_resampled, epsg=2154)[2]
    s3_data.geotransform = (ulxy[0], resolution, 0.0,
                            ulxy[1], 0.0, -resolution)

    return s3_data
Ejemplo n.º 20
0
def get_eye(start_point, end_point):
    lat_0, lat_1 = start_point["USA_LAT"], end_point["USA_LAT"]
    lon_0, lon_1 = start_point["USA_LON"], end_point["USA_LON"]
    try:
        files, urls = get_data(DATA_DIRECTORY,
                               start_point["ISO_TIME"].to_pydatetime(),
                               end_point["ISO_TIME"].to_pydatetime(),
                               north=max(lat_0, lat_1) + DEFAULT_MARGIN,
                               south=min(lat_0, lat_1) - DEFAULT_MARGIN,
                               east=wrap(max(lon_0, lon_1) + DEFAULT_MARGIN),
                               west=wrap(min(lon_0, lon_1) - DEFAULT_MARGIN),
                               dayOrNight="D")
    except FileNotFoundError:
        return None
    raw_scene = Scene(filenames=files, reader="viirs_l1b")
    raw_scene.load(
        ["I04", "I05", "i_lat", "i_lon", "i_satellite_azimuth_angle"])
    t = raw_scene.start_time - start_point["ISO_TIME"].to_pydatetime()

    metadata = interpolate(start_point, end_point, t)
    eye_radius = metadata["USA_RMW"] / 60
    # core_area = create_area_def("core_eye",{
    #     "proj":"lcc","ellps":"WGS84","lat_0":metadata["USA_LAT"],"lon_1":metadata["USA_LON"]},units="degrees",
    #
    # })
    first_pass = create_area_def("first_pass", {
        "proj": "lcc",
        "ellps": "WGS84",
        "lat_0": metadata["USA_LAT"],
        "lon_0": metadata["USA_LON"],
        "lat_1": metadata["USA_LAT"]
    },
                                 units="degrees",
                                 resolution=RESOLUTION_DEF,
                                 area_extent=[
                                     metadata["USA_LON"] - 2 * eye_radius,
                                     metadata["USA_LAT"] - 2 * eye_radius,
                                     metadata["USA_LON"] + 2 * eye_radius,
                                     metadata["USA_LAT"] + 2 * eye_radius
                                 ])
    cropped_scene = raw_scene.resample(first_pass)
    centered_lon, centered_lat = first_pass.get_lonlat(*np.unravel_index(
        cropped_scene["I05"].values.argmax(), cropped_scene["I05"].shape))
    recentered_area = create_area_def("better_eye_area", {
        "proj": "lcc",
        "ellps": "WGS84",
        "lat_0": centered_lat,
        "lon_0": centered_lon,
        "lat_1": centered_lat
    },
                                      units="degrees",
                                      resolution=RESOLUTION_DEF,
                                      area_extent=[
                                          centered_lon - 2 * eye_radius,
                                          centered_lat - 2 * eye_radius,
                                          centered_lon + 2 * eye_radius,
                                          centered_lat + 2 * eye_radius
                                      ])
    new_scene = raw_scene.resample(recentered_area)

    return CycloneSnapshot(new_scene["I04"].values,
                           new_scene["I05"].values,
                           recentered_area.pixel_size_x,
                           recentered_area.pixel_size_y,
                           new_scene["i_satellite_azimuth_angle"].values,
                           metadata,
                           b_lon=centered_lon - 2 * eye_radius,
                           b_lat=centered_lat - 2 * eye_radius)