Exemplo n.º 1
0
    def __init__(self, config: configs.Config, loglevel: str, logfile: str, worker_id: int = None, total_workers: int = None):
        """
        Worker class to help run a subset of spectra.

        Args:
            config: isofit configuration
            loglevel: output logging level
            logfile: output logging file
            worker_id: worker ID for logging reference
            total_workers: the total number of workers running, for logging reference
        """

        logging.basicConfig(format='%(levelname)s:%(message)s', level=loglevel, filename=logfile)
        self.config = config
        self.fm = ForwardModel(self.config)

        if self.config.implementation.mode == 'mcmc_inversion':
            self.iv = MCMCInversion(self.config, self.fm)
        elif self.config.implementation.mode in ['inversion', 'simulation']:
            self.iv = Inversion(self.config, self.fm)
        else:
            # This should never be reached due to configuration checking
            raise AttributeError('Config implementation mode node valid')

        self.io = IO(self.config, self.fm)

        self.approximate_total_spectra = None
        if total_workers is not None:
            self.approximate_total_spectra = self.io.n_cols * self.io.n_rows / total_workers
        self.worker_id = worker_id
        self.completed_spectra = 0
Exemplo n.º 2
0
    def _init_nonpicklable_objects(self):
        self.fm = ForwardModel(self.config)

        if self.config.implementation.mode == 'mcmc_inversion':
            self.iv = MCMCInversion(self.config, self.fm)
        elif self.config.implementation.mode in ['inversion', 'simulation']:
            self.iv = Inversion(self.config, self.fm)
        else:
            # This should never be reached due to configuration checking
            raise AttributeError('Config implementation mode node valid')
Exemplo n.º 3
0
    def _init_nonpicklable_objects(self) -> None:
        """ Internal function to initialize objects that cannot be pickled
        """
        self.fm = ForwardModel(self.config)

        if self.config.implementation.mode == 'mcmc_inversion':
            self.iv = MCMCInversion(self.config, self.fm)
        elif self.config.implementation.mode in ['inversion', 'simulation']:
            self.iv = Inversion(self.config, self.fm)
        else:
            # This should never be reached due to configuration checking
            raise AttributeError('Config implementation mode node valid')
Exemplo n.º 4
0
    def __init__(self, config: configs.Config, loglevel: str, logfile: str):

        logging.basicConfig(format='%(levelname)s:%(message)s', level=loglevel, filename=logfile)
        self.config = config
        self.fm = ForwardModel(self.config)

        if self.config.implementation.mode == 'mcmc_inversion':
            self.iv = MCMCInversion(self.config, self.fm)
        elif self.config.implementation.mode in ['inversion', 'simulation']:
            self.iv = Inversion(self.config, self.fm)
        else:
            # This should never be reached due to configuration checking
            raise AttributeError('Config implementation mode node valid')

        self.io = IO(self.config, self.fm)
Exemplo n.º 5
0
def run_forward():
    """Simulate the remote measurement of a spectrally uniform surface."""

    # Configure the surface/atmosphere/instrument model
    testdir, fname = os.path.split(os.path.abspath(__file__))
    datadir = os.path.join(testdir, 'data')
    config = create_new_config(os.path.join(datadir, 'config_forward.json'))
    fm = ForwardModel(config)
    iv = Inversion(config, fm)
    io = IO(config, fm, iv, [0], [0])

    # Simulate a measurement and write result
    for row, col, meas, geom, configs in io:
        states = iv.invert(meas, geom)
        io.write_spectrum(row, col, states, meas, geom)

    assert True
    return states[0]
Exemplo n.º 6
0
def run_inverse():
    """Invert the remote measurement."""

    # Configure the surface/atmosphere/instrument model
    testdir, fname = os.path.split(os.path.abspath(__file__))
    datadir = os.path.join(testdir, 'data')
    config = create_new_config(os.path.join(datadir, 'config_forward.json'))
    fm = ForwardModel(config)
    iv = Inversion(config, fm)
    io = IO(config, fm, iv, [0], [0])
    geom = None

    # Get our measurement from the simulation results, and invert.
    # Calculate uncertainties at the solution state, write result
    for row, col, meas, geom, configs in io:
        states = iv.invert(meas, geom)
        io.write_spectrum(row, col, states, meas, geom)

    assert True
    return states[-1]
Exemplo n.º 7
0
def run_forward():
    """Simulate the remote measurement of a spectrally uniform surface."""

    # Configure the surface/atmosphere/instrument model
    testdir, fname = os.path.split(os.path.abspath(__file__))
    datadir = os.path.join(testdir, 'data')
    config = create_new_config(os.path.join(datadir, 'config_forward.json'))
    fm = ForwardModel(config)
    iv = Inversion(config, fm)
    io = IO(config, fm)

    # Simulate a measurement and write result
    for row in range(io.n_rows):
        for col in range(io.n_cols):
            id = io.get_components_at_index(row, col)
            if id is not None:
                states = iv.invert(id.meas, id.geom)
                io.write_spectrum(row, col, states, fm, iv)

    assert True
    return states[0]
Exemplo n.º 8
0
class Worker(object):
    def __init__(self, config: configs.Config, loglevel: str, logfile: str):

        logging.basicConfig(format='%(levelname)s:%(message)s', level=loglevel, filename=logfile)
        self.config = config
        self.fm = ForwardModel(self.config)

        if self.config.implementation.mode == 'mcmc_inversion':
            self.iv = MCMCInversion(self.config, self.fm)
        elif self.config.implementation.mode in ['inversion', 'simulation']:
            self.iv = Inversion(self.config, self.fm)
        else:
            # This should never be reached due to configuration checking
            raise AttributeError('Config implementation mode node valid')

        self.io = IO(self.config, self.fm)


    def run_set_of_spectra(self, indices: np.array):


        for index in range(0, indices.shape[0]):

            logging.debug("Read chunk of spectra")
            row, col = indices[index,0], indices[index,1]

            input_data = self.io.get_components_at_index(row, col)

            if input_data is not None:
                logging.debug("Run model")
                # The inversion returns a list of states, which are
                # intepreted either as samples from the posterior (MCMC case)
                # or as a gradient descent trajectory (standard case). For
                # a trajectory, the last spectrum is the converged solution.
                states = self.iv.invert(input_data.meas, input_data.geom)

                logging.debug("Write chunk of spectra")
                # Write the spectra to disk
                try:
                    self.io.write_spectrum(row, col, states, self.fm, self.iv)
                except ValueError as err:
                    logging.info(
                        f"""
                        Encountered the following ValueError in (row,col) ({row},{col}).
                        Results for this pixel will be all zeros.
                        """
                    )
                    logging.error(err)
                if index % 100 == 0:
                    logging.info(f'Core at start location ({row},{col}) completed {index}/{indices.shape[0]}')

        self.io.flush_buffers()
Exemplo n.º 9
0
def run_inverse():
    """Invert the remote measurement."""

    # Configure the surface/atmosphere/instrument model
    testdir, fname = os.path.split(os.path.abspath(__file__))
    datadir = os.path.join(testdir, 'data')
    config = create_new_config(os.path.join(datadir, 'config_forward.json'))
    fm = ForwardModel(config)
    iv = Inversion(config, fm)
    io = IO(config, fm)

    # Get our measurement from the simulation results, and invert.
    # Calculate uncertainties at the solution state, write result
    for row in range(io.n_rows):
        for col in range(io.n_cols):
            id = io.get_components_at_index(row, col)
            if id is not None:
                states = iv.invert(id.meas, id.geom)
                io.write_spectrum(row, col, states, fm, iv)

    assert True
    return states[-1]
Exemplo n.º 10
0
class Isofit:
    """Initialize the Isofit class.

    Args:
        config_file: isofit configuration file in JSON or YAML format
        row_column: The user can specify

                    * a single number, in which case it is interpreted as a row
                    * a comma-separated pair, in which case it is interpreted as a
                      row/column tuple (i.e. a single spectrum)
                    * a comma-separated quartet, in which case it is interpreted as
                      a row, column range in the order (line_start, line_end, sample_start,
                      sample_end) all values are inclusive.

                    If none of the above, the whole cube will be analyzed.
        level: logging level (ERROR, WARNING, INFO, DEBUG)
        logfile: file to write output logs to
    """

    def __init__(self, config_file, row_column='', level='INFO', logfile=None):

        # Explicitly set the number of threads to be 1, so we more effectively
        #run in parallel 
        os.environ["MKL_NUM_THREADS"] = "1"

        # Set logging level
        self.loglevel = level
        self.logfile = logfile
        logging.basicConfig(format='%(levelname)s:%(message)s', level=self.loglevel, filename=self.logfile)

        self.rows = None
        self.cols = None
        self.config = None
        self.fm = None
        self.iv = None
        self.io = None
        self.states = None

        # Load configuration file
        self.config = configs.create_new_config(config_file)
        self.config.get_config_errors()

        # Initialize ray for parallel execution
        rayargs = {'address': self.config.implementation.ip_head,
                   'redis_password': self.config.implementation.redis_password,
                   'ignore_reinit_error':True,
                   'local_mode': self.config.implementation.n_cores == 1}

        # only specify a temporary directory if we are not connecting to 
        # a ray cluster
        if rayargs['local_mode']:
            rayargs['temp_dir'] = self.config.implementation.ray_temp_dir
            # Used to run on a VPN
            ray.services.get_node_ip_address = lambda: '127.0.0.1'

        # We can only set the num_cpus if running on a single-node
        if self.config.implementation.ip_head is None and self.config.implementation.redis_password is None:
            rayargs['num_cpus'] = self.config.implementation.n_cores
        ray.init(**rayargs)

        if len(row_column) > 0:
            ranges = row_column.split(',')
            if len(ranges) == 1:
                self.rows, self.cols = [int(ranges[0])], None
            if len(ranges) == 2:
                row_start, row_end = ranges
                self.rows, self.cols = range(
                    int(row_start), int(row_end)), None
            elif len(ranges) == 4:
                row_start, row_end, col_start, col_end = ranges
                line_start, line_end, samp_start, samp_end = ranges
                self.rows = range(int(row_start), int(row_end))
                self.cols = range(int(col_start), int(col_end))

        # Build the forward model and inversion objects
        self._init_nonpicklable_objects()
        self.io = IO(self.config, self.fm, self.iv, self.rows, self.cols)
    

    def __del__(self):
        ray.shutdown()

    def _init_nonpicklable_objects(self) -> None:
        """ Internal function to initialize objects that cannot be pickled
        """
        self.fm = ForwardModel(self.config)

        if self.config.implementation.mode == 'mcmc_inversion':
            self.iv = MCMCInversion(self.config, self.fm)
        elif self.config.implementation.mode in ['inversion', 'simulation']:
            self.iv = Inversion(self.config, self.fm)
        else:
            # This should never be reached due to configuration checking
            raise AttributeError('Config implementation mode node valid')

    def _clear_nonpicklable_objects(self):
        """ Internal function to clean objects that cannot be pickled
        """
        self.fm = None
        self.iv = None

    @ray.remote
    def _run_set_of_spectra(self, index_start: int, index_stop: int) -> None:
        """Internal function to run a chunk of spectra

        Args:
            index_start: spectral index to start execution at
            index_stop: spectral index to stop execution at

        """
        logging.basicConfig(format='%(levelname)s:%(message)s', level=self.loglevel, filename=self.logfile)
        self._init_nonpicklable_objects()
        io = IO(self.config, self.fm, self.iv, self.rows, self.cols)
        for index in range(index_start, index_stop):
            success, row, col, meas, geom = io.get_components_at_index(
                index)
            # Only run through the inversion if we got some data
            if success:
                if meas is not None and all(meas < -49.0):
                    # Bad data flags
                    self.states = []
                else:
                    # The inversion returns a list of states, which are
                    # intepreted either as samples from the posterior (MCMC case)
                    # or as a gradient descent trajectory (standard case). For
                    # a trajectory, the last spectrum is the converged solution.
                    self.states = self.iv.invert(meas, geom)

                # Write the spectra to disk
                io.write_spectrum(row, col, self.states, meas,
                                  geom, flush_immediately=True)
                if (index - index_start) % 100 == 0:
                    logging.info(
                        'Core at start index {} completed inversion {}/{}'.format(index_start, index-index_start,
                                                                                  index_stop-index_start))

    def run(self):
        """
        Iterate over all spectra, reading and writing through the IO
        object to handle formatting, buffering, and deferred write-to-file.
        The idea is to avoid reading the entire file into memory, or hitting
        the physical disk too often. These are our main class variables.
        """

        n_iter = len(self.io.iter_inds)
        self._clear_nonpicklable_objects()
        self.io = None

        if self.config.implementation.n_cores is None:
            n_workers = min(multiprocessing.cpu_count(), n_iter)
        else:
            n_workers = min(self.config.implementation.n_cores, n_iter)

        start_time = time.time()
        logging.info('Beginning inversions using {} cores'.format(n_workers))

        # Divide up spectra to run into chunks
        index_sets = np.linspace(0, n_iter, num=n_workers+1, dtype=int)

        # Run spectra, in either serial or parallel depending on n_workers
        results = ray.get([self._run_set_of_spectra.remote(self, index_sets[l], index_sets[l + 1])
                           for l in range(len(index_sets)-1)])

        total_time = time.time() - start_time
        logging.info('Inversions complete.  {} s total, {} spectra/s, {} spectra/s/core'.format(
            round(total_time,2), round(n_iter/total_time,4), round(n_iter/total_time/n_workers,4)))
Exemplo n.º 11
0
class Worker(object):
    def __init__(self, config: configs.Config, loglevel: str, logfile: str, worker_id: int = None, total_workers: int = None):
        """
        Worker class to help run a subset of spectra.

        Args:
            config: isofit configuration
            loglevel: output logging level
            logfile: output logging file
            worker_id: worker ID for logging reference
            total_workers: the total number of workers running, for logging reference
        """

        logging.basicConfig(format='%(levelname)s:%(message)s', level=loglevel, filename=logfile)
        self.config = config
        self.fm = ForwardModel(self.config)

        if self.config.implementation.mode == 'mcmc_inversion':
            self.iv = MCMCInversion(self.config, self.fm)
        elif self.config.implementation.mode in ['inversion', 'simulation']:
            self.iv = Inversion(self.config, self.fm)
        else:
            # This should never be reached due to configuration checking
            raise AttributeError('Config implementation mode node valid')

        self.io = IO(self.config, self.fm)

        self.approximate_total_spectra = None
        if total_workers is not None:
            self.approximate_total_spectra = self.io.n_cols * self.io.n_rows / total_workers
        self.worker_id = worker_id
        self.completed_spectra = 0


    def run_set_of_spectra(self, indices: np.array):


        for index in range(0, indices.shape[0]):

            logging.debug("Read chunk of spectra")
            row, col = indices[index,0], indices[index,1]

            input_data = self.io.get_components_at_index(row, col)

            self.completed_spectra += 1
            if input_data is not None:
                logging.debug("Run model")
                # The inversion returns a list of states, which are
                # intepreted either as samples from the posterior (MCMC case)
                # or as a gradient descent trajectory (standard case). For
                # a trajectory, the last spectrum is the converged solution.
                states = self.iv.invert(input_data.meas, input_data.geom)

                logging.debug("Write chunk of spectra")
                # Write the spectra to disk
                try:
                    self.io.write_spectrum(row, col, states, self.fm, self.iv)
                except ValueError as err:
                    logging.info(
                        f"""
                        Encountered the following ValueError in (row,col) ({row},{col}).
                        Results for this pixel will be all zeros.
                        """
                    )
                    logging.error(err)

                if index % 100 == 0:
                    if self.worker_id is not None and self.approximate_total_spectra is not None:
                        percent = np.round(self.completed_spectra / self.approximate_total_spectra * 100,2)
                        logging.info(f'Worker {self.worker_id} completed {self.completed_spectra}/~{self.approximate_total_spectra}:: {percent}% complete')
                    else:
                        logging.info(f'Worker at start location ({row},{col}) completed {index}/{indices.shape[0]}')

        self.io.flush_buffers()
Exemplo n.º 12
0
    def build_output(self, states: List, input_data: InputData,
                     fm: ForwardModel, iv: Inversion):
        """
        Build the output to be written to disk as a dictionary

        Args:
            states: results states from inversion.  In the MCMC case, these are interpreted as samples from the
            posterior, otherwise they are a gradient descent trajectory (with the last spectrum being the converged
            solution).
            input_data: an InputData object
            fm: the forward model used to solve the inversion
            iv: the inversion object
        """

        if len(states) == 0:
            # Write a bad data flag
            atm_bad = np.zeros(len(fm.instrument.n_chan) * 5) * -9999.0
            state_bad = np.zeros(len(fm.statevec)) * -9999.0
            data_bad = np.zeros(fm.instrument.n_chan) * -9999.0
            to_write = {
                'estimated_state_file': state_bad,
                'estimated_reflectance_file': data_bad,
                'estimated_emission_file': data_bad,
                'modeled_radiance_file': data_bad,
                'apparent_reflectance_file': data_bad,
                'path_radiance_file': data_bad,
                'simulated_measurement_file': data_bad,
                'algebraic_inverse_file': data_bad,
                'atmospheric_coefficients_file': atm_bad,
                'radiometry_correction_file': data_bad,
                'spectral_calibration_file': data_bad,
                'posterior_uncertainty_file': state_bad
            }

        else:
            to_write = {}

            meas = input_data.meas
            geom = input_data.geom
            reference_reflectance = input_data.reference_reflectance

            if self.config.implementation.mode == 'inversion_mcmc':
                state_est = states.mean(axis=0)
            else:
                state_est = states[-1, :]

            ############ Start with all of the 'independent' calculations
            if 'estimated_state_file' in self.output_datasets:
                to_write['estimated_state_file'] = state_est

            if 'path_radiance_file' in self.output_datasets:
                path_est = fm.calc_meas(state_est,
                                        geom,
                                        rfl=np.zeros(self.meas_wl.shape))
                to_write['path_radiance_file'] = np.column_stack(
                    (fm.instrument.wl_init, path_est))

            if 'spectral_calibration_file' in self.output_datasets:
                # Spectral calibration
                wl, fwhm = fm.calibration(state_est)
                cal = np.column_stack(
                    [np.arange(0, len(wl)), wl / 1000.0, fwhm / 1000.0])
                to_write['spectral_calibration_file'] = cal

            if 'posterior_uncertainty_file' in self.output_datasets:
                S_hat, K, G = iv.calc_posterior(state_est, geom, meas)
                to_write['posterior_uncertainty_file'] = np.sqrt(
                    np.diag(S_hat))

            ############ Now proceed to the calcs where they may be some overlap

            if any(item in
                   ['estimated_emission_file', 'apparent_reflectance_file']
                   for item in self.output_datasets):
                Ls_est = fm.calc_Ls(state_est, geom)

            if any(item in [
                    'estimated_reflectance_file', 'apparent_reflectance_file',
                    'modeled_radiance_file', 'simulated_measurement_file'
            ] for item in self.output_datasets):
                lamb_est = fm.calc_lamb(state_est, geom)

            if any(item in
                   ['modeled_radiance_file', 'simulated_measurement_file']
                   for item in self.output_datasets):
                meas_est = fm.calc_meas(state_est, geom, rfl=lamb_est)
                if 'modeled_radiance_file' in self.output_datasets:
                    to_write['modeled_radiance_file'] = np.column_stack(
                        (fm.instrument.wl_init, meas_est))

                if 'simulated_measurement_file' in self.output_datasets:
                    meas_sim = fm.instrument.simulate_measurement(
                        meas_est, geom)
                    to_write['simulated_measurement_file'] = np.column_stack(
                        (self.meas_wl, meas_sim))

            if 'estimated_emission_file' in self.output_datasets:
                to_write['estimated_emission_file'] = np.column_stack(
                    (self.meas_wl, Ls_est))

            if 'estimated_reflectance_file' in self.output_datasets:
                to_write['estimated_reflectance_file'] = np.column_stack(
                    (self.meas_wl, lamb_est))

            if 'apparent_reflectance_file' in self.output_datasets:
                # Upward emission & glint and apparent reflectance
                apparent_rfl_est = lamb_est + Ls_est
                to_write['apparent_reflectance_file'] = np.column_stack(
                    (self.meas_wl, apparent_rfl_est))

            x_surface, x_RT, x_instrument = fm.unpack(state_est)
            if any(item in
                   ['algebraic_inverse_file', 'atmospheric_coefficients_file']
                   for item in self.output_datasets):
                rfl_alg_opt, Ls, coeffs = invert_algebraic(
                    fm.surface, fm.RT, fm.instrument, x_surface, x_RT,
                    x_instrument, meas, geom)

            if 'algebraic_inverse_file' in self.output_datasets:
                to_write['algebraic_inverse_file'] = np.column_stack(
                    (self.meas_wl, rfl_alg_opt))

            if 'atmospheric_coefficients_file' in self.output_datasets:
                rhoatm, sphalb, transm, solar_irr, coszen, transup = coeffs
                atm = np.column_stack(
                    list(coeffs[:4]) +
                    [np.ones((len(self.meas_wl), 1)) * coszen])
                atm = atm.T.reshape((len(self.meas_wl) * 5, ))
                to_write['atmospheric_coefficients_file'] = atm

            if 'radiometry_correction_file' in self.output_datasets:
                factors = np.ones(len(self.meas_wl))
                if 'reference_reflectance_file' in self.input_datasets:
                    meas_est = fm.calc_meas(state_est,
                                            geom,
                                            rfl=reference_reflectance)
                    factors = meas_est / meas
                else:
                    logging.warning('No reflectance reference')
                to_write['radiometry_correction_file'] = factors

        return to_write
Exemplo n.º 13
0
class Isofit:
    """Spectroscopic Surface and Atmosphere Fitting."""
    def __init__(self,
                 config_file,
                 row_column='',
                 profile=False,
                 level='INFO'):
        """Initialize the Isofit class."""

        # Explicitly set the number of threads to be 1, so we can make better
        # use of multiprocessing
        os.environ["MKL_NUM_THREADS"] = "1"

        # Set logging level
        logging.basicConfig(format='%(message)s', level=level)

        self.rows = None
        self.cols = None
        self.config = None
        self.profile = profile
        self.fm = None
        self.iv = None
        self.io = None
        self.states = None

        # Load configuration file
        self.config = configs.create_new_config(config_file)
        self.config.get_config_errors()

        # Build the forward model and inversion objects
        self._init_nonpicklable_objects()

        # We set the row and column range of our analysis. The user can
        # specify: a single number, in which case it is interpreted as a row;
        # a comma-separated pair, in which case it is interpreted as a
        # row/column tuple (i.e. a single spectrum); or a comma-separated
        # quartet, in which case it is interpreted as a row, column range in the
        # order (line_start, line_end, sample_start, sample_end) - all values are
        # inclusive. If none of the above, we will analyze the whole cube.
        if len(row_column) > 0:
            ranges = row_column.split(',')
            if len(ranges) == 1:
                self.rows, self.cols = [int(ranges[0])], None
            if len(ranges) == 2:
                row_start, row_end = ranges
                self.rows, self.cols = range(int(row_start),
                                             int(row_end)), None
            elif len(ranges) == 4:
                row_start, row_end, col_start, col_end = ranges
                line_start, line_end, samp_start, samp_end = ranges
                self.rows = range(int(row_start), int(row_end))
                self.cols = range(int(col_start), int(col_end))

    def _init_nonpicklable_objects(self):
        self.fm = ForwardModel(self.config)

        if self.config.implementation.mode == 'mcmc_inversion':
            self.iv = MCMCInversion(self.config, self.fm)
        elif self.config.implementation.mode in ['inversion', 'simulation']:
            self.iv = Inversion(self.config, self.fm)
        else:
            # This should never be reached due to configuration checking
            raise AttributeError('Config implementation mode node valid')

    def _clear_nonpicklable_objects(self):
        self.fm = None
        self.iv = None

    def _run_set_of_spectra(self, index_start, index_stop):
        self._init_nonpicklable_objects()
        io = IO(self.config, self.fm, self.iv, self.rows, self.cols)
        for index in range(index_start, index_stop):
            success, row, col, meas, geom, configs = io.get_components_at_index(
                index)
            # Only run through the inversion if we got some data
            if success:
                if meas is not None and all(meas < -49.0):
                    # Bad data flags
                    self.states = []
                else:
                    # The inversion returns a list of states, which are
                    # intepreted either as samples from the posterior (MCMC case)
                    # or as a gradient descent trajectory (standard case). For
                    # a trajectory, the last spectrum is the converged solution.
                    self.states = self.iv.invert(meas, geom)

                # Write the spectra to disk
                io.write_spectrum(row,
                                  col,
                                  self.states,
                                  meas,
                                  geom,
                                  flush_immediately=True)
                if index % 1000 == 0:
                    logging.info('Completed inversion {}/{}'.format(
                        index, len(io.iter_inds)))

    def run(self, profile=False):
        """
        Iterate over all spectra, reading and writing through the IO
        object to handle formatting, buffering, and deferred write-to-file.
        The idea is to avoid reading the entire file into memory, or hitting
        the physical disk too often. These are our main class variables.
        """

        io = IO(self.config, self.fm, self.iv, self.rows, self.cols)
        if profile:
            for row, col, meas, geom, configs in io:
                if meas is not None and all(meas < -49.0):
                    # Bad data flags
                    self.states = []
                else:
                    # Profile output
                    gbl, lcl = globals(), locals()
                    cProfile.runctx('self.iv.invert(meas, geom)', gbl, lcl)

                # Write the spectra to disk
                io.write_spectrum(row, col, self.states, meas, geom)
        else:
            n_iter = len(io.iter_inds)
            io = None
            self._clear_nonpicklable_objects()

            if self.config.implementation.n_cores is None:
                n_cores = multiprocessing.cpu_count()
            else:
                n_cores = self.config.implementation.n_cores

            # Don't use more cores than needed
            n_cores = min(n_cores, n_iter)

            if self.config.implementation.runtime_nice_level is None:
                pool = multiprocessing.Pool(processes=n_cores)
            else:
                pool = multiprocessing.Pool(
                    processes=n_cores,
                    initializer=common.nice_me(
                        self.config.implementation.runtime_nice_level))

            start_time = time.time()
            logging.info('Beginning inversions using {} cores'.format(n_cores))

            results = []
            index_sets = np.linspace(0, n_iter, num=n_cores + 1, dtype=int)
            for l in range(len(index_sets) - 1):
                if n_cores == 1:
                    self._run_set_of_spectra(index_sets[0], index_sets[-1])
                else:
                    results.append(
                        pool.apply_async(self._run_set_of_spectra,
                                         args=(index_sets[l],
                                               index_sets[l + 1])))
            results = [p.get() for p in results]
            pool.close()
            pool.join()

            total_time = time.time() - start_time
            logging.info(
                'Parallel inversions complete.  {} s total, {} spectra/s, {}/spectra/core'
                .format(total_time, n_iter / total_time,
                        n_iter / total_time / n_cores))
Exemplo n.º 14
0
    full_config = Config({"forward_model":{"instrument":instrument_config,
                                           "surface":surface_config,
                                           "radiative_transfer": rtm_config}})
    #Start up ray
    if ray.is_initialized():
        ray.shutdown()
    ray.init(num_cpus = 48)

    # Run intial forward model
    fm = ForwardModel(full_config)

    inversion_settings = {"implementation": {"mode": "inversion",
                                             "inversion": {
                                              "windows": windows}}}
    inverse_config = Config(inversion_settings)
    iv = Inversion(inverse_config, fm)

    # Refine water vapor LUT
    water = []
    window  =5
    for line in range(10,990,100):
        print(line)
        obs_mean  =  observables.get_chunk(2,990,
                                          line-window,line+window).mean(axis =(0,1))
        loc_mean  =  location.get_chunk(2,990,
                                          line-window,line+window).mean(axis =(0,1))
        rad_mean  = radiance.get_chunk(2,990,
                                     line-window,line+window).mean(axis =(0,1))
        geom = Geometry(obs = obs_mean,loc = loc_mean)
        state_trajectory = iv.invert(rad_mean, geom)
        water.append(state_trajectory[-1][-1])
Exemplo n.º 15
0
    if ray.is_initialized():
        ray.shutdown()
    ray.init(num_cpus=48)

    fm = ForwardModel(full_config)

    inversion_settings = {
        "implementation": {
            "mode": "inversion",
            "inversion": {
                "windows": windows
            }
        }
    }
    inverse_config = Config(inversion_settings)
    iv = Inversion(inverse_config, fm)

    # Refine water vapor LUT
    water = []
    window = 5
    for line in range(10, 990, 100):
        print(line)
        obs_mean = observables.get_chunk(2, 990, line - window,
                                         line + window).mean(axis=(0, 1))
        loc_mean = location.get_chunk(2, 990, line - window,
                                      line + window).mean(axis=(0, 1))
        rad_mean = radiance.get_chunk(2, 990, line - window,
                                      line + window).mean(axis=(0, 1))
        geom = Geometry(obs=obs_mean, loc=loc_mean)
        state_trajectory = iv.invert(rad_mean, geom)
        water.append(state_trajectory[-1][-1])