def _create_fig(
    *,
    x_sc=bq.LinearScale,
    y_sc=bq.LinearScale,
    x_ax=bq.Axis,
    y_ax=bq.Axis,
    fig=bq.Figure,
    options={},
    params={}
):
    """
    Initializes scales and axes for a bqplot figure and returns the resulting
    blank figure. Each plot component is passed in as a class. The plot options
    should be passed into options.

    Any additional parameters to initialize plot components are passed into
    params as a dict of { plot_component: { trait: value, ... } }

    For example, to change the grid lines of the x-axis:
    params={ 'x_ax': {'grid_lines' : 'solid'} }

    If the param value is a function, it will be called with the options dict
    augmented with all previously created plot elements. This permits
    dependencies on plot elements:
    params={ 'x_ax': {'scale': lambda opts: opts['x_sc'] } }
    """
    params = _merge_with_defaults(params)

    x_sc = x_sc(**_call_params(params['x_sc'], options))
    y_sc = y_sc(**_call_params(params['y_sc'], options))
    options = tz.merge(options, {'x_sc': x_sc, 'y_sc': y_sc})

    x_ax = x_ax(**_call_params(params['x_ax'], options))
    y_ax = y_ax(**_call_params(params['y_ax'], options))
    options = tz.merge(options, {'x_ax': x_ax, 'y_ax': y_ax, 'marks': []})

    fig = fig(**_call_params(params['fig'], options))
    return fig
Initializes scales and axes for a bqplot figure and returns the resulting
    blank figure. Each plot component is passed in as a class. The plot options
    should be passed into options.

    Any additional parameters to initialize plot components are passed into
    params as a dict of { plot_component: { trait: value, ... } }

    For example, to change the grid lines of the x-axis:
    params={ 'x_ax': {'grid_lines' : 'solid'} }

    If the param value is a function, it will be called with the options dict
    augmented with all previously created plot elements. This permits
    dependencies on plot elements:
    params={ 'x_ax': {'scale': lambda opts: opts['x_sc'] } }