Source code for isofit.configs.sections.inversion_config

#! /usr/bin/env python3
#
#  Copyright 2018 California Institute of Technology
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.
#
# ISOFIT: Imaging Spectrometer Optimal FITting
# Author: Philip G. Brodrick, philip.brodrick@jpl.nasa.gov

from collections import OrderedDict
from typing import Dict, List, Type

from isofit.configs.base_config import BaseConfigSection


[docs] class InversionConfig(BaseConfigSection): """ Inversion configuration. """ def __init__(self, sub_configdic: dict = None):
[docs] self._windows_type = list()
[docs] self.windows = None
"""List[List[float]]: inversion retrieval windows to operate over."""
[docs] self._cressie_map_confidence_type = bool
[docs] self.cressie_map_confidence = False
"""bool: N. Cressie [ASA 2018] suggests an alternate definition of S_hat for more statistically-consistent posterior confidence estimation, this flag runs in this mode"""
[docs] self._mcmc_type = McmcConfig
[docs] self.mcmc = McmcConfig({})
"""MCMC parameters, only used if mode = mcmc."""
[docs] self._integration_grid_type = OrderedDict
[docs] self.integration_grid = OrderedDict({})
"""Grid of inversion points to execute if mode='grid'. Either fixed, or starting points, depending on self.fixed_inversion_grid"""
[docs] self._priors_in_initial_guess_type = bool
[docs] self.priors_in_initial_guess = True
"""Boolean to inidicate the use of surface priors outside of the inversion windows during the intial guess."""
[docs] self._inversion_grid_as_preseed_type = bool
[docs] self.inversion_grid_as_preseed = False
"""Parameter indicating whether to treat the inversion grid as: (True) - a series of seeds for the optimization (variable by the optimization algorithm). (False) - a set of fixed points (not variable by the optimization algorithm) """
[docs] self._least_squares_params_type = LeastSquaresConfig
[docs] self.least_squares_params = LeastSquaresConfig({})
""" Least squares parameters for core inversion solve. See https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.least_squares.html for details. """ self.set_config_options(sub_configdic)
[docs] def _check_config_validity(self) -> List[str]: errors = list() # TODO: add some checking to windows if self.windows is None and self.mode != "simulation": errors.append("windows is a required parameters inside of inversion") else: for subset in self.windows: if isinstance(subset, List) is False: errors.append( "windows parameter must be a list of lists of wavelength ranges" ) elif subset[0] > subset[1]: errors.append( "In inversion window subset {}, wavelength ranges must be in" " order".format(subset) ) return errors
[docs] class McmcConfig(BaseConfigSection): """ MCMC inversion configuration. """ def __init__(self, sub_configdic: dict = None):
[docs] self._iterations_type = int
[docs] self.iterations = 10000
"""int: Number of MCMC iterations to run."""
[docs] self._burnin_type = int
[docs] self.burnin = 200
[docs] self._regularizer_type = float
[docs] self.regularizer = 1e-3
[docs] self._proposal_scaling_type = float
[docs] self.proposal_scaling = 0.01
[docs] self._verbose_type = bool
[docs] self.verbose = True
[docs] self._restart_every_type = int
[docs] self.restart_every = 2000
self.set_config_options(sub_configdic)
[docs] def _check_config_validity(self) -> List[str]: errors = list() # TODO: add flags for rile overright, and make sure files don't exist if not checked? return errors
[docs] class LeastSquaresConfig(BaseConfigSection): """ Least squares config parameters. """ def __init__(self, sub_configdic: dict = None):
[docs] self._method_type = str
[docs] self.method = "trf"
"""str: Optimzation method to use. Default 'trf'."""
[docs] self._max_nfev_type = int
[docs] self.max_nfev = 20
"""int: Maximum number of function evaluations before the termination. If None (default), the value is chosen automatically. Default 20."""
[docs] self._xtol_type = float
[docs] self.xtol = None
"""float: Tolerance for termination by the change of the independent variables. Default is None, which disables termination from this criteria."""
[docs] self._ftol_type = float
[docs] self.ftol = 0.01
"""float: Tolerance for termination by the change of the cost function. Default is 0.01"""
[docs] self._gtol_type = float
[docs] self.gtol = None
"""float: Tolerance for termination by the norm of the gradient. Default is None, which disables termination from this criteria."""
[docs] self._tr_solver_type = str
[docs] self.tr_solver = "lsmr"
"""str: Method for solving trust-region subproblems, relevant only for ‘trf’ and ‘dogbox’ methods. Options are None, 'exact', or 'lsmr'""" self.set_config_options(sub_configdic)
[docs] def _check_config_validity(self) -> List[str]: errors = list() # TODO: add flags for rile overright, and make sure files don't exist if not checked? if self.tr_solver is not None: if self.tr_solver not in [None, "exact", "lsmr"]: errors.append( "Least squares tr_solver must be in [None, 'exact', 'lsmr']" ) return errors