def astra_projector(vol_interp, astra_vol_geom, astra_proj_geom, ndim, impl):
    """Create an ASTRA projector configuration dictionary.

    Parameters
    ----------
    vol_interp : {'nearest', 'linear'}
        Interpolation type of the volume discretization. This determines
        the projection model that is chosen.
    astra_vol_geom : dict
        ASTRA volume geometry.
    astra_proj_geom : dict
        ASTRA projection geometry.
    ndim : {2, 3}
        Number of dimensions of the projector.
    impl : {'cpu', 'cuda'}
        Implementation of the projector.

    Returns
    -------
    proj_id : int
        Handle for the created ASTRA internal projector object.
    """
    if vol_interp not in ('nearest', 'linear'):
        raise ValueError("`vol_interp` '{}' not understood"
                         ''.format(vol_interp))
    impl = str(impl).lower()
    if impl not in ('cpu', 'cuda'):
        raise ValueError("`impl` '{}' not understood"
                         ''.format(impl))

    if 'type' not in astra_proj_geom:
        raise ValueError('invalid projection geometry dict {}'
                         ''.format(astra_proj_geom))
    if ndim == 3 and impl == 'cpu':
        raise ValueError('3D projectors not supported on CPU')

    ndim = int(ndim)

    proj_type = astra_proj_geom['type']
    if proj_type not in ('parallel', 'fanflat', 'fanflat_vec',
                         'parallel3d', 'parallel3d_vec', 'cone', 'cone_vec'):
        raise ValueError('invalid geometry type {!r}'.format(proj_type))

    # Mapping from interpolation type and geometry to ASTRA projector type.
    # "I" means probably mathematically inconsistent. Some projectors are
    # not implemented, e.g. CPU 3d projectors in general.
    type_map_cpu = {'parallel': {'nearest': 'line',
                                 'linear': 'linear'},  # I
                    'fanflat': {'nearest': 'line_fanflat',
                                'linear': 'line_fanflat'},  # I
                    'parallel3d': {'nearest': 'linear3d',  # I
                                   'linear': 'linear3d'},  # I
                    'cone': {'nearest': 'linearcone',  # I
                             'linear': 'linearcone'}}  # I
    type_map_cpu['fanflat_vec'] = type_map_cpu['fanflat']
    type_map_cpu['parallel3d_vec'] = type_map_cpu['parallel3d']
    type_map_cpu['cone_vec'] = type_map_cpu['cone']

    # GPU algorithms not necessarily require a projector, but will in future
    # releases making the interface more coherent regarding CPU and GPU
    type_map_cuda = {'parallel': 'cuda',  # I
                     'parallel3d': 'cuda3d'}  # I
    type_map_cuda['fanflat'] = type_map_cuda['parallel']
    type_map_cuda['fanflat_vec'] = type_map_cuda['fanflat']
    type_map_cuda['cone'] = type_map_cuda['parallel3d']
    type_map_cuda['parallel3d_vec'] = type_map_cuda['parallel3d']
    type_map_cuda['cone_vec'] = type_map_cuda['cone']

    # create config dict
    proj_cfg = {}
    if impl == 'cpu':
        proj_cfg['type'] = type_map_cpu[proj_type][vol_interp]
    else:  # impl == 'cuda'
        proj_cfg['type'] = type_map_cuda[proj_type]
    proj_cfg['VolumeGeometry'] = astra_vol_geom
    proj_cfg['ProjectionGeometry'] = astra_proj_geom
    proj_cfg['options'] = {}

    # Add the hacky 1/r^2 weighting exposed in intermediate versions of
    # ASTRA
    if (proj_type in ('cone', 'cone_vec') and
            astra_supports('cone3d_hacky_density_weighting')):
        proj_cfg['options']['DensityWeighting'] = True

    if ndim == 2:
        return astra.projector.create(proj_cfg)
    else:
        return astra.projector3d.create(proj_cfg)
Create an ASTRA projector configuration dictionary.

    Parameters
    ----------
    vol_interp : {'nearest', 'linear'}
        Interpolation type of the volume discretization. This determines
        the projection model that is chosen.
    astra_vol_geom : dict
        ASTRA volume geometry.
    astra_proj_geom : dict
        ASTRA projection geometry.
    ndim : {2, 3}
        Number of dimensions of the projector.
    impl : {'cpu', 'cuda'}
        Implementation of the projector.

    Returns
    -------
    proj_id : int
        Handle for the created ASTRA internal projector object.