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()
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)