Commit dc5b1c37 authored by Daniel Scheffler's avatar Daniel Scheffler
Browse files

Added SRF object (needed for atmospheric correction of Landsat).

- _get_srf(): now returns an instance of SRF object
- run_atmospheric_correction(): activated SRF getter

- SRF_reader(): added verbose mode
- added class SRF

- updated __version__

Former-commit-id: 32d65014
parent d08a8a57
......@@ -15,7 +15,7 @@ from . import config
from .processing.process_controller import process_controller
__version__ = '20170126.02'
__version__ = '20170127.01'
__author__ = 'Daniel Scheffler'
__all__ = ['algorithms',
......@@ -39,7 +39,8 @@ from ..config import GMS_config as CFG
from . import GEOPROCESSING as GEOP
from .L1B_P import L1B_object
from .METADATA import get_LayerBandsAssignment
from ..misc.definition_dicts import get_outFillZeroSaturated
from ..misc.definition_dicts import get_outFillZeroSaturated, proc_chain
from import SRF
from S2SCAPEM.s2_ac import AC_GMS
from S2MSI import RSImage
......@@ -651,9 +652,15 @@ class AtmCorr(object):
def _get_srf(self):
"""Returns an SRF object S2SRF.
"""Returns an instance of SRF in the same structure like S2MSI.Tools.S2SRF.S2SRF
return None # TODO
# FIXME calculation of center wavelengths within SRF() used not the GMS algorithm
# SRF instance must be created for all bands and the previous proc level
GMS_identifier_fullScene = self.inObjs[0].GMS_identifier
GMS_identifier_fullScene['Subsystem'] = ''
GMS_identifier_fullScene['proc_level'] = proc_chain[proc_chain.index(self.inObjs[0].proc_level) - 1]
return SRF(GMS_identifier_fullScene, wvl_unit='nanometers', format_bandnames=True)
def run_atmospheric_correction(self, dump_ac_input=False):
......@@ -675,7 +682,7 @@ class AtmCorr(object):
band_spatial_sampling = self.band_spatial_sampling,
tile_name = self.tile_name,
dem = self._get_dem(),
#srf = self._get_srf()
srf = self._get_srf()
) # NOTE: all keys of this dict are later converted to attributes of RSImage
options = self.inObjs[0].ac_options
script = False
......@@ -26,6 +26,7 @@ import numpy as np
import scipy.interpolate
import spectral
from import envi as envi
from pandas import DataFrame, Series
from ..config import GMS_config as CFG
from ..algorithms import METADATA as META
......@@ -175,10 +176,11 @@ def get_list_GMSfiles(dataset_list, target):
return GMS_list
def SRF_reader(GMS_identifier):
def SRF_reader(GMS_identifier, v=False):
"""Reads SRF for any sensor and returns a dictionary containing band names as keys and SRF numpy arrays as values.
:param GMS_identifier:
:param v: verbose mode
satellite, sensor, logger = (GMS_identifier['Satellite'], GMS_identifier['Sensor'], GMS_identifier['logger'])
......@@ -190,6 +192,7 @@ def SRF_reader(GMS_identifier):
SRF_path = PG.get_path_srf_file(GMS_identifier, bandname=bandname)
SRF_dict[bandname] = np.loadtxt(SRF_path,skiprows=1)
if v:'Reading SRF for %s %s, %s...' %(satellite,sensor,bandname))
except FileNotFoundError:
logger.warning('No spectral response function found for %s %s %s at %s! >None< is returned.'
......@@ -202,6 +205,90 @@ def SRF_reader(GMS_identifier):
return SRF_dict
class SRF(object):
def __init__(self, GMS_identifier=None, wvl_unit='nanometers', format_bandnames= False, v=False):
# type: (dict, str, bool, bool) -> None
"""SRF instance provides SRF functions, wavelength positions, etc..
:param GMS_identifier: dictionary as provided by GMS_object
:param wvl_unit: the wavelengths unit to be used within SRF instance ('nanometers' or 'micrometers)
:param format_bandnames: whether to format default strings from LayerBandsAssignment as 'B01', 'B02' etc..
:param v: verbose mode
if not wvl_unit in ['micrometers', 'nanometers']:
raise ValueError('Unknown wavelength unit %s.' %wvl_unit)
self.srfs_wvl = []
self.srfs = []
self.bands = []
self.wvl = []
self.wvl_unit = wvl_unit
self.format_bandnames = format_bandnames
self.v = v
if GMS_identifier:
def _set_attrs(self, wvl, srfs):
for bN in srfs:
srf = np.array(srfs[bN], dtype=np.float)
srfs[bN] = srf / np.trapz(x=wvl,y=srf)
self.srfs_wvl = wvl
self.srfs = srfs
self.bands = sorted(list(self.srfs.keys()))
# FIXME this is not the GMS algorithm to calculalate center wavelengths
self.wvl = [np.trapz(x=self.srfs_wvl, y=self.srfs_wvl * self.srfs[band]) for band in self.bands] # calculate center wavelengths
self.wvl = self.wvl if self.wvl_unit=='micrometers' else [int(i) for i in self.wvl]
self.conv = {}
self.conv.update({key: value for key, value in zip(self.bands, self.wvl)})
self.conv.update({value: key for key, value in zip(self.bands, self.wvl)})
def from_GMS_identifier(self, GMS_identifier):
srf_dict = SRF_reader(GMS_identifier, v=self.v)
return self.from_dict(srf_dict)
def from_dict(self, srf_dict):
"""Create an instance of SRF from a dictionary.
:param dict: {'key_LayerBandsAssignment': <2D array: cols=[wvl,resp],rows=samples>}
is_nm = [300 < np.max(srf_dict[band][:, 0]) < 15000 for band in srf_dict]
assert len(set(is_nm))==1, "'srf_dict' must contain only one wavelength unit."
scale_factor = 1 if is_nm[0] else 1000
all_wvls = np.concatenate(list((arr[:,0] for key, arr in srf_dict.items())))*scale_factor
wvl = np.arange(all_wvls.min(), all_wvls.max() + 1, 1).astype(
df = DataFrame(index = wvl)
for band in srf_dict:
bandname = band if not self.format_bandnames else ('B%s' % band if len(band) == 2 else 'B0%s' % band)
df = df.join(Series(srf_dict[band][:,1],
.astype(, name=bandname))
df = df.fillna(0)
wvl = df.index.astype(np.float) if self.wvl_unit == 'nanometers' else df.index/1000.
self._set_attrs(wvl=wvl, srfs=df.to_dict(orient='series'))
return self
def instrument(self,bands):
return {
'rspf':np.vstack([self[band] for band in bands]),
def __call__(self,band):
return self.srfs[band]
def __getitem__(self,band):
return self.srfs[band]
def pickle_SRF_DB(L1A_Instances):
list_GMS_identifiers = [i.GMS_identifier for i in L1A_Instances]
out_dict = collections.OrderedDict()
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment