docs: def main():
  
      """
      Zebrafish:
          1. Map ENSP to ZFIN Ids using Intermine
          2. Map deprecated ENSP IDs to ensembl genes
             by querying the ensembl database then use
             intermine to resolve to gene IDs
      Mouse: Map deprecated ENSP IDs to ensembl genes
             by querying the ensembl database then use
             intermine to resolve to MGI IDs
      Fly: ENSP IDs appear as xrefs on translation IDs
      Worm: Use UniProt Mapping file provided by String
      """
  
      parser = argparse.ArgumentParser(usage=__doc__)
      parser.add_argument('--config', '-c', required=True, help='JSON configuration file')
      parser.add_argument('--out', '-o', required=False, help='output directory', default="./")
      parser.add_argument('--use_cache', '-cached', action="store_true",
                          required=False, help='use cached files', default=False)
      args = parser.parse_args()
  
      # Hardcoded dir for raw files
      out_path = Path(args.out)
      raw_dir = out_path / "out"
      raw_dir.mkdir(parents=True, exist_ok=True)
  
      # Hardcoded unmapped file
  
      VERSION = 'v10.5'
      STRING_BASE = "http://string-db.org/download/" \
                    "protein.links.detailed.{}".format(VERSION)
  
      config_file = open(args.config, 'r')
      config = yaml.load(config_file)
      config_file.close()
  
      out_unmapped_file = out_path / "unmapped_ids.tsv"
      unmapped_file = out_unmapped_file.open("w")
  
      # Connect to ensembl
      connection = connect_to_database(host=config['database']['host'],
                                       username=config['database']['username'],
                                       port=config['database']['port'])
  
      cursor = connection.cursor()
  
      # Process MGI eqs #
      ####################
      taxon = config['taxa_specific']['mouse']['tax_id']
  
      # IO
      dump_file = raw_dir / '{}.protein.links.detailed.{}.txt.gz' \
          .format(taxon, VERSION)
  
      mouse_map_file = out_path / config['taxa_specific']['mouse']['output_file']
      mouse_file = mouse_map_file.open('w')
  
      path = '{}/{}.protein.links.detailed.{}.txt.gz' \
          .format(STRING_BASE, taxon, VERSION)
      if not args.use_cache:
          download_file(path, dump_file)
  
      ensembl = Ensembl("rdf_graph", True)
      p2gene_map = ensembl.fetch_protein_gene_map(taxon)
  
      fh = gzip.open(str(dump_file), 'rb')
      df = pd.read_csv(fh, sep='\s+')
      fh.close()
      proteins = pd.unique(df[['protein1', 'protein2']].values.ravel())
      logger.info("Processing {} proteins".format(len(proteins)))
      for protein in proteins:
          prot = protein.replace('{}.'.format(str(taxon)), '')
          try:
              ens_gene = p2gene_map[prot]
              ens_curie = "ENSEMBL:{}".format(ens_gene)
              mouse_file.write("{}\t{}\n".format(prot, ens_curie))
              continue
          except KeyError:
              pass
  
          ens_gene = get_deprecated_protein_gene_rel(
              cursor, prot, config['taxa_specific']['mouse']['ensembl'],
              config)
          intermine_resp = query_mousemine(
              config['taxa_specific']['mouse']['intermine'], ens_gene)
          if intermine_resp.is_successful:
              mouse_file.write("{}\t{}\n".format(prot, intermine_resp.gene_id))
          else:
              unmapped_file.write("{}\t{}\t{}\n".format(prot, ens_gene, taxon))
  
      mouse_file.close()
  
      # Process Fly eqs #
      ####################
      taxon = config['taxa_specific']['fly']['tax_id']
  
      # IO
      dump_file = raw_dir / '{}.protein.links.detailed.{}.txt.gz' \
          .format(taxon, VERSION)
  
      fly_map_file = out_path / config['taxa_specific']['fly']['output_file']
      fly_file = fly_map_file.open('w')
  
      path = '{}/{}.protein.links.detailed.{}.txt.gz' \
          .format(STRING_BASE, taxon, VERSION)
      if not args.use_cache:
          download_file(path, dump_file)
  
      ensembl = Ensembl("rdf_graph", True)
      p2gene_map = ensembl.fetch_protein_gene_map(taxon)
  
      fh = gzip.open(str(dump_file), 'rb')
      df = pd.read_csv(fh, sep='\s+')
      fh.close()
      proteins = pd.unique(df[['protein1', 'protein2']].values.ravel())
      logger.info("Processing {} proteins".format(len(proteins)))
      for protein in proteins:
          prot = protein.replace('{}.'.format(str(taxon)), '')
          try:
              ens_gene = p2gene_map[prot]
              ens_curie = "ENSEMBL:{}".format(ens_gene)
              fly_file.write("{}\t{}\n".format(prot, ens_curie))
              continue
          except KeyError:
              pass
  
          ens_gene = get_xref_protein_gene_rel(
              cursor, prot, config['taxa_specific']['fly']['ensembl'],
              config, taxon)
  
          if ens_gene is not None:
              fly_file.write("{}\t{}\n".format(prot, "ENSEMBL:{}".format(ens_gene)))
          else:
              unmapped_file.write("{}\t{}\t{}\n".format(prot, '', taxon))
  
      fly_file.close()
  
      # Process Worm eqs #
      ####################
      taxon = config['taxa_specific']['worm']['tax_id']
  
      # IO
      dump_file = raw_dir / '{}.protein.links.detailed.{}.txt.gz' \
          .format(taxon, VERSION)
  
      uniprot_file = raw_dir / config['taxa_specific']['worm']['uniprot_file']
  
      worm_map_file = out_path / config['taxa_specific']['worm']['output_file']
      worm_file = worm_map_file.open('w')
  
      path = '{}/{}.protein.links.detailed.{}.txt.gz' \
          .format(STRING_BASE, taxon, VERSION)
      if not args.use_cache:
          download_file(path, dump_file)
          download_file(config['taxa_specific']['worm']['uniprot_mappings'],
                        uniprot_file)
  
      ensembl = Ensembl("rdf_graph", True)
      p2gene_map = ensembl.fetch_protein_gene_map(taxon)
      uni2gene_map = ensembl.fetch_uniprot_gene_map(taxon)
  
      fh = gzip.open(str(uniprot_file), 'rb')
      df = pd.read_csv(fh, sep='\s+')
      fh.close()
      string_uniprot_map = {}
      for index, row in df.iterrows():
          uniprot_ac = row['uniprot_ac|uniprot_id'].split('|')[0]
          string_uniprot_map[row['string_id']] = uniprot_ac
  
      fh = gzip.open(str(dump_file), 'rb')
      df = pd.read_csv(fh, sep='\s+')
      fh.close()
      proteins = pd.unique(df[['protein1', 'protein2']].values.ravel())
      logger.info("Processing {} proteins".format(len(proteins)))
      for protein in proteins:
          prot = protein.replace('{}.'.format(str(taxon)), '')
          try:
              ens_gene = p2gene_map[prot]
              ens_curie = "ENSEMBL:{}".format(ens_gene)
              worm_file.write("{}\t{}\n".format(prot, ens_curie))
              continue
          except KeyError:
              pass
  
          try:
              uniprot_ac = string_uniprot_map[prot]
              ens_gene = uni2gene_map[uniprot_ac]
              ens_curie = "ENSEMBL:{}".format(ens_gene)
              worm_file.write("{}\t{}\n".format(prot, ens_curie))
              continue
          except KeyError:
              pass
  
          unmapped_file.write("{}\t{}\t{}\n".format(prot, '', taxon))
  
      worm_file.close()
  
      # Process ZFIN eqs #
      ####################
      taxon = config['taxa_specific']['zebrafish']['tax_id']
  
      # IO
      dump_file = raw_dir / '{}.protein.links.detailed.{}.txt.gz' \
          .format(taxon, VERSION)
  
      zfin_map_file = out_path / config['taxa_specific']['zebrafish']['output_file']
      zfin_file = zfin_map_file.open('w')
  
      path = '{}/{}.protein.links.detailed.{}.txt.gz' \
          .format(STRING_BASE, taxon, VERSION)
      if not args.use_cache:
          download_file(path, dump_file)
  
      ensembl = Ensembl("rdf_graph", True)
      p2gene_map = ensembl.fetch_protein_gene_map(taxon)
  
      # in 3.6 gzip accepts Paths
      fh = gzip.open(str(dump_file), 'rb')
      df = pd.read_csv(fh, sep='\s+')
      fh.close()
      proteins = pd.unique(df[['protein1', 'protein2']].values.ravel())
      logger.info("Processing {} proteins".format(len(proteins)))
      for protein in proteins:
          prot = protein.replace('{}.'.format(str(taxon)), '')
          try:
              ens_gene = p2gene_map[prot]
              ens_curie = "ENSEMBL:{}".format(ens_gene)
              zfin_file.write("{}\t{}\n".format(prot, ens_curie))
              continue
          except KeyError:
              pass
  
          intermine_resp = query_fishmine(
              config['taxa_specific']['zebrafish']['intermine'], prot)
          if intermine_resp.is_successful:
              zfin_file.write("{}\t{}\n".format(prot, intermine_resp.gene_id))
              continue
  
          ens_gene = get_deprecated_protein_gene_rel(
              cursor, prot, config['taxa_specific']['zebrafish']['ensembl'],
              config)
          intermine_resp = query_fishmine(
              config['taxa_specific']['zebrafish']['intermine'], ens_gene)
          if intermine_resp.is_successful:
              zfin_file.write("{}\t{}\n".format(prot, intermine_resp.gene_id))
              continue
  
          intermine_resp = query_fishmine(
              config['taxa_specific']['zebrafish']['intermine'],
              ens_gene, "Pseudogene")
          if intermine_resp.is_successful:
              zfin_file.write("{}\t{}\n".format(prot, intermine_resp.gene_id))
          else:
              unmapped_file.write("{}\t{}\t{}\n".format(prot, ens_gene, taxon))
  
      zfin_file.close()
  
      unmapped_file.close()
      connection.close()
  
      logger.info("ID Map Finished")