def _to_marginal()

in python-package/lets_plot/plot/marginal_layer.py [0:0]


def _to_marginal(side: str, size, layer: LayerSpec) -> LayerSpec:
    if side not in ['l', 'r', 't', 'b']:
        raise ValueError("Invalid 'side' value: {}. Valid values: 'l','r','t','b'.".format(side))

    if size is not None:
        if not 0.01 <= size <= 0.95:
            raise ValueError("Invalid 'size' value: {}. Should be in range [0.01..0.95].".format(size))

    layer_copy = LayerSpec.duplicate(layer)
    marginal_options = dict(
        marginal=True,
        margin_side=side,
        margin_size=size
    )

    layer_props = layer_copy.props()
    layer_props.update(marginal_options)

    layer_kind = None
    stat = layer_props.get('stat')
    if stat is not None:
        if stat == 'bin':
            layer_kind = 'histogram'
        elif stat == 'ydensity':
            layer_kind = 'violin'
        elif stat in ('density', 'boxplot', 'boxplot_outlier'):
            layer_kind = stat
    else:
        geom = layer_props.get('geom')
        if geom in ('histogram', 'boxplot', 'violin', 'density', 'freqpoly'):
            layer_kind = geom

    auto_settings = {}

    # choose a proper orientation
    if (side in ('l', 'r') and layer_kind in ('histogram', 'density', 'freqpoly')):
        auto_settings['orientation'] = 'y'

    if layer_kind in ('boxplot', 'boxplot_outlier', 'violin'):
        if side in ('l', 'r'):
            auto_settings['x'] = 0
        elif side in ('t', 'b'):
            auto_settings['y'] = 0
            auto_settings['orientation'] = 'y'

    # Update layer's options with auto-generated and try not to override user-defined options.
    filtered = {k: v for k, v in layer_props.items() if v is not None}
    layer_props.update(
        {**auto_settings, **filtered}
    )

    # For 'histogram' set mapping of x or y to '..density..' for compatibility with 'density' geom.
    if layer_kind == 'histogram':
        if side in ('l', 'r'):
            added_mapping = {'x': '..density..'}
        elif side in ('t', 'b'):
            added_mapping = {'y': '..density..'}

        aes_feature_spec = layer_props.get('mapping')
        mappings = aes_feature_spec.props() if isinstance(aes_feature_spec, FeatureSpec) else {}
        filtered_mappings = {k: v for k, v in mappings.items() if v is not None}
        updated_mappings = {**added_mapping, **filtered_mappings}
        updated_aes_feature_spec = FeatureSpec('mapping', name=None, **updated_mappings)
        layer_props['mapping'] = updated_aes_feature_spec

    return layer_copy