def get_angles(self): self.get_times() tle1, tle2 = self.get_tle_lines() orb = Orbital(self.spacecrafts_orbital[self.spacecraft_id], line1=tle1, line2=tle2) sat_azi, sat_elev = orb.get_observer_look(self.times[:, np.newaxis], self.lons, self.lats, 0) sat_zenith = 90 - sat_elev sun_zenith = astronomy.sun_zenith_angle(self.times[:, np.newaxis], self.lons, self.lats) alt, sun_azi = astronomy.get_alt_az(self.times[:, np.newaxis], self.lons, self.lats) del alt sun_azi = np.rad2deg(sun_azi) sun_azi = np.where(sun_azi < 0, sun_azi + 180, sun_azi - 180) rel_azi = abs(sat_azi - sun_azi) rel_azi = np.where(rel_azi > 180.0, 360.0 - rel_azi, rel_azi) return sat_azi, sat_zenith, sun_azi, sun_zenith, rel_azi
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 parse_jaxa_hotspot_txt(self, file_path): """ Parse the JAXA Himawari-8/9 AHI hotspot text file and insert attrs into the Pandas DataFrame Args: file_path (str): File path to the JAXA Himawari-8/9 hotspot .csv Returns: hs_df (obj): DataFrame obj that contains attr of Himawari-8/9 hospot """ hs_ahi_df = pd.DataFrame() cols_to_use_list = [0, 2, *(i for i in range(7, 24))] date_col_list = [0] names_list = ['date', 'satellite', 'lon', 'lat', 'viewzenang', 'viewazang', 'pixwid', 'pixlen', 't07', 't14', 't07_t14', 'meant07', 'meant14', 'meandt', 'sdt07', 'sdt14', 'sddt', 'ref3', 'ref4'] for file in glob.glob(file_path): try: log.debug(f'Reading {file}') temp_hs_ahi_df = pd.read_csv(file, sep=",", skiprows=[0], \ header=None, usecols=cols_to_use_list, \ names=names_list, \ parse_dates=date_col_list) temp_hs_ahi_df['satellite'] = 'Himawari-8/9' except Exception as e: log.error(f'Error reading {file}') log.error(e) continue if len(temp_hs_ahi_df) > 0: try: temp_hs_ahi_df['solarazang'] = temp_hs_ahi_df.apply( \ lambda x: np.degrees(astronomy.get_alt_az(x['date'], x['lon'], x['lat'])[1]), axis=1) temp_hs_ahi_df['solarzenang'] = temp_hs_ahi_df.apply( \ lambda x: astronomy.sun_zenith_angle(x['date'], x['lon'], x['lat']), axis=1) temp_hs_ahi_df['relazang'] = temp_hs_ahi_df['solarazang'] - temp_hs_ahi_df['viewazang'] temp_hs_ahi_df['sunglint_angle'] = temp_hs_ahi_df.apply(compute_sun_glint_angle, axis=1) except Exception as e: temp_hs_ahi_df['sunglint_angle'] = np.nan try: temp_hs_ahi_df.loc[(temp_hs_ahi_df['date'].dt.hour >= 0) \ & (temp_hs_ahi_df['date'].dt.hour <= 11), 'daynight'] = 'day' temp_hs_ahi_df.loc[temp_hs_ahi_df['date'].dt.hour > 11, \ 'daynight'] = 'night' temp_hs_ahi_df['date'] = temp_hs_ahi_df['date'].dt.strftime( \ "%d/%m/%Y %H:%M:%S") except Exception as e: date_from_file = datetime.strptime(filename[4:17], "%Y%m%d_%H%M") temp_hs_ahi_df['date'] = date_from_file.strftime("%d/%m/%Y %H:%M:%S") hs_ahi_df = pd.concat([hs_ahi_df, temp_hs_ahi_df]) if len(hs_ahi_df) > 0: hs_ahi_df = hs_ahi_df.reset_index(drop=True) self.hs_df = pd.concat([hs_ahi_df, self.hs_df])
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 get_angles(self): """Get azimuth and zenith angles. Azimuth angle definition is the same as in pyorbital, but with different units (degrees not radians for sun azimuth angles) and different ranges. Returns: sat_azi: satellite azimuth angle degree clockwise from north in range ]-180, 180], sat_zentih: satellite zenith angles in degrees in range [0,90], sun_azi: sun azimuth angle degree clockwise from north in range ]-180, 180], sun_zentih: sun zenith angles in degrees in range [0,90], rel_azi: absolute azimuth angle difference in degrees between sun and sensor in range [0, 180] """ self.get_times() self.get_lonlat() tle1, tle2 = self.get_tle_lines() times = self.times orb = Orbital(self.spacecrafts_orbital[self.spacecraft_id], line1=tle1, line2=tle2) sat_azi, sat_elev = orb.get_observer_look(times[:, np.newaxis], self.lons, self.lats, 0) sat_zenith = 90 - sat_elev sun_zenith = astronomy.sun_zenith_angle(times[:, np.newaxis], self.lons, self.lats) alt, sun_azi = astronomy.get_alt_az(times[:, np.newaxis], self.lons, self.lats) del alt sun_azi = np.rad2deg(sun_azi) rel_azi = get_absolute_azimuth_angle_diff(sun_azi, sat_azi) # Scale angles range to half open interval ]-180, 180] sat_azi = centered_modulus(sat_azi, 360.0) sun_azi = centered_modulus(sun_azi, 360.0) # Mask corrupt scanlines for arr in (sat_azi, sat_zenith, sun_azi, sun_zenith, rel_azi): arr[self.mask] = np.nan return sat_azi, sat_zenith, sun_azi, sun_zenith, rel_azi
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 getSentinel2Geometry(startDateUTC, lengthDays, lat, lon, alt=0.0, mission="Sentinel-2a", tleFile="../TLE/norad_resource_tle.txt"): """Calculate approximate geometry for Sentinel overpasses. Approximate because it assumes maximum satellite elevation is the time at which target is imaged. :param startDateUTC: a datetime object specifying when to start prediction. :type startDateUTC: object :param lengthDays: number of days over which to perform calculations. :type lengthDays: int :param lat: latitude of target. :type lat: float :param lon: longitude of target. :type lon: float :param alt: altitude of target (in km). :type alt: float :param mission: mission name as in TLE file. :type mission: str :param tleFile: TLE file. :type tleFile: str :return: a python list containing instances of the sensorGeometry class arranged in date order. :rtype: list """ orb = Orbital(mission, tleFile) passes = orb.get_next_passes(startDateUTC, 24 * lengthDays, lon, lat, alt) geomList = [] for p in passes: look = orb.get_observer_look(p[2], lon, lat, alt) vza = 90 - look[1] vaa = look[0] sza = ast.sun_zenith_angle(p[2], lon, lat) saa = np.rad2deg(ast.get_alt_az(p[2], lon, lat)[1]) if sza < 90 and vza < 10.3: thisGeom = sensorGeometry() thisGeom.date_utc = p[2] thisGeom.vza = vza thisGeom.vaa = vaa thisGeom.sza = sza thisGeom.saa = saa geomList.append(thisGeom) return geomList
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 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
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 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
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 get_solar_angles(scene, lons, lats): """Compute solar angles. Compute angles for each scanline using their acquisition time to account for the earth's rotation over the course of one scan. Returns: Solar azimuth angle, Solar zenith angle in degrees """ suna = np.full(lons.shape, np.nan) sunz = np.full(lons.shape, np.nan) mean_acq_time = get_mean_acq_time(scene) for line, acq_time in enumerate(mean_acq_time.values): if np.isnat(acq_time): continue _, suna_line = get_alt_az(acq_time, lons[line, :], lats[line, :]) suna_line = np.rad2deg(suna_line) suna[line, :] = suna_line sunz[line, :] = sun_zenith_angle(acq_time, lons[line, :], lats[line, :]) return suna, sunz
def _get_sun_azimuth_ndarray(lons: np.ndarray, lats: np.ndarray, start_time: datetime) -> np.ndarray: with ignore_invalid_float_warnings(): suna = get_alt_az(start_time, lons, lats)[1] suna = np.rad2deg(suna) return suna
lats[:, :][::1, ::1]) print(sun_zenith.shape) #------------------------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------------------------ # 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.
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 _get_sun_angles(self, vis, lons, lats): from pyorbital.astronomy import get_alt_az, sun_zenith_angle 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) return suna, sunz
def get_satellite_geometry(startDateUTC, lengthDays, lon, lat, alt=0.0, mission="Sentinel-2a", tleFile="/data/tle/norad_resource_tle.txt"): """Calculate approximate geometry for Sentinel overpasses. Approximate because it assumes maximum satellite elevation is the time at which target is imaged. :param startDateUTC: a datetime object specifying when to start prediction. :type startDateUTC: object :param lengthDays: number of days over which to perform calculations. :type lengthDays: int :param lat: latitude of target. :type lat: float :param lon: longitude of target. :type lon: float :param alt: altitude of target (in km). :type alt: float :param mission: mission name as in TLE file. :type mission: str :param tleFile: TLE file. :type tleFile: str :return: a python list containing instances of the sensorGeometry class arranged in date order. :rtype: list """ orb = Orbital(mission, tleFile) passes = orb.get_next_passes(startDateUTC, 24 * lengthDays, lon, lat, alt) geom_inst = SensorGeometry() geom_inst.date_utc = [] geom_inst.vza = [] geom_inst.vaa = [] geom_inst.sza = [] geom_inst.saa = [] for p in passes: look = orb.get_observer_look(p[2], lon, lat, alt) vza = 90 - look[1] vaa = look[0] sza = ast.sun_zenith_angle(p[2], lon, lat) saa = np.rad2deg(ast.get_alt_az(p[2], lon, lat)[1]) if mission == 'Sentinel-1b': if 75 < vaa < 105 and 20. < vza < 45.: # vaa usually [0, 180], testing observation times geom_inst.date_utc.append(p[2]) geom_inst.vza.append(vza) geom_inst.vaa.append(vaa) geom_inst.sza.append(sza) geom_inst.saa.append(saa) elif mission == 'Sentinel-1a': if 75 < vaa < 105 and 20. < vza < 45.: # vaa usually [0, 180], testing observation times geom_inst.date_utc.append(p[2]) geom_inst.vza.append(vza) geom_inst.vaa.append(vaa) geom_inst.sza.append(sza) geom_inst.saa.append(saa) elif mission == 'Sentinel-2a': if sza < 90 and vza < 10.3: geom_inst.date_utc.append(p[2]) geom_inst.vza.append(vza) geom_inst.vaa.append(vaa) geom_inst.sza.append(sza) geom_inst.saa.append(saa) return geom_inst