def _get_view_zenith(scn, obs_lon, obs_lat):
    """
    helper function to compute the view zenith angle to a observed lat/lon
    point (at zero altitude) for the given satellite.
    The satellite position is stored within the satpy Scene object,
    so we get the required info from the scn metadata. Note this only works
    after the true_color composite is loaded.
    """

    obs_datetime = scn.attrs['start_time']
    obs_alt = 0.0

    # orbital parameters are stored in different keys for
    # GOES and Himawari; first branch is the GOES version.
    if 'orbital_parameters' in scn['true_color'].attrs:
        orb_pars = scn['true_color'].attrs['orbital_parameters']
        sat_lon = orb_pars['satellite_nominal_longitude']
        sat_lat = orb_pars['satellite_nominal_latitude']
        sat_alt = orb_pars['satellite_nominal_altitude']
    else:
        sat_lon = scn['true_color'].attrs['satellite_longitude']
        sat_lat = 0.0
        sat_alt = scn['true_color'].attrs['satellite_altitude']

    # in scn object, this is units [m], need [km] for pyorbital function.
    sat_alt *= 1e-3
    # get_observer_look expects array like inputs; if we put sat_lon inside
    # a 1-element list, everything gets broadcast to that shape.
    _, view_el = get_observer_look([sat_lon], sat_lat, sat_alt, obs_datetime,
                                   obs_lon, obs_lat, obs_alt)
    # convert back to scalar while changing from elevation to zenith.
    view_zenith = 90 - view_el[0]

    return view_zenith
Exemple #2
0
    def __call__(self, projectables, optional_datasets=None, **info):
        """Get the atmospherical correction. Uses pyspectral.
        """
        from pyspectral.atm_correction_ir import AtmosphericalCorrection

        band = projectables[0]

        if optional_datasets:
            satz = optional_datasets[0]
        else:
            from pyorbital.orbital import get_observer_look
            lons, lats = band.attrs['area'].get_lonlats_dask(CHUNK_SIZE)

            try:
                dummy, satel = get_observer_look(
                    band.attrs['satellite_longitude'],
                    band.attrs['satellite_latitude'],
                    band.attrs['satellite_altitude'], band.attrs['start_time'],
                    lons, lats, 0)
            except KeyError:
                raise KeyError('Band info is missing some meta data!')
            satz = 90 - satel
            del satel

        LOG.info('Correction for limb cooling')
        corrector = AtmosphericalCorrection(band.attrs['platform_name'],
                                            band.attrs['sensor'])

        atm_corr = corrector.get_correction(satz, band.attrs['name'], band)
        proj = band - atm_corr
        proj.attrs = band.attrs
        self.apply_modifier_info(band, proj)

        return proj
Exemple #3
0
    def __call__(self, projectables, optional_datasets=None, **info):
        """Get the corrected reflectance when removing Rayleigh scattering. Uses
        pyspectral.
        """
        from pyspectral.rayleigh import Rayleigh

        (vis, red) = projectables
        if vis.shape != red.shape:
            raise IncompatibleAreas
        try:
            (sata, satz, suna, sunz) = optional_datasets
        except ValueError:
            from pyorbital.astronomy import get_alt_az, sun_zenith_angle
            from pyorbital.orbital import get_observer_look
            lons, lats = vis.info['area'].get_lonlats()
            sunalt, suna = get_alt_az(vis.info['start_time'], lons, lats)
            suna = np.rad2deg(suna)
            sunz = sun_zenith_angle(vis.info['start_time'], lons, lats)
            sata, satel = get_observer_look(vis.info['satellite_longitude'],
                                            vis.info['satellite_latitude'],
                                            vis.info['satellite_altitude'],
                                            vis.info['start_time'], lons, lats,
                                            0)
            satz = 90 - satel
            del satel
        LOG.info('Removing Rayleigh scattering and aerosol absorption')

        # First make sure the two azimuth angles are in the range 0-360:
        sata = np.mod(sata, 360.)
        suna = np.mod(suna, 360.)
        ssadiff = np.abs(suna - sata)
        ssadiff = np.where(ssadiff > 180, 360 - ssadiff, ssadiff)
        del sata, suna

        atmosphere = self.info.get('atmosphere', 'us-standard')
        aerosol_type = self.info.get('aerosol_type', 'marine_clean_aerosol')

        corrector = Rayleigh(vis.info['platform_name'],
                             vis.info['sensor'],
                             atmosphere=atmosphere,
                             aerosol_type=aerosol_type)

        try:
            refl_cor_band = corrector.get_reflectance(sunz, satz, ssadiff,
                                                      vis.id.name, red)
        except KeyError:
            LOG.warning(
                "Could not get the reflectance correction using band name: %s",
                vis.id.name)
            LOG.warning(
                "Will try use the wavelength, however, this may be ambiguous!")
            refl_cor_band = corrector.get_reflectance(sunz, satz, ssadiff,
                                                      vis.id.wavelength[1],
                                                      red)

        proj = Dataset(vis - refl_cor_band, copy=False, **vis.info)
        self.apply_modifier_info(vis, proj)

        return proj
 def test_basic_numpy(self):
     """Test with numpy array inputs"""
     from pyorbital import orbital
     azi, elev = orbital.get_observer_look(self.sat_lon, self.sat_lat,
                                           self.sat_alt, self.t,
                                           self.lon, self.lat, self.alt)
     np.testing.assert_allclose(azi, self.exp_azi)
     np.testing.assert_allclose(elev, self.exp_elev)
 def test_basic_numpy(self):
     """Test with numpy array inputs"""
     from pyorbital import orbital
     azi, elev = orbital.get_observer_look(self.sat_lon, self.sat_lat,
                                           self.sat_alt, self.t, self.lon,
                                           self.lat, self.alt)
     np.testing.assert_allclose(azi, self.exp_azi)
     np.testing.assert_allclose(elev, self.exp_elev)
Exemple #6
0
def _get_sensor_angles_ndarray(lons, lats, start_time, sat_lon, sat_lat, sat_alt) -> np.ndarray:
    with ignore_invalid_float_warnings():
        sata, satel = get_observer_look(
            sat_lon,
            sat_lat,
            sat_alt / 1000.0,  # km
            start_time,
            lons, lats, 0)
        satz = 90 - satel
        return np.stack([sata, satz])
def get_satellite_angles(dataset, lons, lats):
    """Compute satellite angles.

    Returns:
        Satellite azimuth angle, Satellite zenith angle in degrees

    """
    sat_lon, sat_lat, sat_alt = satpy.utils.get_satpos(dataset)

    # Double check that pyorbital/satpy behave as expected (satpy returning
    # altitude in meters and pyorbital expecting km).
    #
    # if:
    #   1) get_observer_look() gives wrong answer ...
    #   ... for satellite altitude in m. AND
    #   2) get_observer_look() gives correct answer ...
    #   ....  for satellite altitude in km. AND
    #   3) Satellite altitude is m.:
    #    => Satellite alltitude need to be converted to km.
    # else:
    #    => There have been updates to SatPy and this script
    #       need to be modified.
    if not (get_observer_look(0, 0, 36000 * 1000, datetime.utcnow(
    ), np.array([16]), np.array([58]), np.array([0]))[1] > 30
            and get_observer_look(0, 0, 36000, datetime.utcnow(), np.array(
                [16]), np.array([58]), np.array([0]))[1] < 23
            and sat_alt > 38000):
        raise UnexpectedSatpyVersion(
            'Unexpected handling of satellite altitude in pyorbital/'
            'satpy. Conversion to km is probably unneeded and wrong.')

    # Convert altitude from meters to kilometers, as expected by the
    # current version of pyorbital
    sat_alt *= 0.001

    # Compute angles
    sata, satel = get_observer_look(sat_lon, sat_lat, sat_alt,
                                    dataset.attrs['start_time'], lons, lats, 0)
    satz = 90 - satel

    return sata, satz
Exemple #8
0
 def _get_sensor_angles(self, vis, lons, lats):
     from pyorbital.orbital import get_observer_look
     sat_lon, sat_lat, sat_alt = get_satpos(vis)
     sata, satel = get_observer_look(
         sat_lon,
         sat_lat,
         sat_alt / 1000.0,  # km
         vis.attrs['start_time'],
         lons,
         lats,
         0)
     satz = 90 - satel
     return sata, satz
Exemple #9
0
    def get_angles(self, vis):
        from pyorbital.astronomy import get_alt_az, sun_zenith_angle
        from pyorbital.orbital import get_observer_look

        lons, lats = vis.attrs['area'].get_lonlats_dask(chunks=vis.data.chunks)
        suna = get_alt_az(vis.attrs['start_time'], lons, lats)[1]
        suna = xu.rad2deg(suna)
        sunz = sun_zenith_angle(vis.attrs['start_time'], lons, lats)
        sata, satel = get_observer_look(vis.attrs['satellite_longitude'],
                                        vis.attrs['satellite_latitude'],
                                        vis.attrs['satellite_altitude'],
                                        vis.attrs['start_time'], lons, lats, 0)
        satz = 90 - satel
        return sata, satz, suna, sunz
 def test_basic_dask(self):
     """Test with dask array inputs"""
     from pyorbital import orbital
     import dask.array as da
     sat_lon = da.from_array(self.sat_lon, chunks=2)
     sat_lat = da.from_array(self.sat_lat, chunks=2)
     sat_alt = da.from_array(self.sat_alt, chunks=2)
     lon = da.from_array(self.lon, chunks=2)
     lat = da.from_array(self.lat, chunks=2)
     alt = da.from_array(self.alt, chunks=2)
     azi, elev = orbital.get_observer_look(sat_lon, sat_lat, sat_alt,
                                           self.t, lon, lat, alt)
     np.testing.assert_allclose(azi.compute(), self.exp_azi)
     np.testing.assert_allclose(elev.compute(), self.exp_elev)
Exemple #11
0
    def __call__(self, projectables, optional_datasets=None, **info):
        """Get the corrected reflectance when removing Rayleigh scattering. Uses
        pyspectral.
        """
        from pyspectral.rayleigh import Rayleigh

        (vis, blue) = projectables
        if vis.shape != blue.shape:
            raise IncompatibleAreas
        try:
            (sata, satz, suna, sunz) = optional_datasets
        except ValueError:
            from pyorbital.astronomy import get_alt_az, sun_zenith_angle
            from pyorbital.orbital import get_observer_look
            sunalt, suna = get_alt_az(
                vis.info['start_time'], *vis.info['area'].get_lonlats())
            suna = np.rad2deg(suna)
            sunz = sun_zenith_angle(
                vis.info['start_time'], *vis.info['area'].get_lonlats())
            lons, lats = vis.info['area'].get_lonlats()
            sata, satel = get_observer_look(vis.info['satellite_longitude'],
                                            vis.info['satellite_latitude'],
                                            vis.info['satellite_altitude'],
                                            vis.info['start_time'],
                                            lons, lats, 0)
            satz = 90 - satel
            del satel
        LOG.info('Removing Rayleigh scattering and aerosol absorption')

        ssadiff = np.abs(suna - sata)
        ssadiff = np.where(ssadiff > 180, 360 - ssadiff, ssadiff)
        del sata, suna

        atmosphere = self.info.get('atmosphere', 'us-standard')
        aerosol_type = self.info.get('aerosol_type', 'marine_clean_aerosol')

        corrector = Rayleigh(vis.info['platform_name'], vis.info['sensor'],
                             atmosphere=atmosphere,
                             aerosol_type=aerosol_type)

        refl_cor_band = corrector.get_reflectance(
            sunz, satz, ssadiff, vis.id.wavelength[1], blue)

        proj = Dataset(vis - refl_cor_band,
                       copy=False,
                       **vis.info)
        self.apply_modifier_info(vis, proj)

        return proj
 def test_basic_dask(self):
     """Test with dask array inputs"""
     from pyorbital import orbital
     import dask.array as da
     sat_lon = da.from_array(self.sat_lon, chunks=2)
     sat_lat = da.from_array(self.sat_lat, chunks=2)
     sat_alt = da.from_array(self.sat_alt, chunks=2)
     lon = da.from_array(self.lon, chunks=2)
     lat = da.from_array(self.lat, chunks=2)
     alt = da.from_array(self.alt, chunks=2)
     azi, elev = orbital.get_observer_look(sat_lon, sat_lat,
                                           sat_alt, self.t,
                                           lon, lat, alt)
     np.testing.assert_allclose(azi.compute(), self.exp_azi)
     np.testing.assert_allclose(elev.compute(), self.exp_elev)
Exemple #13
0
    def get_angles(self, vis):
        from pyorbital.astronomy import get_alt_az, sun_zenith_angle
        from pyorbital.orbital import get_observer_look

        lons, lats = vis.attrs['area'].get_lonlats_dask(
            chunks=vis.data.chunks)

        sunalt, suna = get_alt_az(vis.attrs['start_time'], lons, lats)
        suna = xu.rad2deg(suna)
        sunz = sun_zenith_angle(vis.attrs['start_time'], lons, lats)
        sata, satel = get_observer_look(
            vis.attrs['satellite_longitude'],
            vis.attrs['satellite_latitude'],
            vis.attrs['satellite_altitude'],
            vis.attrs['start_time'],
            lons, lats, 0)
        satz = 90 - satel
        return sata, satz, suna, sunz
    def test_xarray_with_numpy(self):
        """Test with xarray DataArray with numpy array as inputs"""
        from pyorbital import orbital
        import xarray as xr

        def _xarr_conv(input):
            return xr.DataArray(input)

        sat_lon = _xarr_conv(self.sat_lon)
        sat_lat = _xarr_conv(self.sat_lat)
        sat_alt = _xarr_conv(self.sat_alt)
        lon = _xarr_conv(self.lon)
        lat = _xarr_conv(self.lat)
        alt = _xarr_conv(self.alt)
        azi, elev = orbital.get_observer_look(sat_lon, sat_lat, sat_alt,
                                              self.t, lon, lat, alt)
        np.testing.assert_allclose(azi.data, self.exp_azi)
        np.testing.assert_allclose(elev.data, self.exp_elev)
    def test_xarray_with_numpy(self):
        """Test with xarray DataArray with numpy array as inputs"""
        from pyorbital import orbital
        import xarray as xr

        def _xarr_conv(input):
            return xr.DataArray(input)
        sat_lon = _xarr_conv(self.sat_lon)
        sat_lat = _xarr_conv(self.sat_lat)
        sat_alt = _xarr_conv(self.sat_alt)
        lon = _xarr_conv(self.lon)
        lat = _xarr_conv(self.lat)
        alt = _xarr_conv(self.alt)
        azi, elev = orbital.get_observer_look(sat_lon, sat_lat,
                                              sat_alt, self.t,
                                              lon, lat, alt)
        np.testing.assert_allclose(azi.data, self.exp_azi)
        np.testing.assert_allclose(elev.data, self.exp_elev)
Exemple #16
0
    def get_angles(self, vis):
        from pyorbital.astronomy import get_alt_az, sun_zenith_angle
        from pyorbital.orbital import get_observer_look

        lons, lats = vis.attrs['area'].get_lonlats_dask(chunks=vis.data.chunks)
        suna = get_alt_az(vis.attrs['start_time'], lons, lats)[1]
        suna = np.rad2deg(suna)
        sunz = sun_zenith_angle(vis.attrs['start_time'], lons, lats)
        sat_lon, sat_lat, sat_alt = get_satpos(vis)
        sata, satel = get_observer_look(
            sat_lon,
            sat_lat,
            sat_alt / 1000.0,  # km
            vis.attrs['start_time'],
            lons,
            lats,
            0)
        satz = 90 - satel
        return sata, satz, suna, sunz
Exemple #17
0
 def get_angles(self, vis):
     """Get sun and satellite angles to use in crefl calculations."""
     from pyorbital.astronomy import get_alt_az, sun_zenith_angle
     from pyorbital.orbital import get_observer_look
     lons, lats = vis.attrs['area'].get_lonlats(chunks=vis.data.chunks)
     lons = da.where(lons >= 1e30, np.nan, lons)
     lats = da.where(lats >= 1e30, np.nan, lats)
     suna = get_alt_az(vis.attrs['start_time'], lons, lats)[1]
     suna = np.rad2deg(suna)
     sunz = sun_zenith_angle(vis.attrs['start_time'], lons, lats)
     sat_lon, sat_lat, sat_alt = get_satpos(vis)
     sata, satel = get_observer_look(
         sat_lon,
         sat_lat,
         sat_alt / 1000.0,  # km
         vis.attrs['start_time'],
         lons, lats, 0)
     satz = 90 - satel
     return sata, satz, suna, sunz
Exemple #18
0
    def __call__(self, projectables, optional_datasets=None, **info):
        """Get the corrected reflectance when removing Rayleigh scattering. Uses
        pyspectral.
        """

        from pyspectral.rayleigh import Rayleigh

        (vis, ) = projectables
        try:
            (sata, satz, suna, sunz) = optional_datasets
        except ValueError:
            from pyorbital.astronomy import get_alt_az, sun_zenith_angle
            from pyorbital.orbital import get_observer_look
            sunalt, suna = get_alt_az(vis.info['start_time'],
                                      *vis.info['area'].get_lonlats())
            sunz = sun_zenith_angle(vis.info['start_time'],
                                    *vis.info['area'].get_lonlats())
            lons, lats = vis.info['area'].get_lonlats()
            sata, satel = get_observer_look(vis.info['satellite_longitude'],
                                            vis.info['satellite_latitude'],
                                            vis.info['satellite_altitude'],
                                            vis.info['start_time'], lons, lats,
                                            0)
            satz = 90 - satel

        LOG.info('Removing Rayleigh scattering')

        ssadiff = np.abs(suna - sata)
        ssadiff = np.where(np.greater(ssadiff, 180), 360 - ssadiff, ssadiff)

        corrector = Rayleigh(vis.info['platform_name'],
                             vis.info['sensor'],
                             atmosphere='us-standard',
                             rural_aerosol=False)

        refl_cor_band = corrector.get_reflectance(sunz, satz, ssadiff,
                                                  vis.info['id'].wavelength[1],
                                                  vis)

        proj = Projectable(vis - refl_cor_band, copy=False, **vis.info)
        self.apply_modifier_info(vis, proj)

        return proj
    def test_xarray_with_dask(self):
        """Test with xarray DataArray with dask array as inputs"""
        from pyorbital import orbital
        import dask.array as da
        import xarray as xr

        def _xarr_conv(input):
            return xr.DataArray(da.from_array(input, chunks=2))
        sat_lon = _xarr_conv(self.sat_lon)
        sat_lat = _xarr_conv(self.sat_lat)
        sat_alt = _xarr_conv(self.sat_alt)
        lon = _xarr_conv(self.lon)
        lat = _xarr_conv(self.lat)
        alt = _xarr_conv(self.alt)
        azi, elev = orbital.get_observer_look(sat_lon, sat_lat,
                                              sat_alt, self.t,
                                              lon, lat, alt)
        np.testing.assert_allclose(azi.data.compute(), self.exp_azi)
        np.testing.assert_allclose(elev.data.compute(), self.exp_elev)
    def test_xarray_with_dask(self):
        """Test with xarray DataArray with dask array as inputs"""
        from pyorbital import orbital
        import dask.array as da
        import xarray as xr

        def _xarr_conv(input):
            return xr.DataArray(da.from_array(input, chunks=2))

        sat_lon = _xarr_conv(self.sat_lon)
        sat_lat = _xarr_conv(self.sat_lat)
        sat_alt = _xarr_conv(self.sat_alt)
        lon = _xarr_conv(self.lon)
        lat = _xarr_conv(self.lat)
        alt = _xarr_conv(self.alt)
        azi, elev = orbital.get_observer_look(sat_lon, sat_lat, sat_alt,
                                              self.t, lon, lat, alt)
        np.testing.assert_allclose(azi.data.compute(), self.exp_azi)
        np.testing.assert_allclose(elev.data.compute(), self.exp_elev)
Exemple #21
0
    def __call__(self, projectables, optional_datasets=None, **info):
        """Get the corrected reflectance when removing Rayleigh scattering. Uses
        pyspectral.
        """

        from pyspectral.rayleigh import Rayleigh

        (vis,) = projectables
        try:
            (sata, satz, suna, sunz) = optional_datasets
        except ValueError:
            from pyorbital.astronomy import get_alt_az, sun_zenith_angle
            from pyorbital.orbital import get_observer_look
            sunalt, suna = get_alt_az(
                vis.info['start_time'], *vis.info['area'].get_lonlats())
            sunz = sun_zenith_angle(
                vis.info['start_time'], *vis.info['area'].get_lonlats())
            lons, lats = vis.info['area'].get_lonlats()
            sata, satel = get_observer_look(vis.info['satellite_longitude'],
                                            vis.info['satellite_latitude'],
                                            vis.info['satellite_altitude'],
                                            vis.info['start_time'],
                                            lons, lats, 0)
            satz = 90 - satel

        LOG.info('Removing Rayleigh scattering')

        ssadiff = np.abs(suna - sata)
        ssadiff = np.where(np.greater(ssadiff, 180), 360 - ssadiff, ssadiff)

        corrector = Rayleigh(
            vis.info['platform_name'], vis.info['sensor'], atmosphere='us-standard', rural_aerosol=False)

        refl_cor_band = corrector.get_reflectance(
            sunz, satz, ssadiff, vis.info['id'].wavelength[1], vis)

        proj = Projectable(vis - refl_cor_band,
                           copy=False,
                           **vis.info)
        self.apply_modifier_info(vis, proj)

        return proj
Exemple #22
0
    def __call__(self, projectables, optional_datasets=None, **info):
        """Get the atmospherical correction.

        Uses pyspectral.
        """
        from pyspectral.atm_correction_ir import AtmosphericalCorrection

        band = projectables[0]

        if optional_datasets:
            satz = optional_datasets[0]
        else:
            from pyorbital.orbital import get_observer_look
            lons, lats = band.attrs['area'].get_lonlats(
                chunks=band.data.chunks)
            sat_lon, sat_lat, sat_alt = get_satpos(band)
            try:
                dummy, satel = get_observer_look(
                    sat_lon,
                    sat_lat,
                    sat_alt / 1000.0,  # km
                    band.attrs['start_time'],
                    lons,
                    lats,
                    0)
            except KeyError:
                raise KeyError('Band info is missing some meta data!')
            satz = 90 - satel
            del satel

        logger.info('Correction for limb cooling')
        corrector = AtmosphericalCorrection(band.attrs['platform_name'],
                                            band.attrs['sensor'])

        atm_corr = corrector.get_correction(satz, band.attrs['name'], band)
        proj = xr.DataArray(atm_corr,
                            attrs=band.attrs,
                            dims=band.dims,
                            coords=band.coords)
        self.apply_modifier_info(band, proj)

        return proj
Exemple #23
0
    def __call__(self, projectables, optional_datasets=None, **info):
        """Get the atmospherical correction. Uses pyspectral.
        """
        from pyspectral.atm_correction_ir import AtmosphericalCorrection

        band = projectables[0]

        if optional_datasets:
            satz = optional_datasets[0]
        else:
            from pyorbital.orbital import get_observer_look
            lons, lats = band.attrs['area'].get_lonlats_dask(CHUNK_SIZE)

            try:
                dummy, satel = get_observer_look(band.attrs['satellite_longitude'],
                                                 band.attrs[
                                                     'satellite_latitude'],
                                                 band.attrs[
                                                     'satellite_altitude'],
                                                 band.attrs['start_time'],
                                                 lons, lats, 0)
            except KeyError:
                raise KeyError(
                    'Band info is missing some meta data!')
            satz = 90 - satel
            del satel

        LOG.info('Correction for limb cooling')
        corrector = AtmosphericalCorrection(band.attrs['platform_name'],
                                            band.attrs['sensor'])

        atm_corr = corrector.get_correction(satz, band.attrs['name'], band)
        proj = band - atm_corr
        proj.attrs = band.attrs
        self.apply_modifier_info(band, proj)

        return proj
Exemple #24
0
def process_one_scan(tslot_files,
                     out_path,
                     process_buggy_satellite_zenith_angles=False):
    """ Make level 1c files in PPS-format """
    tic = time.time()
    image_num = 0  # name of first dataset is image0
    #if len(tslot_files) != 8 * len(BANDNAMES) + 2:
    #    raise Exception("Some data is missing")
    platform_shortname = p__.parse(os.path.basename(
        tslot_files[0]))['platform_shortname']
    start_time = p__.parse(os.path.basename(tslot_files[0]))['start_time']
    platform_name = PLATFORM_SHORTNAMES[platform_shortname]
    #Load channel data for one scene and set some attributes
    coefs = get_calibration_for_time(platform=platform_shortname,
                                     time=start_time)

    scn_ = Scene(reader='seviri_l1b_hrit',
                 filenames=tslot_files,
                 reader_kwargs={
                     'calib_mode': CALIB_MODE,
                     'ext_calib_coefs': coefs
                 })
    scn_.attrs['platform_name'] = platform_name

    #SEVIRI data only
    if scn_.attrs['sensor'] == {'seviri'}:
        sensor = 'seviri'
        scn_.load(BANDNAMES)
    for band in BANDNAMES:
        idtag = PPS_TAGNAMES[band]
        scn_[band].attrs['id_tag'] = idtag
        scn_[band].attrs['description'] = 'SEVIRI ' + str(band)
        scn_[band].attrs['sun_earth_distance_correction_applied'] = 'False'
        scn_[band].attrs['sun_earth_distance_correction_factor'] = 1.0
        scn_[band].attrs['sun_zenith_angle_correction_applied'] = 'False'
        scn_[band].attrs['name'] = "image{:d}".format(image_num)
        scn_[band].attrs['coordinates'] = 'lon lat'
        image_num += 1

    #correct area
    area_corr = pyresample.geometry.AreaDefinition(
        'seviri-corrected', 'Corrected SEVIRI L1.5 grid (since Dec 2017)',
        'geosmsg', {
            'a': 6378169.00,
            'b': 6356583.80,
            'h': 35785831.0,
            'lon_0': 0.0,
            'proj': 'geos',
            'units': 'm'
        }, 3712, 3712, (5567248.28340708, 5570248.686685662,
                        -5570248.686685662, -5567248.28340708))
    if not scn_['IR_108'].attrs['georef_offset_corrected']:
        scn_ = scn_.resample(area_corr)
        print(scn_['IR_108'].attrs['georef_offset_corrected'])

    #import pdb;pdb.set_trace()
    #Set som header attributes:
    scn_.attrs['platform'] = platform_name
    scn_.attrs['instrument'] = sensor.upper()
    scn_.attrs['source'] = "seviri2pps.py"
    scn_.attrs['orbit_number'] = "99999"
    #scn_.attrs['orbit'] = "99999"
    nowutc = datetime.utcnow()
    scn_.attrs['date_created'] = nowutc.strftime("%Y-%m-%dT%H:%M:%SZ")
    #Find lat/lon data
    irch = scn_['IR_108']
    lons, lats = irch.attrs['area'].get_lonlats()
    lons[lons > 360] = -999.0
    lons[lons < -360] = -999.0
    lats[lats > 360] = -999.0
    lats[lats < -360] = -999.0

    #Find angles data
    sunalt, suna = get_alt_az(irch.attrs['start_time'],
                              *irch.attrs['area'].get_lonlats())
    suna = np.rad2deg(suna)
    sunz = sun_zenith_angle(irch.attrs['start_time'],
                            *irch.attrs['area'].get_lonlats())

    # if:
    #   Buggy data is requested buggy data is prepared!
    # elif:
    #   1) get_observer_look() gives wrong answer ...
    #   ... for satellite altitude in m. AND
    #   2) get_observer_look() gives correct answer ...
    #   ....  for satellite altitude in km. AND
    #   3) Satellite altitude is m.:
    #    => Satellite alltitude need to be converted to km.
    # else:
    #    => There have been updates to SatPy and this script
    #       need to be modified.
    if process_buggy_satellite_zenith_angles:
        print(" Making buggy satellite zenith angels on purpose!")
        sata, satel = get_observer_look(
            irch.attrs['orbital_parameters']['satellite_actual_longitude'],
            irch.attrs['orbital_parameters']['satellite_actual_latitude'],
            irch.attrs['orbital_parameters']['satellite_actual_altitude'],
            irch.attrs['start_time'], lons, lats, 0)
    elif (get_observer_look(0, 0, 36000 * 1000, datetime.utcnow(),
                            np.array([16]), np.array([58]), np.array(
                                [0]))[1] > 30
          and get_observer_look(0, 0, 36000, datetime.utcnow(), np.array([16]),
                                np.array([58]), np.array([0]))[1] < 23
          and irch.attrs['orbital_parameters']['satellite_actual_altitude'] >
          38000):
        sata, satel = get_observer_look(
            irch.attrs['orbital_parameters']['satellite_actual_longitude'],
            irch.attrs['orbital_parameters']['satellite_actual_latitude'],
            0.001 *
            irch.attrs['orbital_parameters']['satellite_actual_altitude'],
            irch.attrs['start_time'], lons, lats, 0)
    else:
        raise UnexpectedSatpyVersion(
            "You might have a newer version of satpy/pyorbital that"
            "handles units. In that case the m => km conversion might"
            "be unneeded and wrong.")

    satz = 90 - satel
    azidiff = make_azidiff_angle(sata, suna, -32767)
    #Add lat/lon  and angles datasets to the scen object
    my_coords = scn_['IR_108'].coords
    my_coords['time'] = irch.attrs['start_time']
    scn_['lat'] = xr.DataArray(da.from_array(lats, chunks=(53, 3712)),
                               dims=['y', 'x'],
                               coords={
                                   'y': scn_['IR_108']['y'],
                                   'x': scn_['IR_108']['x']
                               })
    scn_['lat'].attrs['long_name'] = 'latitude coordinate'
    scn_['lat'].attrs['standard_name'] = 'latitude'
    scn_['lat'].attrs['units'] = 'degrees_north'
    scn_['lat'].attrs['start_time'] = irch.attrs['start_time']
    scn_['lat'].attrs['end_time'] = irch.attrs['end_time']
    scn_['lon'] = xr.DataArray(da.from_array(lons, chunks=(53, 3712)),
                               dims=['y', 'x'],
                               coords={
                                   'y': scn_['IR_108']['y'],
                                   'x': scn_['IR_108']['x']
                               })
    scn_['lon'].attrs['long_name'] = 'longitude coordinate'
    scn_['lon'].attrs['standard_name'] = 'longitude'
    scn_['lon'].attrs['units'] = 'degrees_east'
    scn_['lon'].attrs['start_time'] = irch.attrs['start_time']
    scn_['lon'].attrs['end_time'] = irch.attrs['end_time']
    #sunzenith
    scn_['sunzenith'] = xr.DataArray(da.from_array(sunz[:, :],
                                                   chunks=(53, 3712)),
                                     dims=['y', 'x'],
                                     coords=my_coords)
    scn_['sunzenith'].attrs['id_tag'] = 'sunzenith'
    scn_['sunzenith'].attrs['long_name'] = 'sun zenith angle'
    scn_['sunzenith'].attrs['standard_name'] = 'solar_zenith_angle'
    scn_['sunzenith'].attrs['valid_range'] = [0, 18000]
    scn_['sunzenith'].attrs['name'] = "image{:d}".format(image_num)
    image_num += 1
    #satzenith
    scn_['satzenith'] = xr.DataArray(da.from_array(satz[:, :],
                                                   chunks=(53, 3712)),
                                     dims=['y', 'x'],
                                     coords=my_coords)
    scn_['satzenith'].attrs['id_tag'] = 'satzenith'
    scn_['satzenith'].attrs['long_name'] = 'satellite zenith angle'
    scn_['satzenith'].attrs['standard_name'] = 'platform_zenith_angle'
    scn_['satzenith'].attrs['valid_range'] = [0, 9000]
    scn_['satzenith'].attrs['name'] = "image{:d}".format(image_num)
    image_num += 1
    #azidiff
    scn_['azimuthdiff'] = xr.DataArray(da.from_array(azidiff[:, :],
                                                     chunks=(53, 3712)),
                                       dims=['y', 'x'],
                                       coords=my_coords)
    scn_['azimuthdiff'].attrs['id_tag'] = 'azimuthdiff'
    #scn_['azimuthdiff'].attrs['standard_name'] = (
    #    'angle_of_rotation_from_solar_azimuth_to_platform_azimuth')
    scn_['azimuthdiff'].attrs[
        'long_name'] = 'absoulte azimuth difference angle'
    scn_['azimuthdiff'].attrs['valid_range'] = [0, 18000]
    scn_['azimuthdiff'].attrs['name'] = "image{:d}".format(image_num)
    image_num += 1
    for angle in ['azimuthdiff', 'satzenith', 'sunzenith']:
        scn_[angle].attrs['units'] = 'degree'
        for attr in irch.attrs.keys():
            if attr in [
                    "start_time", "end_time", "navigation",
                    "georef_offset_corrected", "projection"
            ]:
                scn_[angle].attrs[attr] = irch.attrs[attr]

    #Get filename
    start_time = scn_['IR_108'].attrs['start_time']
    end_time = scn_['IR_108'].attrs['end_time']
    filename = os.path.join(
        out_path, "S_NWC_seviri_{:s}_{:s}_{:s}Z_{:s}Z.nc".format(
            platform_name.lower().replace('-', ''), "99999",
            start_time.strftime('%Y%m%dT%H%M%S%f')[:-5],
            end_time.strftime('%Y%m%dT%H%M%S%f')[:-5]))

    #Encoding for channels
    save_info = {}
    for band in BANDNAMES:
        idtag = PPS_TAGNAMES[band]
        name = scn_[band].attrs['name']
        scn_[band].attrs.pop('area', None)
        # Add time coordinate. To make cfwriter aware that we want 3D data.
        my_coords = scn_[band].coords
        my_coords['time'] = irch.attrs['start_time']

        if 'tb' in idtag:
            save_info[name] = {
                'dtype': 'int16',
                'scale_factor': 0.01,
                '_FillValue': -32767,
                'zlib': True,
                'complevel': 4,
                'add_offset': 273.15
            }
        else:
            save_info[name] = {
                'dtype': 'int16',
                'scale_factor': 0.01,
                'zlib': True,
                'complevel': 4,
                '_FillValue': -32767,
                'add_offset': 0.0
            }
    #Encoding for angles and lat/lon
    for name in ['image11', 'image12', 'image13']:
        save_info[name] = {
            'dtype': 'int16',
            'scale_factor': 0.01,
            'zlib': True,
            'complevel': 4,
            '_FillValue': -32767,
            'add_offset': 0.0
        }

    for name in ['lon', 'lat']:
        save_info[name] = {
            'dtype': 'float32',
            'zlib': True,
            'complevel': 4,
            '_FillValue': -999.0
        }
    header_attrs = scn_.attrs.copy()
    header_attrs['start_time'] = time.strftime(
        "%Y-%m-%d %H:%M:%S", irch.attrs['start_time'].timetuple())
    header_attrs['end_time'] = time.strftime(
        "%Y-%m-%d %H:%M:%S", irch.attrs['end_time'].timetuple())
    header_attrs['sensor'] = sensor.lower()
    header_attrs.pop('platform_name', None)

    scn_.save_datasets(writer='cf',
                       filename=filename,
                       header_attrs=header_attrs,
                       engine='netcdf4',
                       encoding=save_info,
                       include_lonlats=False,
                       pretty=True,
                       flatten_attrs=True,
                       exclude_attrs=['raw_metadata'])
    print("Saved file {:s} after {:3.1f} seconds".format(
        os.path.basename(filename),
        time.time() - tic))  #About 40 seconds
    return filename
    def read2h5(self, infile):
        # 主程序
        #         print(infile)

        try:
            f = h5py.File(infile, 'r')
        except:
            errordir = os.path.dirname(infile) + os.sep + 'error'
            if not os.path.exists(errordir):
                os.makedirs(errordir)
            errors = glob.glob(infile[0:-3] + '*')
            for error in errors:
                shutil.move(error, errordir + os.sep + os.path.basename(error))
            return

        #         输出文件名
        millisecond = f['Millisecond/Millisecond'][()]
        hour = np.min(millisecond) // (1000 * 60 * 60)
        minute = (np.min(millisecond) - hour * (1000 * 60 * 60)) // (1000 * 60)
        second = (np.min(millisecond) - hour *
                  (1000 * 60 * 60) - minute * 1000 * 60) // (1000)

        time1 = datetime.datetime(int('20' + os.path.basename(infile)[6:8]), 1, 1) + \
                datetime.timedelta(days=int(os.path.basename(infile)[8:11]) - 1) + \
                datetime.timedelta(hours=int(hour)) + datetime.timedelta(minutes=int(minute)) + \
                datetime.timedelta(seconds=int(second))

        hour = np.max(millisecond) // (1000 * 60 * 60)
        minute = (np.max(millisecond) - hour * (1000 * 60 * 60)) // (1000 * 60)
        second = (np.max(millisecond) - hour *
                  (1000 * 60 * 60) - minute * 1000 * 60) // (1000)

        time2 = datetime.datetime(int('20' + os.path.basename(infile)[6:8]), 1, 1) + \
                datetime.timedelta(days=int(os.path.basename(infile)[8:11]) - 1) + \
                datetime.timedelta(hours=int(hour)) + datetime.timedelta(minutes=int(minute)) + \
                datetime.timedelta(seconds=int(second))

        # del millisecond

        tree = ET.ElementTree(file=infile[0:-2] + 'xml')
        root = tree.getroot()
        node = root[0].find("OrbitNumber")

        outfile = os.path.dirname(infile) + os.sep + 'H1A_OPER_OCT_L1B_' + time1.strftime("%Y%m%dT%H%M%S") + '_' + \
                  time2.strftime("%Y%m%dT%H%M%S") + '_' + node.text + '_10.h5'

        if os.access(outfile, os.R_OK):
            return outfile

        f_new = h5py.File(outfile, 'a')

        # Calibration
        calibration = f_new.create_group('Calibration')
        data = np.zeros((10, 1))
        calibration.create_dataset('Calibration Coefficients Offsets factor',
                                   (data.shape[0], data.shape[1]),
                                   dtype='f',
                                   data=data)
        del data
        data = np.ones((10, 1))
        calibration.create_dataset('Calibration Coefficients Scale factor',
                                   (data.shape[0], data.shape[1]),
                                   dtype='f',
                                   data=data)
        del data
        data = np.ones((10, 1))
        calibration.create_dataset('Mirror-side Correction Scale Factors',
                                   (data.shape[0], 1),
                                   dtype='f',
                                   data=data[:, 0])
        data = np.zeros((10, 1))
        calibration.create_dataset('Mirror-side Correction Offsets Factors',
                                   (data.shape[0], 1),
                                   dtype='f',
                                   data=data[:, 0])
        del data
        data = np.zeros((10, 1))
        calibration.create_dataset('Time-dependent Correction Constant Terms',
                                   (data.shape[0], data.shape[1]),
                                   dtype='f',
                                   data=data)
        del data
        data = np.ones((10, 1))
        calibration.create_dataset(
            'Time-dependent Correction Linear Coefficients',
            (data.shape[0], data.shape[1]),
            dtype='f',
            data=data)
        del data
        data = np.ones((10, 1))
        calibration.create_dataset(
            'Time-dependent Correction Quadratic Coefficients',
            (data.shape[0], data.shape[1]),
            dtype='f',
            data=data)
        del data
        data = np.array([[1], [1], [1], [1], [1], [1], [1], [1]])
        calibration.create_dataset('Vicarious Calibration gan factor',
                                   (data.shape[0], data.shape[1]),
                                   dtype='f',
                                   data=data)
        del data
        calibration.attrs['Calibration Entry Year'] = np.int16(2019)
        calibration.attrs['Calibration Entry Day'] = np.int16(330)
        calibration.attrs['Calibration Reference Year'] = np.int16(0)
        calibration.attrs['Calibration Reference Day'] = np.int16(0)
        calibration.attrs['Calibration Reference Minute'] = np.int32(0)
        calibration.attrs['Visible Channel Radiance Data Unit'] = np.string_(
            'mWcm-2 um-1 sr-1')
        calibration.attrs['Infrared Channel Radiance Data Unit'] = np.string_(
            'mWcm-2 um-1 sr-1')

        # geophysical Data
        group = f_new.create_group('Geophysical Data')
        for j, dataset_of_group in enumerate(f['Scan image data'].items()):
            dataset = group.create_dataset(dataset_of_group[0],
                                           dataset_of_group[1].shape,
                                           dtype=np.float32,
                                           data=dataset_of_group[1][()])
            dataset.attrs['Unit'] = np.string_('None')
            dataset.attrs['long_name'] = np.string_('Top of Atmosphere B' +
                                                    dataset_of_group[0][2:] +
                                                    'nm/um radiance counts')
        del group, dataset

        # Extra Data
        group = f_new.create_group('Extra Data')
        Ext_xxx = [
            '412', '443', '490', '520', '565', '670', '750', '865', '11', '12'
        ]
        try:
            L0file = glob.glob(
                os.path.dirname(infile) + os.sep +
                os.path.basename(infile)[0:-6] + 'L0.bz2')[0]
            L0 = L0parase()
            data = L0.run_this_function(L0file)
        #         print('LA')
        except:
            data = np.zeros(shape=(10, dataset_of_group[1].shape[0], 43))
        for j, ext_x in enumerate(Ext_xxx):
            ext = group.create_dataset('Ext_' + ext_x, (data.shape[1], 43),
                                       dtype='uint16',
                                       data=data[j, :, :])
            if len(ext_x) == 2:
                ext.attrs['long_name'] = np.string_('B' + ext_x +
                                                    'um Extra data counts')
            else:
                ext.attrs['long_name'] = np.string_('B' + ext_x +
                                                    'nm Extra data counts')
        del group, ext

        # navigaton data
        group = f_new.create_group('Navigation Data')

        # 计算四个角度

        # =======================================================================================================================
        lat = f['Pixels location data/latitude'][()]
        lon = f['Pixels location data/longitude'][()]
        millisecond = f['Millisecond/Millisecond'][()]
        # year = np.ones(shape=lat.shape) * int('20' + os.path.basename(infile)[6:8])
        # # year= np.array([[2003,2003],[2003,2004]])
        # # month=np.array([[1,2],[6,12]])
        # # day=np.array([[2,16],[14,2]])
        # DOY = np.ones(shape=lat.shape) * int(os.path.basename(infile)[8:11])
        #
        # millisecond = np.repeat(millisecond, 102, axis=1)
        # # hour = np.array([[1, 2], [3, 4]])
        # hour = np.trunc(millisecond / 1000 / 3600)
        # minu = np.trunc((millisecond - hour * 1000 * 3600) / 1000 / 60)
        # sec = (millisecond - hour * 1000 * 3600 - minu * 1000 * 60) / 1000
        # # minu=np.array([[23,23],[23,22]])
        # # sec=np.array([[1,2],[24,55]])
        #
        # TimeZone = np.trunc((lon - np.sign(lon) * 7.5) / 15 + np.sign(lon))
        #
        # # N0   sitar=θ
        # N0 = 79.6764 + 0.2422 * (year - 1985) - np.trunc((year - 1985) / 4.0)
        # sitar = 2 * np.pi * (DOY - N0) / 365.2422
        # ED1 = 0.3723 + 23.2567 * np.sin(sitar) + 0.1149 * np.sin(2 * sitar) - 0.1712 * np.sin(
        #     3 * sitar) - 0.758 * np.cos(
        #     sitar) + 0.3656 * np.cos(2 * sitar) + 0.0201 * np.cos(3 * sitar)
        # ED = ED1 * np.pi / 180  # ED本身有符号
        #
        # dLon = (lon - TimeZone * 15.0) * np.sign(lon)
        #
        # # 时差
        # Et = 0.0028 - 1.9857 * np.sin(sitar) + 9.9059 * np.sin(2 * sitar) - 7.0924 * np.cos(sitar) - 0.6882 * np.cos(
        #     2 * sitar)
        # gtdt1 = hour + minu / 60.0 + sec / 3600.0 + dLon / 15  # 地方时
        # gtdt = gtdt1 + Et / 60.0
        # dTimeAngle1 = 15.0 * (gtdt - 12)
        # dTimeAngle = dTimeAngle1 * np.pi / 180
        # latitudeArc = lat * np.pi / 180
        #
        # # 高度角计算公式
        # HeightAngleArc = np.arcsin(
        #     np.sin(latitudeArc) * np.sin(ED) + np.cos(latitudeArc) * np.cos(ED) * np.cos(dTimeAngle))
        # # 方位角计算公式
        # CosAzimuthAngle = (np.sin(HeightAngleArc) * np.sin(latitudeArc) - np.sin(ED)) / np.cos(HeightAngleArc) / np.cos(
        #     latitudeArc)
        # AzimuthAngleArc = np.arccos(CosAzimuthAngle)
        # HeightAngle = HeightAngleArc * 180 / np.pi
        # sza = 90 - HeightAngle
        # AzimuthAngle1 = AzimuthAngleArc * 180 / np.pi
        # saa = 180 + AzimuthAngle1 * np.sign(dTimeAngle)
        # ========================================================================================================================
        # 使用pysolar计算sza saa
        time = [*map(
            lambda t: datetime.datetime(int('20' + os.path.basename(infile)[6:8]), 1, 1, tzinfo=datetime.timezone.utc) + \
                      datetime.timedelta(days=(int(os.path.basename(infile)[8:11]) - 1)) + \
                      datetime.timedelta(milliseconds=t[0]), millisecond.tolist())]

        time = np.repeat(np.array(time).reshape(-1, 1), 102, axis=1)
        time = time.flatten()
        lat = lat.flatten()
        lon = lon.flatten()

        sza = np.array([
            *map(lambda sx, sy, t: 90 - get_altitude(sx, sy, t), lat, lon,
                 time)
        ])
        sza = sza.reshape(-1, 102)
        saa = np.array(
            [*map(lambda sx, sy, t: get_azimuth(sx, sy, t), lat, lon, time)])
        saa = saa.reshape(-1, 102)

        # sza = np.array([*map(lambda x, y, t: 90.0 - get_altitude(x, y, t), lat, lon, time)]).reshape(-1, 102)
        # saa = np.array([*map(lambda x, y, t: get_azimuth(x, y, t), lat, lon, time)]).reshape(-1, 102)
        center_lat = f['Center Latitude/Center Latitude'][()]
        center_lon = f['Center Longitude/Center Longitude'][()]
        center_lat = np.repeat(center_lat, 102, axis=1)
        center_lon = np.repeat(center_lon, 102, axis=1)
        center_lat = center_lat.flatten()
        center_lon = center_lon.flatten()
        # pyorbital.orbital.get_observer_look(sat_lon, sat_lat, sat_alt, utc_time, lon, lat, alt)
        view_angle = np.array([
            *map(
                lambda sx, sy, t, x, y: orbital.get_observer_look(
                    np.atleast_1d(sx), np.atleast_1d(sy), np.atleast_1d(798),
                    t, np.atleast_1d(x), np.atleast_1d(y), np.atleast_1d(0)),
                center_lon, center_lat, time, lon, lat)
        ])
        vaa = (view_angle[:, 0]).reshape(-1, 102)
        vza = (90 - view_angle[:, 1]).reshape(-1, 102)
        lon = lon.reshape(-1, 102)
        lat = lat.reshape(-1, 102)

        parameters = [lon, lat, sza, saa, vza, vaa]
        parameter_ID = [
            'Longitude', 'Latitude', 'Solar Zenith Angle',
            'Solar Azimuth Angle', 'Satellite Zenith Angle',
            'Satellite Azimuth Angle'
        ]

        for ID, parameter in enumerate(parameters):
            nl = np.arange(parameter.shape[0])
            #             当经度跨过180度经线时,
            if parameter_ID[ID] == 'Longitude':
                if parameter.max() - parameter.min() > 300:  # 跨180经度时
                    parameter[parameter < 0] = parameter[
                        parameter < 0] + 360.0  # 180经线两边数值连续,以正确插值
                    parameter_inter = np.array(
                        [*map(lambda n: self.interp(parameter[n, :]), nl)])
                    parameter_inter[parameter_inter > 180] = parameter_inter[
                        parameter_inter > 180] - 360.0  # 变回来
                    group.create_dataset(
                        parameter_ID[ID],
                        (parameter_inter.shape[0], parameter_inter.shape[1]),
                        dtype=np.float32,
                        data=parameter_inter)
                    continue  # 经度无需再写
            #             按行计算
            parameter_inter = np.array(
                [*map(lambda n: self.interp(parameter[n, :]), nl)])
            group.create_dataset(
                parameter_ID[ID],
                (parameter_inter.shape[0], parameter_inter.shape[1]),
                dtype='f',
                data=parameter_inter)

        group.attrs['Navigation Point Counts'] = np.int32(
            parameter_inter.shape[1])
        group.attrs['First Navigation Points'] = np.int32(1)
        group.attrs['Pixel-intervals of Navigation Point'] = np.int32(1)
        del group, parameters

        #         QC Attributes
        group = f_new.create_group('QC Attributes')
        parameters = ['Staturated Pixel Counts', 'Zero Pixel Counts']
        data = f['Saturated Pixels/Saturated Pixels'][()]
        group.create_dataset('Staturated Pixel Counts',
                             (data.shape[0], data.shape[1]),
                             dtype='uint16',
                             data=data)
        data = f['Zero Pixels/Zero Pixels'][()]
        group.create_dataset('Zero Pixel Counts',
                             (data.shape[0], data.shape[1]),
                             dtype='uint16',
                             data=data)
        group.attrs['Missing Frame Counts'] = np.int32(0)
        del group, data

        #         Scan Line Attributes
        group = f_new.create_group('Scan Line Attributes')
        # data = (f.select('Attitude Parameters')).get()
        # group.create_dataset('Attitude Parameters', (data.shape[0], data.shape[1]), dtype=type(data[0][0]), data=data)
        # del data
        data = f['Center Latitude/Center Latitude'][()]
        group.create_dataset('Center Latitude', (data.shape[0], data.shape[1]),
                             dtype=type(data[0][0]),
                             data=data)
        del data

        data = f['Center Latitude/Center Latitude'][()]
        group.create_dataset('Center Longitude',
                             (data.shape[0], data.shape[1]),
                             dtype=type(data[0][0]),
                             data=data)
        del data

        data = f['Center Solar Zenith/Center Solar Zenith'][()]
        group.create_dataset('Center Solar Zenith Angle',
                             (data.shape[0], data.shape[1]),
                             dtype=type(data[0][0]),
                             data=data)
        del data

        data = f['Start Latitude/Start Latitude'][()]
        group.create_dataset('Start Latitude', (data.shape[0], data.shape[1]),
                             dtype=type(data[0][0]),
                             data=data)
        del data

        data = f['Start Longitude/Start Longitude'][()]
        group.create_dataset('Start Longitude', (data.shape[0], data.shape[1]),
                             dtype=type(data[0][0]),
                             data=data)
        del data

        data = f['End Latitude/End Latitude'][()]
        group.create_dataset('End Latitude', (data.shape[0], data.shape[1]),
                             dtype=type(data[0][0]),
                             data=data)
        del data

        data = f['End Longitude/End Longitude'][()]
        group.create_dataset('End Longitude', (data.shape[0], data.shape[1]),
                             dtype=type(data[0][0]),
                             data=data)

        frame = (np.arange(data.shape[0])) % 8
        frame.shape = (frame.shape[0], 1)
        group.create_dataset('Frame Number', (frame.shape[0], frame.shape[1]),
                             dtype='int16',
                             data=frame)
        del data

        # data = (f.select('Infrared Channel Calibration Data')).get()
        # group.create_dataset('Infrared Channel Calibration Data', (data.shape[0], data.shape[1], data.shape[2]),
        #                      dtype=type(data[0][0][0]), data=data)
        # del data

        data = f['Millisecond/Millisecond'][()]
        millisecond = group.create_dataset('Millisecond',
                                           (data.shape[0], data.shape[1]),
                                           dtype=np.float64,
                                           data=data)
        millisecond.attrs['Fillin_value'] = -999.0
        millisecond.attrs['Unit'] = np.string_(
            'milliseconds since at 00:00:00 on this day ')
        del data

        # data = (f.select('Mirror-side Flag')).get()
        #     # group.create_dataset('Mirror-side Flag', (data.shape[0], data.shape[1]), dtype='|S1', data=data)
        #     # del data
        # no ORB_VEC dataset in HDF
        # data = (f.select('ORB_VEC')).get()
        # group.create_dataset('ORB_VEC', (data.shape[0], data.shape[1]), dtype=type(data[0][0]), data=data)
        # del data
        group.attrs['Instrument Parameters'] = np.string_(
            '412nm,443nm,490nm,520nm,565nm,670nm,750nm,865nm,10.3-11.4um,'
            '11.5-12.5um')

        #         file attributes

        f_new.attrs.create('Calibration Flag',
                           'None',
                           shape=(1, ),
                           dtype='S10')
        f_new.attrs.create('Calibration Version',
                           '1.00',
                           shape=(1, ),
                           dtype='S10')
        f_new.attrs.create('DayorNight', 'D', shape=(1, ), dtype='S10')
        distance = 1 - 0.01672 * np.cos(
            0.9856 * (int(os.path.basename(infile)[8:11]) - 4))
        f_new.attrs.create('Earth-Sun Distance',
                           distance,
                           shape=(1, ),
                           dtype=np.float32)
        f_new.attrs.create('Easternmost Longitude',
                           np.max(lon),
                           shape=(1, ),
                           dtype=np.float32)
        f_new.attrs.create('End Center Longitude',
                           center_lon[-1],
                           shape=(1, ),
                           dtype=np.float32)
        f_new.attrs.create('End Center Latitude',
                           center_lat[-1],
                           shape=(1, ),
                           dtype=np.float32)
        f_new.attrs.create('GEO Correction Method',
                           'Unkonwn',
                           shape=(1, ),
                           dtype='S10')
        f_new.attrs.create('Input File',
                           os.path.basename(infile),
                           shape=(1, ),
                           dtype='S10')
        f_new.attrs.create('Latitude Unit', 'degree', shape=(1, ), dtype='S10')
        f_new.attrs.create('Longitude Unit',
                           'degree',
                           shape=(1, ),
                           dtype='S10')
        f_new.attrs.create('Lower Left Latitude',
                           lat[-1, 0],
                           shape=(1, ),
                           dtype=np.float32)
        f_new.attrs.create('Lower Left Longitude',
                           lon[-1, 0],
                           shape=(1, ),
                           dtype=np.float32)
        f_new.attrs.create('Lower Right Latitude',
                           lat[-1, -1],
                           shape=(1, ),
                           dtype=np.float32)
        f_new.attrs.create('Lower Right Longitude',
                           lon[-1, -1],
                           shape=(1, ),
                           dtype=np.float32)

        node = root[0].find("NodeCrossingTime")
        time = datetime.datetime(int('20' + node.text[0:2]), 1, 1) + datetime.timedelta(days=int(node.text[2:5]) - 1) + \
               datetime.timedelta(hours=int(node.text[5:7])) + datetime.timedelta(minutes=int(node.text[7:9]))
        f_new.attrs.create('Node Crossing Time',
                           time.strftime("%Y-%m-%dT%H-%M-%S"),
                           shape=(1, ),
                           dtype='S10')
        f_new.attrs.create('Northernmost Latitude',
                           np.max(lat),
                           shape=(1, ),
                           dtype=np.float32)
        f_new.attrs.create('Number of Bands', 16, shape=(1, ), dtype=np.int16)
        f_new.attrs.create('Number of Scan Lines',
                           f['Scan image data/L_412'].shape[0],
                           shape=(1, ),
                           dtype=np.int32)
        f_new.attrs.create('Orbit Node Longitude',
                           root[0].find("OrbitNodeLongitude").text,
                           shape=(1, ),
                           dtype=np.float32)
        f_new.attrs.create('Orbit Number',
                           root[0].find("OrbitNumber").text,
                           shape=(1, ),
                           dtype=np.int32)
        f_new.attrs.create('Pixels Per Scan Line',
                           1024,
                           shape=(1, ),
                           dtype=np.int32)
        f_new.attrs.create('Processing Center',
                           'NSOAS',
                           shape=(1, ),
                           dtype='S10')
        f_new.attrs.create('Processing Control',
                           'IMG',
                           shape=(1, ),
                           dtype='S10')
        f_new.attrs.create(
            'Processing Time',
            datetime.datetime.now().strftime("%Y-%m-%dT%H-%M-%S"),
            shape=(1, ),
            dtype='S10')
        f_new.attrs.create('Product Name',
                           os.path.basename(outfile),
                           shape=(1, ),
                           dtype='S10')
        f_new.attrs.create('Radiometric Method',
                           'unknown',
                           shape=(1, ),
                           dtype='S10')

        day = datetime.datetime(int('20' + os.path.basename(infile)[6:8]), 1, 1) + \
              datetime.timedelta(days=int(os.path.basename(infile)[8:11]) - 1)
        f_new.attrs.create('Range Beginning Date',
                           day.strftime("%Y%m%d") + ' ' +
                           os.path.basename(infile)[8:11],
                           shape=(1, ),
                           dtype='S10')
        f_new.attrs.create('Range Ending Date',
                           day.strftime("%Y%m%d") + ' ' +
                           os.path.basename(infile)[8:11],
                           shape=(1, ),
                           dtype='S10')
        hour = np.min(millisecond) % (1000 * 60 * 60)
        minute = (np.min(millisecond) - hour * (1000 * 60 * 60)) % (1000 * 60)
        second = (np.min(millisecond) - hour *
                  (1000 * 60 * 60) - minute * 1000 * 60) / (1000)
        f_new.attrs.create('Range Beginning Time',
                           str(hour) + ':' + str(minute) + ':' + str(second),
                           shape=(1, ),
                           dtype='S10')

        hour = np.max(millisecond) // (1000 * 60 * 60)
        minute = (np.max(millisecond) - hour * (1000 * 60 * 60)) // (1000 * 60)
        second = (np.max(millisecond) - hour *
                  (1000 * 60 * 60) - minute * 1000 * 60) // (1000)
        f_new.attrs.create('Range Ending Time',
                           str(hour) + ':' + str(minute) + ':' + str(second),
                           shape=(1, ),
                           dtype='S10')
        f_new.attrs.create('Realtime Delay Flag',
                           'Unknown',
                           shape=(1, ),
                           dtype='S10')
        f_new.attrs.create('Receiving End Time',
                           'Unknown',
                           shape=(1, ),
                           dtype='S10')
        f_new.attrs.create('Receiving Start Time',
                           'Unknown',
                           shape=(1, ),
                           dtype='S10')
        f_new.attrs.create('Ref Band Number', 6, shape=(1, ), dtype=np.int32)

        node = root[0].find("MissionCharacter")
        f_new.attrs.create('Satellite Character',
                           node.text,
                           shape=(1, ),
                           dtype='S10')
        f_new.attrs.create('Satellite Name', 'HY-1A', shape=(1, ), dtype='S10')
        node = root[0].find("SceneCenterLatitude")
        f_new.attrs.create('Sence Center Latitude',
                           node.text,
                           shape=(1, ),
                           dtype=np.float32)
        node = root[0].find("SceneCenterLongitude")
        f_new.attrs.create('Sence Center Longitude',
                           node.text,
                           shape=(1, ),
                           dtype=np.float32)
        node = root[0].find("SceneCenterSolarZenith")
        f_new.attrs.create('Sence Center Solar Zenith',
                           node.text,
                           shape=(1, ),
                           dtype=np.float32)
        node = root[0].find("SceneCenterTime")
        time = datetime.datetime(int('20' + node.text[0:2]), 1, 1) + datetime.timedelta(days=int(node.text[2:5]) - 1) + \
               datetime.timedelta(hours=int(node.text[5:7])) + datetime.timedelta(minutes=int(node.text[7:9]))
        f_new.attrs.create('Sence Center Solar Time',
                           time.strftime("%Y-%m-%dT%H-%M-%S"),
                           shape=(1, ),
                           dtype='S10')
        f_new.attrs.create('Sensor Mode', 'Unknown', shape=(1, ), dtype='S10')
        f_new.attrs.create(
            'Sensor Name',
            'COCTS, Chinese Ocean Color and Temperature Scanner',
            shape=(1, ),
            dtype='S10')
        f_new.attrs.create('Sensor Pitch Element',
                           'Unknown',
                           shape=(1, ),
                           dtype='S10')
        f_new.attrs.create('Sensor Yaw Element',
                           'Unknown',
                           shape=(1, ),
                           dtype='S10')
        f_new.attrs.create('Software Version',
                           '01.00',
                           shape=(1, ),
                           dtype='S10')
        f_new.attrs.create('Southernmost Latitude',
                           np.min(lat),
                           shape=(1, ),
                           dtype=np.float32)
        f_new.attrs.create('Start Center Longitude',
                           center_lon[0],
                           shape=(1, ),
                           dtype=np.float32)
        f_new.attrs.create('Start Center Latitude',
                           center_lat[0],
                           shape=(1, ),
                           dtype=np.float32)
        f_new.attrs.create('TLE', '', shape=(1, ), dtype='S10')
        f_new.attrs.create(
            'The Parameters of Sensor Characteristics',
            '412nm,443nm,490nm,520nm,565nm,670nm,750nm,865nm,10.3-11.4um,'
            '11.5-12.5um',
            shape=(1, ),
            dtype='S10')
        f_new.attrs.create('Title',
                           'HY-1A OCT Level-1B',
                           shape=(1, ),
                           dtype='S10')
        f_new.attrs.create('Upper Left Latitude',
                           lat[0, 0],
                           shape=(1, ),
                           dtype=np.float32)
        f_new.attrs.create('Upper Left Longitude',
                           lon[0, 0],
                           shape=(1, ),
                           dtype=np.float32)
        f_new.attrs.create('Upper Right Latitude',
                           lat[0, -1],
                           shape=(1, ),
                           dtype=np.float32)
        f_new.attrs.create('Upper Right Longitude',
                           lon[0, -1],
                           shape=(1, ),
                           dtype=np.float32)
        f_new.attrs.create('Westernmost Longitude',
                           np.min(lon),
                           shape=(1, ),
                           dtype=np.float32)
        f.close()
        f_new.close()
        return outfile
#------------------------------------------------------------------------------------------------------
# Apply the sun zenith correction
data1 = (data1) / (np.cos(np.deg2rad(sun_zenith)))
data2 = (data2) / (np.cos(np.deg2rad(sun_zenith)))
data3 = (data3) / (np.cos(np.deg2rad(sun_zenith)))
#------------------------------------------------------------------------------------------------------
#------------------------------------------------------------------------------------------------------
# Applying the Rayleigh correction

from pyorbital.astronomy import get_alt_az
from pyorbital.orbital import get_observer_look

sunalt, suna = get_alt_az(utc_time, lons, lats)
suna = np.rad2deg(suna)
#sata, satel = get_observer_look(sat_lon, sat_lat, sat_alt, vis.attrs['start_time'], lons, lats, 0)
sata, satel = get_observer_look(longitude, 0.0, sat_h, utc_time, lons, lats, 0)
satz = 90 - satel

# Reyleigh Correction
atmosphere = 'us-standard'
aerosol_type = 'rayleigh_only'
rayleigh_key = ('GOES-16', 'abi', atmosphere, aerosol_type)
corrector = Rayleigh('GOES-16',
                     'abi',
                     atmosphere=atmosphere,
                     aerosol_type=aerosol_type)

sata = sata % 360.
suna = suna % 360.
ssadiff = np.absolute(suna - sata)
ssadiff = np.minimum(ssadiff, 360 - ssadiff)