docs: 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))