text: from pprint import pprint as pp
  
  from scout.constants import SPIDEX_HUMAN
  
  
  def add_gene_links(gene_obj, build=37):
      """Update a gene object with links
  
      Args:
          gene_obj(dict)
          build(int)
  
      Returns:
          gene_obj(dict): gene_obj updated with many links
      """
      try:
          build = int(build)
      except (ValueError, TypeError) as err:
          build = 37
      # Add links that use the hgnc_id
      hgnc_id = gene_obj["hgnc_id"]
  
      gene_obj["hgnc_link"] = genenames(hgnc_id)
      gene_obj["omim_link"] = omim(hgnc_id)
      # Add links that use ensembl_id
      ensembl_id = gene_obj.get("common", {}).get("ensembl_id")
      if not ensembl_id:
          ensembl_id = gene_obj.get("ensembl_id")
  
      hgnc_symbol = gene_obj.get("common", {}).get("hgnc_symbol")
      if not hgnc_symbol:
          hgnc_symbol = gene_obj.get("hgnc_symbol")
  
      ensembl_37_link = ensembl(ensembl_id, build=37)
      ensembl_38_link = ensembl(ensembl_id, build=38)
      gene_obj["ensembl_37_link"] = ensembl_37_link
      gene_obj["ensembl_38_link"] = ensembl_38_link
      gene_obj["ensembl_link"] = ensembl_37_link
      if build == 38:
          gene_obj["ensembl_link"] = ensembl_38_link
      gene_obj["hpa_link"] = hpa(ensembl_id)
      gene_obj["string_link"] = string(ensembl_id)
      gene_obj["reactome_link"] = reactome(ensembl_id)
      gene_obj["clingen_link"] = clingen(hgnc_id)
      gene_obj["expression_atlas_link"] = expression_atlas(ensembl_id)
      gene_obj["exac_link"] = exac(ensembl_id)
      # Add links that use entrez_id
      gene_obj["entrez_link"] = entrez(gene_obj.get("entrez_id"))
      # Add links that use omim id
      gene_obj["omim_link"] = omim(gene_obj.get("omim_id"))
      # Add links that use hgnc_symbol
      gene_obj["ppaint_link"] = ppaint(hgnc_symbol)
      # Add links that use vega_id
      gene_obj["vega_link"] = vega(gene_obj.get("vega_id"))
      # Add links that use ucsc link
      gene_obj["ucsc_link"] = ucsc(gene_obj.get("ucsc_id"))
      gene_obj["genemania_link"] = genemania(hgnc_symbol)
  
  
  def genemania(hgnc_symbol):
      link = "https://genemania.org/search/homo-sapiens/{}/"
      if not hgnc_symbol:
          return None
      return link.format(hgnc_symbol)
  
  
  def genenames(hgnc_id):
      link = "https://www.genenames.org/cgi-bin/gene_symbol_report?hgnc_id=HGNC:{}"
      if not hgnc_id:
          return None
      return link.format(hgnc_id)
  
  
  def omim(omim_id):
      link = "https://www.omim.org/entry/{}"
      if not omim_id:
          return None
      return link.format(omim_id)
  
  
  def ensembl(ensembl_id, build=37):
  
      link = "http://grch37.ensembl.org/Homo_sapiens/Gene/Summary?db=core;g={}"
      if build == 38:
          link = "http://ensembl.org/Homo_sapiens/Gene/Summary?db=core;g={}"
      if not ensembl_id:
          return None
  
      return link.format(ensembl_id)
  
  
  def exac(ensembl_id):
  
      link = "http://exac.broadinstitute.org/gene/{}"
      if not ensembl_id:
          return None
  
      return link.format(ensembl_id)
  
  
  def hpa(ensembl_id):
      link = "http://www.proteinatlas.org/search/{}"
  
      if not ensembl_id:
          return None
  
      return link.format(ensembl_id)
  
  
  def string(ensembl_id):
      link = "http://string-db.org/newstring_cgi/show_network_" "section.pl?identifier={}"
  
      if not ensembl_id:
          return None
  
      return link.format(ensembl_id)
  
  
  def reactome(ensembl_id):
      link = (
          "http://www.reactome.org/content/query?q={}&species=Homo+sapiens"
          "&species=Entries+without+species&cluster=true"
      )
      if not ensembl_id:
          return None
  
      return link.format(ensembl_id)
  
  
  def clingen(hgnc_id):
      link = "https://search.clinicalgenome.org/kb/genes/HGNC:{}"
      if not hgnc_id:
          return None
      return link.format(hgnc_id)
  
  
  def expression_atlas(ensembl_id):
      link = "https://www.ebi.ac.uk/gxa/genes/{}"
      if not ensembl_id:
          return None
  
      return link.format(ensembl_id)
  
  
  def entrez(entrez_id):
      link = "https://www.ncbi.nlm.nih.gov/gene/{}"
  
      if not entrez_id:
          return None
  
      return link.format(entrez_id)
  
  
  def ppaint(hgnc_symbol):
      link = "https://pecan.stjude.cloud/proteinpaint/{}"
  
      if not hgnc_symbol:
          return None
  
      return link.format(hgnc_symbol)
  
  
  def vega(vega_id):
      link = "http://vega.archive.ensembl.org/Homo_sapiens/Gene/Summary?db=core;g=OTTHUMG00000018506{}"
  
      if not vega_id:
          return None
  
      return link.format(vega_id)
  
  
  def ucsc(ucsc_id):
  
      link = (
          "http://genome.cse.ucsc.edu/cgi-bin/hgGene?org=Human&hgg_chrom=none&hgg_type=knownGene"
          "&hgg_gene={}"
      )
  
      if not ucsc_id:
          return None
  
      return link.format(ucsc_id)
  
  
  def add_tx_links(tx_obj, build=37):
      try:
          build = int(build)
      except ValueError:
          build = 37
  
      ensembl_id = tx_obj.get("ensembl_transcript_id", tx_obj.get("transcript_id"))
      ensembl_37_link = ensembl_tx(ensembl_id, 37)
      ensembl_38_link = ensembl_tx(ensembl_id, 38)
  
      tx_obj["ensembl_37_link"] = ensembl_37_link
      tx_obj["ensembl_38_link"] = ensembl_38_link
      tx_obj["ensembl_link"] = ensembl_37_link
      if build == 38:
          tx_obj["ensembl_link"] = ensembl_38_link
  
      refseq_links = []
      if tx_obj.get("refseq_id"):
          refseq_id = tx_obj["refseq_id"]
          refseq_links.append({"link": refseq(refseq_id), "id": refseq_id})
      tx_obj["refseq_links"] = refseq_links
      tx_obj["swiss_prot_link"] = swiss_prot(tx_obj.get("swiss_prot"))
      tx_obj["pfam_domain_link"] = pfam(tx_obj.get("pfam_domain"))
      tx_obj["prosite_profile_link"] = prosite(tx_obj.get("prosite_profile"))
      tx_obj["smart_domain_link"] = smart(tx_obj.get("smart_domain"))
  
      return tx_obj
  
  
  ##  Transcript links
  def refseq(refseq_id):
      link = "http://www.ncbi.nlm.nih.gov/nuccore/{}"
      if not refseq_id:
          return None
  
      return link.format(refseq_id)
  
  
  def ensembl_tx(ens_tx_id, build=37):
      link = "http://grch37.ensembl.org/Homo_sapiens/" "Gene/Summary?t={}"
  
      if build == 38:
          link = "http://ensembl.org/Homo_sapiens/" "Gene/Summary?t={}"
      if not ens_tx_id:
          return None
  
      return link.format(ens_tx_id)
  
  
  def swiss_prot(swiss_prot_id):
      link = "http://www.uniprot.org/uniprot/{}"
  
      if not swiss_prot_id:
          return None
  
      return link.format(swiss_prot_id)
  
  
  def pfam(pfam_domain):
      link = "http://pfam.xfam.org/family/{}"
  
      if not pfam_domain:
          return None
  
      return link.format(pfam_domain)
  
  
  def prosite(prosat_profile):
      link = "http://prosite.expasy.org/cgi-bin/prosite/" "prosite-search-ac?{}"
      if not prosat_profile:
          return None
  
      return link.format(prosat_profile)
  
  
  def smart(smart_domain):
      link = "http://smart.embl.de/smart/search.cgi?keywords={}"
  
      if not smart_domain:
          return None
  
      return link.format(smart_domain)
  
  
  ############# Variant links ####################
  
  
  def get_variant_links(variant_obj, build=None):
      """Update a variant object with links
  
      Args:
          variant_obj(scout.models.Variant)
          build(int)
  
      Returns:
          links(dict): The variant links
      """
      try:
          build = int(build)
      except (ValueError, TypeError) as err:
          build = 37
      links = dict(
          thousandg_link=thousandg_link(variant_obj, build),
          exac_link=exac_link(variant_obj),
          gnomad_link=gnomad_link(variant_obj),
          swegen_link=swegen_link(variant_obj),
          cosmic_link=cosmic_link(variant_obj),
          beacon_link=beacon_link(variant_obj, build),
          ucsc_link=ucsc_link(variant_obj, build),
          alamut_link=alamut_link(variant_obj),
          spidex_human=spidex_human(variant_obj),
      )
      return links
  
  
  def thousandg_link(variant_obj, build=None):
      """Compose link to 1000G page for detailed information."""
      dbsnp_id = variant_obj.get("dbsnp_id")
      build = build or 37
  
      if not dbsnp_id:
          return None
  
      if build == 37:
          url_template = (
              "http://grch37.ensembl.org/Homo_sapiens/Variation/Explore"
              "?v={};vdb=variation"
          )
      else:
          url_template = (
              "http://www.ensembl.org/Homo_sapiens/Variation/Explore"
              "?v={};vdb=variation"
          )
  
      return url_template.format(dbsnp_id)
  
  
  def exac_link(variant_obj):
      """Compose link to ExAC website for a variant position."""
      url_template = (
          "http://exac.broadinstitute.org/variant/"
          "{this[chromosome]}-{this[position]}-{this[reference]}"
          "-{this[alternative]}"
      )
      return url_template.format(this=variant_obj)
  
  
  def gnomad_link(variant_obj):
      """Compose link to gnomAD website."""
      url_template = (
          "http://gnomad.broadinstitute.org/variant/{this[chromosome]}-"
          "{this[position]}-{this[reference]}-{this[alternative]}"
      )
      return url_template.format(this=variant_obj)
  
  
  def swegen_link(variant_obj):
      """Compose link to SweGen Variant Frequency Database."""
      url_template = (
          "https://swegen-exac.nbis.se/variant/{this[chromosome]}-"
          "{this[position]}-{this[reference]}-{this[alternative]}"
      )
      return url_template.format(this=variant_obj)
  
  
  def cosmic_link(variant_obj):
      """Compose link to COSMIC Database.
  
      Args:
          variant_obj(scout.models.Variant)
  
      Returns:
          url_template(str): Link to COSMIIC database if cosmic id is present
      """
  
      cosmic_ids = variant_obj.get("cosmic_ids")
  
      if not cosmic_ids:
          return None
      else:
          cosmic_id = cosmic_ids[0]
          url_template = "https://cancer.sanger.ac.uk/cosmic/mutation/overview?id={}"
  
      return url_template.format(cosmic_id)
  
  
  def beacon_link(variant_obj, build=None):
      """Compose link to Beacon Network."""
      build = build or 37
      url_template = (
          "https://beacon-network.org/#/search?pos={this[position]}&"
          "chrom={this[chromosome]}&allele={this[alternative]}&"
          "ref={this[reference]}&rs=GRCh37"
      )
      # beacon does not support build 38 at the moment
      # if build == '38':
      #     url_template = ("https://beacon-network.org/#/search?pos={this[position]}&"
      #                     "chrom={this[chromosome]}&allele={this[alternative]}&"
      #                     "ref={this[reference]}&rs=GRCh38")
  
      return url_template.format(this=variant_obj)
  
  
  def ucsc_link(variant_obj, build=None):
      """Compose link to UCSC."""
      build = build or 37
      url_template = (
          "http://genome.ucsc.edu/cgi-bin/hgTracks?db=hg19&"
          "position=chr{this[chromosome]}:{this[position]}"
          "-{this[position]}&dgv=pack&knownGene=pack&omimGene=pack"
      )
      if build == 38:
          url_template = (
              "http://genome.ucsc.edu/cgi-bin/hgTracks?db=hg20&"
              "position=chr{this[chromosome]}:{this[position]}"
              "-{this[position]}&dgv=pack&knownGene=pack&omimGene=pack"
          )
  
      return url_template.format(this=variant_obj)
  
  
  def alamut_link(variant_obj):
      url_template = (
          "http://localhost:10000/show?request={this[chromosome]}:"
          "{this[position]}{this[reference]}>{this[alternative]}"
      )
      return url_template.format(this=variant_obj)
  
  
  def spidex_human(variant_obj):
      """Translate SPIDEX annotation to human readable string."""
      if variant_obj.get("spidex") is None:
          return "not_reported"
      elif abs(variant_obj["spidex"]) < SPIDEX_HUMAN["low"]["pos"][1]:
          return "low"
      elif abs(variant_obj["spidex"]) < SPIDEX_HUMAN["medium"]["pos"][1]:
          return "medium"
      else:
          return "high"
  