docs: def uniprot_map(from_scheme, to_scheme, list_of_from_ids, cache_dir = None, silent = True):
      '''Maps from one ID scheme to another using the UniProt service.
          list_of_ids should be a list of strings.
          This function was adapted from http://www.uniprot.org/faq/28#id_mapping_examples which also gives examples of
          valid values for from_scheme and to_scheme.
          Note that some conversions are not directly possible e.g. PDB_ID (PDB) to UPARC (UniParc). They need to go through
          an intermediary format like ACC (UniProtKB AC) or ID (UniProtKB ID).
          This function returns a dict mapping the IDs in from_scheme to a list of sorted IDs in to_scheme.
      '''
      try:
          assert(hasattr(list_of_from_ids, '__iter__'))
      except:
          raise Exception('The list_of_from_ids argument should be an iterable type (e.g. list).')
      full_mapping = {}
      cached_mapping_file = None
      if cache_dir:
          cached_mapping_file = os.path.join(cache_dir, '%s.%s' % (from_scheme, to_scheme))
          if os.path.exists(cached_mapping_file):
              full_mapping = simplejson.loads(read_file(cached_mapping_file))
      list_of_from_ids = set(list_of_from_ids)
  
      requested_mapping = {}
      remaining_ids = []
      for id in list_of_from_ids:
          if full_mapping.get(id):
              requested_mapping[id] = full_mapping[id]
          else:
              remaining_ids.append(id)
      assert(set(remaining_ids + requested_mapping.keys()) == set(list_of_from_ids))
  
      if remaining_ids:
          if not silent:
              print("Getting %s->%s mapping" % (from_scheme, to_scheme))
          url = 'http://www.uniprot.org/mapping/'
          params = {
              'from'      : from_scheme,
              'to'        : to_scheme,
              'format'    : 'tab',
              'query'     : ' '.join(sorted(list(list_of_from_ids))),
          }
  
          data = urllib.urlencode(params)
          request = urllib2.Request(url, data)
          contact = "" # Please set your email address here to help us debug in case of problems.
          request.add_header('User-Agent', 'Python %s' % contact)
          response = urllib2.urlopen(request)
          page = response.read(200000)
          lines = page.split("\n")
  
          assert(lines[-1] == '')
          assert(lines[0].split("\t") == ['From', 'To'])
          for line in lines[1:-1]:
              tokens = line.split("\t")
              assert(len(tokens) == 2)
              assert(tokens[0] in list_of_from_ids)
              full_mapping[tokens[0]] = full_mapping.get(tokens[0], [])
              full_mapping[tokens[0]].append(tokens[1])
              requested_mapping[tokens[0]] = requested_mapping.get(tokens[0], [])
              requested_mapping[tokens[0]].append(tokens[1])
  
      # Sort the IDs
      for k, v in requested_mapping.iteritems():
          #assert(len(v) == len(set(v)))
          requested_mapping[k] = sorted(set(v))
      for k, v in full_mapping.iteritems():
          #assert(len(v) == len(set(v)))
          full_mapping[k] = sorted(set(v))
  
      if remaining_ids and cached_mapping_file:
          write_file(cached_mapping_file, simplejson.dumps(full_mapping))
      return requested_mapping