def test_plot(): pathlist = glob.glob( os.path.join('tests', 'data', 'datastore', 'BTCN', '*')) sm = SiteMeasurements.from_pathlist( pathlist)[dt.datetime(2018, 5, 28):dt.datetime(2018, 5, 29)] srfs = [Sentinel2Blue(), Sentinel2Green()] # make sure all below modes don't fail: for with_errors in [False, True]: for types in ['toa', 'sr', ['toa', 'sr']]: plot(types, sm, srfs, with_errors=with_errors, show=False)
# some spectral plots if (0): import numpy as np import matplotlib.pyplot as plt from calval.satellites.srf import Sentinel2Green, Sentinel2Red, Landsat8Blue, NewsatBlue, NewsatRed from pyspectral.solar import (SolarIrradianceSpectrum, TOTAL_IRRADIANCE_SPECTRUM_2000ASTM) srr = SolarIrradianceSpectrum(TOTAL_IRRADIANCE_SPECTRUM_2000ASTM, dlambda=0.0005) srr.interpolate(ival_wavelength=(0.200, 2.000)) print(srr.units) print(srr.ipol_wavelength, srr.ipol_irradiance) plt.figure() plt.plot(srr.ipol_wavelength, srr.ipol_irradiance, 'k-.') srf = Sentinel2Green() x = srr.ipol_wavelength * 1000 vals = srf(x) * srr.ipol_irradiance avg = np.dot(srf(x), srr.ipol_irradiance) / np.sum(srf(x)) plt.plot(srr.ipol_wavelength, vals, 'g-') plt.plot([srf.start / 1000, srf.end / 1000], [avg, avg], 'g--') srf = Sentinel2Red() x = srr.ipol_wavelength * 1000 vals = srf(x) * srr.ipol_irradiance avg = np.dot(srf(x), srr.ipol_irradiance) / np.sum(srf(x)) plt.plot(srr.ipol_wavelength, vals, 'r-') plt.plot([srf.start / 1000, srf.end / 1000], [avg, avg], 'r--') srf = Landsat8Blue() x = srr.ipol_wavelength * 1000
def __init__(self): super().__init__([ Sentinel2Blue(), Sentinel2Green(), Sentinel2Red() ])
def test_plot(): # checks plot_srf doesn't fail srfs = [Sentinel2Red(), Sentinel2Green(), Sentinel2Blue()] plot_srfs(srfs, show=False, normalize_max=True)
def test_sentinel(): # comparing central wavelength to https://en.wikipedia.org/wiki/Sentinel-2 assert Sentinel2Blue().center == pytest.approx(490, abs=10) assert Sentinel2Green().center == pytest.approx(560, abs=.10) assert Sentinel2Red().center == pytest.approx(665, abs=10) assert Sentinel2Nir().center == pytest.approx(833, abs=10)
def test_as_dataframe(): srf = Sentinel2Green() df = srf.as_dataframe() assert df['response'][srf.start] == srf(srf.start)
class SentinelSceneData(SceneData): band_ex_irradiance = { _band_aliases['blue']: srf_exatmospheric_irradiance(Sentinel2Blue()), _band_aliases['green']: srf_exatmospheric_irradiance(Sentinel2Green()), _band_aliases['red']: srf_exatmospheric_irradiance(Sentinel2Red()), _band_aliases['nir']: srf_exatmospheric_irradiance(Sentinel2Nir()) } def __init__(self, sceneinfo, path=None): super().__init__(sceneinfo, path) self.granule = self.sceneinfo._get_granule() self._read_product_metadata() self._read_l1_metadata() def _granule_mtd_path(self): return os.path.join(self.path, 'GRANULE', self.granule, 'MTD_TL.xml') def _product_mtd_path(self): return os.path.join(self.path, 'MTD_{}.xml'.format(self.sceneinfo._data.product)) def _read_product_metadata(self): self.product_meta = metadata = parse_xml_metadata( self._product_mtd_path()) data = metadata['General_Info']['Product_Image_Characteristics'][ 'Reflectance_Conversion'] self.esuns = [ data['Solar_Irradiance_List']['SOLAR_IRRADIANCE_{}'.format( _band_id(_band_aliases[band]))] for band in band_names ] self.sun_distance = np.sqrt( 1.0 / data['U']) # assuming U is `d(t)` of the TG data = metadata['Geometric_Info']['Product_Footprint'][ 'Product_Footprint'] coords = data['Global_Footprint']['EXT_POS_LIST'] self.corners = [(coords[i + 1], coords[i]) for i in range(0, 8, 2)] self.center = tuple(np.average(self.corners, axis=0)) self.cloud_coverage = metadata['Quality_Indicators_Info'][ 'Cloud_Coverage_Assessment'] def _read_l1_metadata(self): self.metadata = metadata = parse_tile_metadata( self._granule_mtd_path()) self.timestamp = metadata['General_Info']['SENSING_TIME'] def _view_angle(bandid): mean_view_list = metadata['Geometric_Info']['Tile_Angles'][ 'Mean_Viewing_Incidence_Angle_List'] return mean_view_list['Mean_Viewing_Incidence_Angle_{}'.format( bandid)] assert _view_angle(_band_id( _band_aliases['green']))['AZIMUTH_ANGLE_unit'] == 'deg' # NOTE: Seem to be large differences between viewing angles of the channels # TODO: make per-channel calcs! angles = [ _view_angle(_band_id(_band_aliases[band]))['AZIMUTH_ANGLE'] for band in band_names ] view_average_azimuth = np.average(angles) angles = [ _view_angle(_band_id(_band_aliases[band]))['ZENITH_ANGLE'] for band in band_names ] view_average_zenith = np.average(angles) self.sat_average_angle = IncidenceAngle(view_average_azimuth, 90 - view_average_zenith) sun_azimuth = metadata['Geometric_Info']['Tile_Angles'][ 'Mean_Sun_Angle']['AZIMUTH_ANGLE'] sun_zenith = metadata['Geometric_Info']['Tile_Angles'][ 'Mean_Sun_Angle']['ZENITH_ANGLE'] self.sun_average_angle = IncidenceAngle(sun_azimuth, 90 - sun_zenith) def get_metadata(self): meta = { 'center': self.center, 'esuns': self.esuns, 'sun_distance': self.sun_distance, # based on `U` from metadata 'sat_average_angle': self.sat_average_angle.to_dict(), 'sun_average_angle': self.sun_average_angle.to_dict(), 'cloud_cover': self.cloud_coverage } return meta def get_scale(self, band, product): """ TODO: compute from metadata """ return _scale_values[product]