def clean(self, value):
        """Cleans and returns the given value, or raises a ParameterNotValidError exception"""

        if not isinstance(value, six.string_types):
            raise ParameterNotValidError

        try:
            source, value = value.split('://', 1)
        except ValueError:
            raise ParameterNotValidError

        if source == 'service':
            if '@' in value:
                value, timestamp = value.split('@', 1)

                try:
                    service_time = timestamp_to_date(int(timestamp))
                except ValueError:
                    raise ParameterNotValidError
            else:
                service_time = None

            if ':' in value:
                service_name, variable_name = value.split(':', 1)
            else:
                service_name = value
                variable_name = None

            try:
                self.service = Service.objects.get(name=service_name)
            except ObjectDoesNotExist:
                raise ParameterNotValidError("Service '{}' not found".format(service_name))

            if variable_name:
                try:
                    variable = self.service.variable_set.all().get(variable=variable_name)
                except ObjectDoesNotExist:
                    raise ParameterNotValidError("Variable '{}' not found".format(variable_name))

                if service_time is not None:
                    time_index = best_fit(variable.time_stops, service_time)
                else:
                    time_index = None

                data = self.get_grid_for_variable(variable, time_index=time_index)
                return Raster(data, variable.full_extent, 1, 0, self.is_y_increasing(variable))
            else:
                return self.dataset
        else:
            raise ParameterNotValidError('Invalid source: {}'.format(source))