Example #1
0
def resample(cube, config, output, format, variables, method, frequency,
             offset, base, kind, tolerance, dry_run):
    """
    Resample data along the time dimension.
    """

    input_path = cube
    config_files = config
    output_path = output
    output_format = format

    from xcube.util.config import load_configs
    config = load_configs(*config_files) if config_files else {}

    if input_path:
        config['input_path'] = input_path
    if output_path:
        config['output_path'] = output_path
    if output_format:
        config['output_format'] = output_format
    if method:
        config['methods'] = method
    if frequency:
        config['frequency'] = frequency
    if offset:
        config['offset'] = offset
    if offset:
        config['base'] = base
    if kind:
        config['interp_kind'] = kind
    if tolerance:
        config['tolerance'] = tolerance
    if variables:
        try:
            variables = set(map(lambda c: str(c).strip(),
                                variables.split(',')))
        except ValueError:
            variables = None
        if variables is not None \
                and next(iter(True for var_name in variables if var_name == ''), False):
            variables = None
        if variables is None or len(variables) == 0:
            raise click.ClickException(f'invalid variables {variables!r}')
        config['variables'] = variables

    if 'methods' in config:
        methods = config['methods']
        for method in methods:
            if method not in RESAMPLING_METHODS:
                raise click.ClickException(
                    f'invalid resampling method {method!r}')

    # noinspection PyBroadException
    _resample_in_time(**config, dry_run=dry_run, monitor=print)

    return 0
Example #2
0
def _get_custom_color_list(config_file):
    global SNAP_CPD_LIST
    config = load_configs(config_file) if config_file else {}
    styles = config['Styles']
    for style in styles:
        cm = style['ColorMappings']
        for key in cm.keys():
            if 'ColorFile' in cm[key]:
                cf = cm[key]['ColorFile']
                if cf not in SNAP_CPD_LIST:
                    SNAP_CPD_LIST.append(cf)
    return SNAP_CPD_LIST
Example #3
0
def _get_custom_color_list(config_file):
    # global: too bad :(
    global SNAP_CPD_LIST
    config = load_configs(config_file) if config_file else {}
    styles = config.get('Styles')
    if isinstance(styles, list):
        for style in styles:
            cm = style.get('ColorMappings')
            if isinstance(cm, dict):
                for key in cm.keys():
                    if 'ColorFile' in cm[key]:
                        cf = cm[key]['ColorFile']
                        if cf not in SNAP_CPD_LIST:
                            SNAP_CPD_LIST.append(cf)
    return SNAP_CPD_LIST
Example #4
0
def edit_metadata(input_path: str,
                  output_path: str = None,
                  metadata_path: str = None,
                  update_coords: bool = False,
                  in_place: bool = False,
                  monitor: Callable[..., None] = None,
                  exception_type: Type[Exception] = ValueError):
    """
    Edit the metadata of an xcube dataset.

    Editing the metadata because it may be incorrect, inconsistent or incomplete.
    The metadata attributes should be given by a yaml file with the keywords to be edited.
    The function currently works only for data cubes using ZARR format.

    :param input_path: Path to input dataset with ZARR format.
    :param output_path: Path to output dataset with ZARR format. May contain "{input}" template string,
           which is replaced by the input path's file name without file name extentsion.
    :param metadata_path: Path to the metadata file, which will edit the existing metadata.
    :param update_coords: Whether to update the metadata about the coordinates.
    :param in_place: Whether to modify the dataset in place.
           If False, a copy is made and *output_path* must be given.
    :param monitor: A progress monitor.
    :param exception_type: Type of exception to be used on value errors.
    """

    input_path = os.path.abspath(os.path.normpath(input_path))

    if not os.path.isfile(os.path.join(input_path, '.zgroup')):
        raise exception_type(
            'Input path must point to ZARR dataset directory.')

    if in_place:
        output_path = input_path
    else:
        if not output_path:
            raise exception_type(f'Output path must be given.')
        if '{input}' in output_path:
            base_name, _ = os.path.splitext(os.path.basename(input_path))
            output_path = output_path.format(input=base_name)
        output_path = os.path.abspath(os.path.normpath(output_path))
        if os.path.exists(output_path):
            raise exception_type(f'Output path already exists.')

    if not in_place:
        shutil.copytree(input_path, output_path)

    if monitor is None:
        # noinspection PyUnusedLocal
        def monitor(*args):
            pass

    cube = zarr.open(output_path)

    if update_coords:
        with xr.open_zarr(output_path) as ds:
            ds_attrs = update_dataset_attrs(ds,
                                            update_existing=False,
                                            in_place=True).attrs
        for key in ds_attrs:
            cube.attrs.update({key: ds_attrs[key]})

    if metadata_path:
        new_metadata = load_configs(metadata_path)

        for element in new_metadata:
            if 'output_metadata' in element:
                _edit_keyvalue_in_metadata(cube, new_metadata, element,
                                           monitor)
            else:
                if cube.__contains__(element):
                    _edit_keyvalue_in_metadata(cube[element], new_metadata,
                                               element, monitor)
                else:
                    warnings.warn(
                        f'The variable "{element}" could not be found in the xcube dataset. '
                        f'Please check spelling of it.')

    # the metadata attrs of a consolidated xcube dataset may not be changed
    # (https://zarr.readthedocs.io/en/stable/api/convenience.html#zarr.convenience.consolidate_metadata)
    # therefore after changing metadata the xcube dataset needs to be consolidated once more.
    if os.path.exists(os.path.join(output_path, '.zmetadata')):
        optimize_dataset(output_path, in_place=True)
Example #5
0
def get_config_dict(config_files: Sequence[str] = None,
                    input_paths: Sequence[str] = None,
                    input_processor_name: str = None,
                    output_path: str = None,
                    output_writer_name: str = None,
                    output_size: str = None,
                    output_region: str = None,
                    output_variables: str = None,
                    output_resampling: str = None,
                    append_mode: bool = True,
                    profile_mode: bool = False,
                    no_sort_mode: bool = False):
    """
    Get a configuration dictionary from given (command-line) arguments.

    :return: Configuration dictionary
    :raise OSError, ValueError
    """

    config = load_configs(*config_files) if config_files else {}

    # preserve backward compatibility for old names
    if 'input_processor' in config:
        config['input_processor_name'] = config.pop('input_processor')
    if 'output_writer' in config:
        config['output_writer_name'] = config.pop('output_writer')

    # Overwrite current configuration by cli arguments
    if input_paths is not None and 'input_paths' not in config:
        if len(input_paths) == 1 and input_paths[0].endswith(".txt"):
            with open(input_paths[0]) as input_txt:
                input_paths = input_txt.readlines()
            config['input_paths'] = [x.strip() for x in input_paths]
        else:
            config['input_paths'] = input_paths

    if input_processor_name is not None and 'input_processor_name' not in config:
        config['input_processor_name'] = input_processor_name

    if output_path is not None and 'output_path' not in config:
        config['output_path'] = output_path

    if output_writer_name is not None and 'output_writer_name' not in config:
        config['output_writer_name'] = output_writer_name

    if output_resampling is not None and 'output_resampling' not in config:
        config['output_resampling'] = output_resampling

    if output_size is not None:
        try:
            output_size = list(map(lambda c: int(c), output_size.split(',')))
        except ValueError:
            output_size = None
        if output_size is None or len(output_size) != 2:
            raise ValueError(
                f'output_size must have the form <width>,<height>,'
                f' where both values must be positive integer numbers')
        config['output_size'] = output_size

    if output_region is not None:
        try:
            output_region = list(
                map(lambda c: float(c), output_region.split(',')))
        except ValueError:
            output_region = None
        if output_region is None or len(output_region) != 4:
            raise ValueError(
                f'output_region must have the form <lon_min>,<lat_min>,<lon_max>,<lat_max>,'
                f' where all four numbers must be floating point numbers in degrees'
            )
        config['output_region'] = output_region

    if output_variables is not None:
        output_variables = list(
            map(lambda c: c.strip(), output_variables.split(',')))
        if output_variables == [''] or any(
            [var_name == '' for var_name in output_variables]):
            raise ValueError(
                'output_variables must be a list of existing variable names')
        config['output_variables'] = output_variables

    if profile_mode is not None and config.get('profile_mode') is None:
        config['profile_mode'] = profile_mode

    if append_mode is not None and config.get('append_mode') is None:
        config['append_mode'] = append_mode

    if no_sort_mode is not None and config.get('no_sort_mode') is None:
        config['no_sort_mode'] = no_sort_mode

    processed_variables = config.get('processed_variables')
    if processed_variables:
        config['processed_variables'] = to_name_dict_pairs(processed_variables)

    output_variables = config.get('output_variables')
    if output_variables:
        config['output_variables'] = to_name_dict_pairs(output_variables,
                                                        default_key='name')

    output_metadata = config.get('output_metadata')
    if output_metadata:
        config['output_metadata'] = flatten_dict(output_metadata)

    return config