Beispiel #1
0
    def __init__(self, engine_config: RadiativeTransferEngineConfig,
                 full_config: Config):

        self.implementation_config: ImplementationConfig = full_config.implementation
        self.wl, self.fwhm = common.load_wavelen(
            full_config.forward_model.instrument.wavelength_file)
        if engine_config.wavelength_range is not None:
            valid_wl = np.logical_and(
                self.wl >= engine_config.wavelength_range[0],
                self.wl <= engine_config.wavelength_range[1])
            self.wl = self.wl[valid_wl]
            self.fwhm = self.fwhm[valid_wl]

        self.n_chan = len(self.wl)

        self.auto_rebuild = full_config.implementation.rte_auto_rebuild
        self.configure_and_exit = full_config.implementation.rte_configure_and_exit
        self.implementation_mode = full_config.implementation.mode

        # We use a sorted dictionary here so that filenames for lookup
        # table (LUT) grid points are always constructed the same way, with
        # consistent dimesion ordering). Every state vector element has
        # a lookup table dimension, but some lookup table dimensions
        # (like geometry parameters) may not be in the state vector.
        # TODO: enforce a requirement that makes all SV elements be inside the LUT
        full_lut_grid = full_config.forward_model.radiative_transfer.lut_grid
        # selectively get lut components that are in this particular RTE
        self.lut_grid_config = OrderedDict()
        if engine_config.lut_names is not None:
            lut_names = engine_config.lut_names
        else:
            lut_names = full_config.forward_model.radiative_transfer.lut_grid.keys(
            )

        for key, value in full_lut_grid.items():
            if key in lut_names:
                self.lut_grid_config[key] = value

        # selectively get statevector components that are in this particular RTE
        full_sv_names = full_config.forward_model.radiative_transfer.statevector.get_element_names(
        )
        self.statevector_names = full_sv_names

        self.lut_dir = engine_config.lut_path
        self.n_point = len(self.lut_grid_config)
        self.n_state = len(self.statevector_names)

        self.luts = {}

        # Retrieved variables.  We establish scaling, bounds, and
        # initial guesses for each state vector element.  The state
        # vector elements are all free parameters in the RT lookup table,
        # and they all have associated dimensions in the LUT grid.
        self.bounds, self.scale, self.init = [], [], []
        self.prior_mean, self.prior_sigma = [], []
        for key in self.statevector_names:
            element: StateVectorElementConfig = full_config.forward_model.radiative_transfer.statevector.get_single_element_by_name(
                key)
            self.bounds.append(element.bounds)
            self.scale.append(element.scale)
            self.init.append(element.init)
            self.prior_sigma.append(element.prior_sigma)
            self.prior_mean.append(element.prior_mean)
        self.bounds = np.array(self.bounds)
        self.scale = np.array(self.scale)
        self.init = np.array(self.init)
        self.prior_mean = np.array(self.prior_mean)
        self.prior_sigma = np.array(self.prior_sigma)

        self.lut_dims = []
        self.lut_grids = []
        self.lut_names = []
        self.lut_interp_types = []
        for key, grid_values in self.lut_grid_config.items():

            # do some quick checks on the values
            # For forward (simulation) mode, 1-dimensional LUT grids are OK!
            if len(grid_values
                   ) == 1 and not self.implementation_mode == "simulation":
                err = 'Only 1 value in LUT grid {}. '.format(key) +\
                    '1-d LUT grids cannot be interpreted.'
                raise ValueError(err)
            if grid_values != sorted(grid_values):
                logging.error('Lookup table grid needs ascending order')
                raise ValueError('Lookup table grid needs ascending order')

            # Store the values
            self.lut_grids.append(grid_values)
            self.lut_dims.append(len(grid_values))
            self.lut_names.append(key)

            # Store in an indication of the type of value each key is
            # (normal - n, degree - d, radian - r)
            if key in self.angular_lut_keys_radians:
                self.lut_interp_types.append('r')
            elif key in self.angular_lut_keys_degrees:
                self.lut_interp_types.append('d')
            else:
                self.lut_interp_types.append('n')

        # Cast as array for faster reference later
        self.lut_interp_types = np.array(self.lut_interp_types)

        # "points" contains all combinations of grid points
        # We will have one filename prefix per point
        self.points = common.combos(self.lut_grids)
        self.files = self.get_lut_filenames()
Beispiel #2
0
    def __init__(self, config, statevector_names):

        TabularRT.__init__(self, config)
        self.sixs_dir = self.find_basedir(config)
        self.wl, self.fwhm = load_wavelen(config['wavelength_file'])
        self.sixs_grid_init = s.arange(self.wl[0], self.wl[-1]+2.5, 2.5)
        self.sixs_ngrid_init = len(self.sixs_grid_init)
        self.sixs_dir = self.find_basedir(config)
        self.params = {'aermodel': 1,
                       'AOT550': 0.01,
                       'H2OSTR': 0,
                       'O3': 0.40,
                       'day':   config['day'],
                       'month': config['month'],
                       'elev':  config['elev'],
                       'alt':   config['alt'],
                       'atm_file': None,
                       'abscf_data_directory': None,
                       'wlinf': self.sixs_grid_init[0]/1000.0,  # convert to nm
                       'wlsup': self.sixs_grid_init[-1]/1000.0}

        if 'obs_file' in config:
            # A special case where we load the observation geometry
            # from a custom-crafted text file
            g = Geometry(obs=config['obs_file'])
            self.params['solzen'] = g.solar_zenith
            self.params['solaz'] = g.solar_azimuth
            self.params['viewzen'] = g.observer_zenith
            self.params['viewaz'] = g.observer_azimuth
        else:
            # We have to get geometry from somewhere, so we presume it is
            # in the configuration file.
            for f in ['solzen', 'viewzen', 'solaz', 'viewaz']:
                self.params[f] = config[f]

        self.esd = s.loadtxt(config['earth_sun_distance_file'])
        dt = datetime(2000, self.params['month'], self.params['day'])
        self.day_of_year = dt.timetuple().tm_yday
        self.irr_factor = self.esd[self.day_of_year-1, 1]

        irr = s.loadtxt(config['irradiance_file'], comments='#')
        iwl, irr = irr.T
        irr = irr / 10.0  # convert, uW/nm/cm2
        irr = irr / self.irr_factor**2  # consider solar distance
        self.solar_irr = resample_spectrum(irr, iwl,  self.wl, self.fwhm)

        self.angular_lut_keys_degrees = ['OBSZEN','TRUEAZ','viewzen','viewaz',
            'solzen','solaz']

        self.lut_quantities = ['rhoatm', 'transm', 'sphalb', 'transup']
        self.build_lut()

        # This array is used to handle the potential indexing mismatch between
        # the 'global statevector' (which may couple multiple radiative 
        # transform models) and this statevector. It should never be modified
        full_to_local_statevector_position_mapping = []
        for sn in self.statevec:
            ix = statevector_names.index(sn)
            full_to_local_statevector_position_mapping.append(ix)
        self._full_to_local_statevector_position_mapping = \
            s.array(full_to_local_statevector_position_mapping)