IGV - Load custom variant track
0
0
Entering edit mode
10 weeks ago
sadapas • 0

I am trying to learn how to integrate IGV in a React app and use a VCF created from a JSON (I will pull the variant data from various APIs) but right now I can load properly the track but the track is empty. I am using a placeholder VCF just to understand how to load and display properly a track and then I will create a script to turn the APIs json in a VCF

import React, { createRef, Component } from "react";
import { convertToVCF } from "../utils/vcfUtils";

const igvStyle = {
  fontFamily: "open sans, Helvetica, Arial, sans-serif",
  paddingTop: "60px",
  margin: "5px",
};

class IGVViewer extends Component {
  constructor(props) {
    super(props);
    this.container = createRef(null);
  }

  componentDidMount() {
    // Dynamically load IGV.js from a CDN
    const script = document.createElement("script");
    script.src = "https://cdn.jsdelivr.net/npm/igv@3.0.7/dist/igv.min.js";
    script.async = true;

    script.onload = () => {
      const { geneData, variants, type } = this.props;

      // Extract chromosome, start, and end from geneData
      const chromosome = geneData?.chromosomes?.[0] || "14"; // Default chromosome
      const start =
        geneData?.annotations?.[0]?.genomic_locations?.[0]?.genomic_range
          ?.begin || 33800027;
      const end =
        geneData?.annotations?.[0]?.genomic_locations?.[0]?.genomic_range
          ?.end || 33851710;

      // Ensure locus string matches IGV format: "chromosome:start-end"
      const locus = `${chromosome}:${start}-${end}`;

      // Default Genome ID (use placeholders for other types)
      let genomeID = "GCA_000002305.1"; // Default Genome ID
      if (type === "ROS_Cfam_1.0") {
        genomeID = "GCA_000002305.1"; // Genome ID for ROS_Cfam_1.0
      } else if (type === "CanFam3.1") {
        genomeID = "GCA_placeholder1"; // Genome ID for CanFam3.1
      } else if (type === "BROADD2") {
        genomeID = "GCA_placeholder2"; // Genome ID for BROADD2
      } else if (type === "Felis_catus_9.0") {
        genomeID = "GCA_placeholder3"; // Genome ID for Felis_catus_9.0
      } else if (type === "Felis_catus_6.2") {
        genomeID = "GCA_placeholder4"; // Genome ID for Felis_catus_6.2
      } else if (type === "EquCab3.0") {
        genomeID = "GCA_placeholder5"; // Genome ID for EquCab3.0
      } else if (type === "EquCab2") {
        genomeID = "GCA_placeholder6"; // Genome ID for EquCab2
      }

      // Define a list of track names to remove (configurable)
      const tracksToRemove = [
        "Augustus",
        "Sine",
        "Simple Repeats",
        "SINE",
        "RNA",
        "Other",
        "Satellite",
        "Simple",
        "LINE",
        "LTR",
        "Low Complexity",
        "CpG Islands",
      ];

      // Dynamically create VCF header with genome and locus information
      const vcfData = `
##fileformat=VCFv4.2
##fileDate=20241011
##source=EnsemblRESTAPI
##reference=file:///seq/references/${genomeID}
##contig=<ID=${chromosome},length=${end},assembly=${genomeID},md5=f126cd8f8a6e0c7f37f9d618ff66beb2da,species="Canis lupus familiaris",taxonomy=x>
##phasing=partial
##INFO=<ID=NS,Number=1,Type=Integer,Description="Number of Samples With Data">
##INFO=<ID=DP,Number=1,Type=Integer,Description="Total Depth">
##INFO=<ID=AF,Number=A,Type=Float,Description="Allele Frequency">
##INFO=<ID=AA,Number=1,Type=String,Description="Ancestral Allele">
##INFO=<ID=DB,Number=0,Type=Flag,Description="dbSNP membership">
##FILTER=<ID=q10,Description="Quality below 10">
##FILTER=<ID=s50,Description="Less than 50% of samples have data">
##FORMAT=<ID=GT,Number=1,Type=String,Description="Genotype">
##FORMAT=<ID=GQ,Number=1,Type=Integer,Description="Genotype Quality">
##FORMAT=<ID=DP,Number=1,Type=Integer,Description="Read Depth">
#CHROM  POS     ID        REF   ALT   QUAL   FILTER  INFO
14      33800027   rs6054257   A     G     29     PASS    NS=3;DP=14;AF=0.5
14      33810027   rs6040355   G     T     67     PASS    NS=3;DP=10;AF=0.333
14      33820027   rsTest123   T     C     50     PASS    NS=3;DP=9
`.trim(); // Trim the string to avoid extra spaces

      // IGV options, using GenArk genome reference and default locus
      const igvOptions = {
        genome: genomeID, // Use GenArk genome ID
        locus: locus,
        tracks: [], // No tracks initially
      };

      // Initialize IGV browser
      window.igv
        .createBrowser(this.container.current, igvOptions)
        .then((browser) => {
          console.log("IGV Viewer successfully loaded.", browser);

          // Ensure correct Base64 encoding of the VCF
          const vcfBase64 = btoa(unescape(encodeURIComponent(vcfData)));
          console.log("VCF Data (Base64):", vcfBase64);

          // Create a track from the Base64-encoded VCF
          const track = {
            name: "Kahl",
            format: "vcf",
            url: "data:text/plain;base64," + vcfBase64,
            indexed: false,
            type: "variant",
            displayMode: "EXPANDED", // Options: COLLAPSED, SQUISHED, EXPANDED
            color: "#FF0000", // You can choose a color for the variants
            height: 100, // Set a reasonable height for the track
          };

          // Load the track into IGV after the locus is set
          browser
            .search(locus)
            .then(() => {
              browser.loadTrack(track).then(() => {
                console.log("Kahl track successfully loaded.");

                // Now ensure the track removal happens after track loading is done
                setTimeout(() => {
                  tracksToRemove.forEach((trackName) => {
                    const trackToRemove = browser.tracks.find(
                      (track) => track.name === trackName
                    );
                    if (trackToRemove) {
                      console.log(`Removing ${trackName} track.`);
                      browser.removeTrack(trackToRemove);
                    }
                  });
                }, 1000); // Add a short delay to allow for all loading to complete
              });
            })
            .catch((error) => {
              console.error("Error setting locus or loading track:", error);
            });
        })
        .catch((error) => {
          console.error("Error loading IGV:", error);
        });
    };

    document.body.appendChild(script);
  }

  render() {
    return <div id="igv-div" ref={this.container} style={igvStyle}></div>;
  }
}

export default IGVViewer;

Also do I have to load all the tracks and then filter them out?

vcf igv react • 240 views
ADD COMMENT

Login before adding your answer.

Traffic: 1890 users visited in the last hour
Help About
FAQ
Access RSS
API
Stats

Use of this site constitutes acceptance of our User Agreement and Privacy Policy.

Powered by the version 2.3.6