Ejemplo n.º 1
0
    def gen_valid_hdf5_output(self):
        import os
        from taurex.output.hdf5 import HDF5Output

        from taurex.util.util import wnwidth_to_wlwidth, compute_bin_edges
        file_path = os.path.join(self.test_dir, 'test.hdf5')

        test_dict = {}

        wngrid = np.linspace(100, 1000, 100)
        wlgrid = 10000 / wngrid
        spectrum = np.random.rand(100)
        error = np.random.rand(100)
        wnwidth = compute_bin_edges(wngrid)[-1]
        wlwidth = wnwidth_to_wlwidth(wngrid, wnwidth)

        test_dict['instrument_wlgrid'] = wlgrid
        test_dict['instrument_wngrid'] = wngrid
        test_dict['instrument_spectrum'] = spectrum
        test_dict['instrument_noise'] = error
        test_dict['instrument_wnwidth'] = wnwidth

        with HDF5Output(file_path) as f:

            group = f.create_group('Output')
            group.store_dictionary(test_dict, group_name='Spectra')

        return file_path, wngrid, wlgrid, spectrum, error, wnwidth, wlwidth
Ejemplo n.º 2
0
 def manual_binning(self):
     from taurex.util.util import compute_bin_edges
     """
     Performs the calculation of bin edges when none are present
     """
     self._bin_edges, self._bin_widths = \
         compute_bin_edges(self.wavelengthGrid)
Ejemplo n.º 3
0
    def __init__(self, filename=None):
        super().__init__()

        self._spectrum = np.loadtxt(filename)

        self._wlgrid = self._spectrum[:, 0]

        sortedwl = self._wlgrid.argsort()[::-1]

        self._wlgrid = self._wlgrid[sortedwl]

        self._wngrid = 10000 / self._wlgrid

        self._noise = self._spectrum[sortedwl, 1]

        try:
            self._wlwidths = self._spectrum[sortedwl, 2]
        except IndexError:
            from taurex.util.util import compute_bin_edges

            self._wlwidths - compute_bin_edges(self._wlgrid)[-1]

        self.create_wn_widths()

        self._binner = FluxBinner(self._wngrid, wngrid_width=self._wnwidths)
Ejemplo n.º 4
0
    def generate_spectrum_output(self,
                                 model_output,
                                 output_size=OutputSize.heavy):
        """
        Given a forward model output, generate a dictionary
        that can be used to store to file. This can include
        storing the native and binned spectrum.
        Not necessary for the function of the class but useful for
        full intergation into TauREx3, especially when storing results
        from a retrieval. 
        Can be overwritten to store more information.

        Parameters
        ----------
        model_output: obj:`tuple`
            Result from running a TauREx3 forward model

        output_size: :class:`~taurex.taurexdefs.OutputSize`
            Size of the output.


        Returns
        -------
        :obj:`dict`:
            Dictionary of spectra


        """
        output = {}

        wngrid, flux, tau, extra = model_output

        output['native_wngrid'] = wngrid
        output['native_wlgrid'] = 10000 / wngrid
        output['native_spectrum'] = flux
        output['binned_spectrum'] = self.bindown(wngrid, flux)[1]
        output['native_wnwidth'] = compute_bin_edges(wngrid)[-1]
        output['native_wlwidth'] = compute_bin_edges(10000 / wngrid)[-1]
        if output_size > OutputSize.lighter:
            output['binned_tau'] = self.bindown(wngrid, tau)[1]
            if output_size > OutputSize.light:
                output['native_tau'] = tau

        return output
Ejemplo n.º 5
0
    def __init__(self, wngrid, wngrid_width=None):
        super().__init__()

        sort_grid = wngrid.argsort()
        self._wngrid = wngrid[sort_grid]
        self._wngrid_width = wngrid_width

        if self._wngrid_width is None:
            self._wngrid_width = compute_bin_edges(self._wngrid)[-1]
        elif hasattr(self._wngrid_width, '__len__'):
            if len(self._wngrid_width) != len(self._wngrid):
                raise ValueError('Wavenumber width should be signel value or '
                                 'same shape as wavenumber grid')
            self._wngrid_width = wngrid_width[sort_grid]

        if not hasattr(self._wngrid_width, '__len__'):
            self._wngrid_width = np.ones_like(self._wngrid)*self._wngrid_width
Ejemplo n.º 6
0
    def __init__(self, wngrid, wngrid_width=None):

        self._wngrid = wngrid
        self._wn_width = wngrid_width
        if self._wn_width is None:
            self._wn_width = compute_bin_edges(self._wngrid)[-1]
Ejemplo n.º 7
0
    def bindown(self, wngrid, spectrum, grid_width=None, error=None):
        """

        Bins down spectrum.

        Parameters
        ----------
        wngrid : :obj:`array`
            The wavenumber grid of the spectrum to be binned down.

        spectrum: :obj:`array`
            The spectra we wish to bin-down. Must be same shape as
            ``wngrid``.

        grid_width: :obj:`array`, optional
            Wavenumber grid full-widths for the spectrum to be binned down.
            Must be same shape as ``wngrid``.
            Optional.

        error: :obj:`array`, optional
            Associated errors or noise of the spectrum. Must be same shape
            as ``wngrid``.Optional parameter.

        Returns
        -------
        binned_wngrid : :obj:`array`
            New wavenumber grid

        spectrum: :obj:`array`
            Binned spectrum.

        grid_width: :obj:`array`
            New grid-widths

        error: :obj:`array` or None
            Binned error if given else ``None``

        """

        sorted_input = wngrid.argsort()
        spectrum = spectrum[..., sorted_input]
        if error is not None:
            error = error[..., sorted_input]

        bin_spectrum = np.zeros(spectrum[..., 0].shape + self._wngrid.shape)

        if error is not None:
            bin_error = np.zeros(spectrum[..., 0].shape + self._wngrid.shape)
        else:
            bin_error = None

        old_spect_wn = wngrid

        old_spect_flux = spectrum
        old_spect_err = error

        old_spect_width = grid_width

        if old_spect_width is None:
            old_spect_width = compute_bin_edges(old_spect_wn)[-1]

        old_spect_min = old_spect_wn - old_spect_width / 2
        old_spect_max = old_spect_wn + old_spect_width / 2

        new_spec_lhs = self._wngrid
        new_spec_rhs = self._wngrid_width

        new_spec_wn = self._wngrid

        new_spec_wn_min = new_spec_lhs - new_spec_rhs / 2
        new_spec_wn_max = new_spec_lhs + new_spec_rhs / 2

        save_start = 0
        save_stop = 0

        for idx, res in enumerate(
                zip(new_spec_wn, new_spec_wn_min, new_spec_wn_max)):

            wn, wn_min, wn_max = res
            sum_spectrum = 0
            sum_noise = 0
            sum_weight = 0

            save_start = np.searchsorted(old_spect_max, wn_min, side='right')
            save_stop = np.searchsorted(old_spect_min[1:],
                                        wn_max,
                                        side='right')

            save_stop = min(save_stop, old_spect_min.shape[0] - 1)
            save_start = min(save_start, old_spect_min.shape[0] - 1)

            if not wn_min <= old_spect_max[save_start] or not \
                    old_spect_min[save_stop] <= wn_max:
                continue

            spect_min = old_spect_min[save_start:save_stop + 1]
            spect_max = old_spect_max[save_start:save_stop + 1]

            weight = (np.minimum(wn_max, spect_max) -
                      np.maximum(spect_min, wn_min)) / (wn_max - wn_min)

            sum_weight = np.sum(weight)

            sum_spectrum = np.sum(
                weight * old_spect_flux[..., save_start:save_stop + 1],
                axis=-1)

            if error is not None:
                sum_noise = np.sum(
                    weight * weight *
                    old_spect_err[..., save_start:save_stop + 1]**2,
                    axis=0)

                sum_noise = np.sqrt(sum_noise / sum_weight / sum_weight)

            bin_spectrum[..., idx] = sum_spectrum

            if error is not None:
                bin_error[idx] = sum_noise

        return self._wngrid, bin_spectrum, bin_error, self._wngrid_width
Ejemplo n.º 8
0
def main():
    import argparse
    import datetime

    import logging
    from taurex.mpi import get_rank
    from taurex.log import setLogLevel
    from taurex.log.logger import root_logger
    from taurex.parameter import ParameterParser
    from taurex.output.hdf5 import HDF5Output
    from taurex.util.output import generate_profile_dict, store_contributions
    from .taurexdefs import OutputSize
    from . import __version__ as version

    import numpy as np

    parser = argparse.ArgumentParser(description='TauREx {}'.format(version))

    parser.add_argument("-i", "--input", dest='input_file', type=str,
                        required=True, help="Input par file to pass")

    parser.add_argument("-R", "--retrieval", dest='retrieval', default=False,
                        help="When set, runs retrieval", action='store_true')

    parser.add_argument("-p", "--plot", dest='plot', default=False,
                              help="Whether to plot after the run",
                              action='store_true')

    parser.add_argument("-g", "--debug-log", dest='debug', default=False,
                        help="Debug log output", action='store_true')

    parser.add_argument("-c", "--show-contrib", dest='contrib',
                        default=False, help="Show basic contributions",
                        action='store_true')

    parser.add_argument("-C", "--full-contrib", dest='full_contrib',
                        default=False, help="Show ALL contributions",
                        action='store_true')

    parser.add_argument("--light", dest='light', default=False,
                        help="Light outputs", action='store_true')

    parser.add_argument("--lighter", dest='lighter', default=False,
                        help="Even Lighter outputs", action='store_true')

    parser.add_argument("-o", "--output_file", dest='output_file', type=str)

    parser.add_argument("-S", "--save-spectrum",
                        dest='save_spectrum', type=str)
    args = parser.parse_args()

    output_size = OutputSize.heavy

    if args.light:
        output_size = OutputSize.light

    if args.lighter:
        output_size = OutputSize.lighter

    if args.debug:
        setLogLevel(logging.DEBUG)

    root_logger.info('TauREx %s', version)

    root_logger.info('TauREx PROGRAM START AT %s', datetime.datetime.now())

    # Parse the input file
    pp = ParameterParser()
    pp.read(args.input_file)

    # Setup global parameters
    pp.setup_globals()
    # Generate a model from the input
    model = pp.generate_appropriate_model()

    # build the model
    model.build()

    # Get the spectrum
    observation = pp.generate_observation()

    binning = pp.generate_binning()

    wngrid = None

    if binning == 'observed' and observation is None:
        logging.critical('Binning selected from Observation yet None provided')
        quit()

    if binning is None:
        if observation is None or observation == 'self':
            binning = model.defaultBinner()
            wngrid = model.nativeWavenumberGrid
        else:
            binning = observation.create_binner()
            wngrid = observation.wavenumberGrid
    else:
        if binning == 'native':
            binning = model.defaultBinner()
            wngrid = model.nativeWavenumberGrid
        elif binning == 'observed':
            binning = observation.create_binner()
            wngrid = observation.wavenumberGrid
        else:
            binning, wngrid = binning

    instrument = pp.generate_instrument(binner=binning)

    num_obs = 1
    if instrument is not None:
        instrument, num_obs = instrument

    if observation == 'self' and instrument is None:
        logging.getLogger('taurex').critical(
            'Instrument nust be specified when using self option')
        raise ValueError('No instruemnt specified for self option')

    inst_result = None
    if instrument is not None:
        inst_result = instrument.model_noise(
            model, model_res=model.model(), num_observations=num_obs)

    # Observation on self
    if observation == 'self':
        from taurex.data.spectrum import ArraySpectrum
        from taurex.util.util import wnwidth_to_wlwidth
        inst_wngrid, inst_spectrum, inst_noise, inst_width = inst_result

        inst_wlgrid = 10000/inst_wngrid

        inst_wlwidth = wnwidth_to_wlwidth(inst_wngrid, inst_width)
        observation = ArraySpectrum(
            np.vstack([inst_wlgrid, inst_spectrum,
                       inst_noise, inst_wlwidth]).T)
        binning = observation.create_binner()

    # Handle outputs
    if args.output_file:
        # Output taurex data
        with HDF5Output(args.output_file) as o:
            model.write(o)

    optimizer = None
    solution = None

    if args.retrieval is True:
        import time
        if observation is None:
            logging.critical('No spectrum is defined!!')
            quit()

        optimizer = pp.generate_optimizer()
        optimizer.set_model(model)
        optimizer.set_observed(observation)

        fitting_parameters = pp.generate_fitting_parameters()

        for key, value in fitting_parameters.items():
            fit = value['fit']
            bounds = value['bounds']
            mode = value['mode']
            factor = value['factor']

            if fit:
                logging.info('Fitting: {}'.format(key))
                optimizer.enable_fit(key)
            else:
                optimizer.disable_fit(key)

            if factor:
                optimizer.set_factor_boundary(key, factor)

            if bounds:
                optimizer.set_boundary(key, bounds)

            if mode:
                optimizer.set_mode(key, mode.lower())

        start_time = time.time()
        solution = optimizer.fit(output_size=output_size)

        end_time = time.time()

        root_logger.info(
            'Total Retrieval finish in %s seconds', end_time-start_time)

        for _, optimized, _, _ in optimizer.get_solution():
            optimizer.update_model(optimized)
            break

    result = model.model()

    if args.save_spectrum is not None:

        # with open(args.save_spectrum, 'w') as f:
        from taurex.util.util import wnwidth_to_wlwidth, compute_bin_edges
        save_wnwidth = compute_bin_edges(wngrid)[1]
        save_wl = 10000/wngrid
        save_wlwidth = wnwidth_to_wlwidth(wngrid, save_wnwidth)
        save_model = binning.bin_model(result)[1]
        save_error = np.zeros_like(save_wl)
        if inst_result is not None:
            inst_wngrid, inst_spectrum, inst_noise, inst_width = inst_result

            save_model = inst_spectrum
            save_wl = 10000/inst_wngrid

            save_wlwidth = wnwidth_to_wlwidth(inst_wngrid, inst_width)

            save_error = inst_noise

        np.savetxt(args.save_spectrum,
                   np.vstack((save_wl, save_model, save_error,
                              save_wlwidth)).T)

    if args.output_file:

        # Output taurex data
        with HDF5Output(args.output_file, append=True) as o:

            out = o.create_group('Output')
            if observation is not None:
                obs = o.create_group('Observed')
                observation.write(obs)

            profiles = generate_profile_dict(model)
            spectrum = \
                binning.generate_spectrum_output(result,
                                                 output_size=output_size)

            if inst_result is not None:
                spectrum['instrument_wngrid'] = inst_result[0]
                spectrum['instrument_wnwidth'] = inst_result[-1]
                spectrum['instrument_wlgrid'] = 10000/inst_result[0]
                spectrum['instrument_spectrum'] = inst_result[1]
                spectrum['instrument_noise'] = inst_result[2]

            spectrum['Contributions'] = \
                store_contributions(binning, model, output_size=output_size-3)
            if solution is not None:
                out.store_dictionary(solution, group_name='Solutions')
                priors = {}
                priors['Profiles'] = profiles
                priors['Spectra'] = spectrum
                out.store_dictionary(priors, group_name='Priors')
            else:
                out.store_dictionary(profiles, group_name='Profiles')
                out.store_dictionary(spectrum, group_name='Spectra')

            if optimizer:
                optimizer.write(o)

    root_logger.info('TauREx PROGRAM END AT %s s', datetime.datetime.now())

    if args.plot:
        wlgrid = 10000/wngrid
        if get_rank() == 0:
            import matplotlib.pyplot as plt
            fig = plt.figure()
            ax = fig.add_subplot(1, 1, 1)

            ax.set_xlabel(r'Wavelength $(\mu m)$')
            ax.set_ylabel(r'$(R_p/R_s)^2$')
            is_lightcurve = False
            try:
                from taurex.model.lightcurve.lightcurve import LightCurveModel
                is_lightcurve = isinstance(model, LightCurveModel)
                ax.set_xscale('linear')
            except ImportError:
                pass

            if observation is not None:
                if is_lightcurve:
                    ax.plot(observation.spectrum.flatten(),
                            label='observation')
                else:
                    ax.errorbar(observation.wavelengthGrid,
                                observation.spectrum, observation.errorBar,
                                fmt='.',
                                label='observation')

            if is_lightcurve:
                ax.plot(result[1], label='forward model')
            else:

                if inst_result is not None:
                    from taurex.util.util import wnwidth_to_wlwidth
                    inst_wngrid, inst_spectrum, \
                        inst_noise, inst_width = inst_result

                    inst_wlgrid = 10000/inst_wngrid

                    inst_wlwidth = wnwidth_to_wlwidth(inst_wngrid, inst_width)

                    ax.errorbar(inst_wlgrid, inst_spectrum, inst_noise,
                                inst_wlwidth/2, '.', label='Instrument')

                else:
                    ax.plot(wlgrid, binning.bin_model(
                        result)[1], label='forward model')

                ax.set_xscale('log')

            if args.contrib:
                native_grid, contrib_result = model.model_contrib(
                    wngrid=wngrid)

                for contrib_name, contrib in contrib_result.items():

                    flux, tau, extras = contrib

                    binned = binning.bindown(native_grid, flux)
                    if is_lightcurve:
                        ax.plot(binned[1], label=contrib_name)
                    else:
                        ax.plot(wlgrid, binned[1], label=contrib_name)

            if args.full_contrib:
                native_grid, contrib_result = model.model_full_contrib(
                    wngrid=wngrid)

                for contrib_name, contrib in contrib_result.items():

                    for name, flux, tau, extras in contrib:

                        label = '{} - {}'.format(contrib_name, name)

                        binned = binning.bindown(native_grid, flux)
                        if is_lightcurve:
                            ax.plot(binned[1], label=label)
                        else:
                            ax.plot(wlgrid, binned[1], label=label)

            plt.legend()
            plt.show()
        else:
            logging.getLogger('taurex').warning(
                'Number of processes > 1 so not plotting')
Ejemplo n.º 9
0
def test_bin_edges(res):
    from taurex.util.util import compute_bin_edges, create_grid_res
    grid = create_grid_res(res, 300, 10000)
    edges, widths = compute_bin_edges(grid[:, 0])
    
    assert round(np.mean(grid[:, 0]/widths)) == res