Skip to content

Commit

Permalink
Export ucsc HUB class
Browse files Browse the repository at this point in the history
Add method to extract all loadable track configurations for web-app menu
  • Loading branch information
jrobinso committed Oct 24, 2023
1 parent 4486c57 commit 78fbc73
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 69 deletions.
6 changes: 2 additions & 4 deletions dev/ucsc/hub.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,10 @@


const hubOptions = {
url: "https://hgdownload.soe.ucsc.edu/hubs/GCA/018/471/515/GCA_018471515.1/hub.txt",
includeTracks: "all"
includeTracks: true
}


const hub = await Hub.loadHub(hubOptions)
const hub = await Hub.loadHub("https://hgdownload.soe.ucsc.edu/hubs/GCA/018/471/515/GCA_018471515.1/hub.txt", hubOptions)
const ref = hub.getGenomeConfig()

const igvConfig = {
Expand Down
5 changes: 2 additions & 3 deletions dev/ucsc/slowHub.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,11 @@


const hubOptions = {
url: "https://hgdownload.soe.ucsc.edu/hubs/GCA/004/027/145/GCA_004027145.1/hub.txt",
includeTracks: "all"
includeTracks: true
}


const hub = await Hub.loadHub(hubOptions)
const hub = await Hub.loadHub("https://hgdownload.soe.ucsc.edu/hubs/GCA/004/027/145/GCA_004027145.1/hub.txt", hubOptions)

const igvConfig = {
showChromosomeWidget: false,
Expand Down
6 changes: 3 additions & 3 deletions js/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ class Browser {
return new XMLSession(string, knownGenomes)

} else if (filename.endsWith("hub.txt")) {
const hub = await Hub.loadHub(options)
const hub = await Hub.loadHub(urlOrFile, options)
if(chromosomeSelectWidget) {
chromosomeSelectWidget.hide()
}
Expand Down Expand Up @@ -763,7 +763,7 @@ class Browser {

let genomeConfig
if (idOrConfig.url && StringUtils.isString(idOrConfig.url) && idOrConfig.url.endsWith("/hub.txt")) {
const hub = await Hub.loadHub(idOrConfig)
const hub = await Hub.loadHub(idOrConfig.url, idOrConfig)
genomeConfig = hub.getGenomeConfig("genes")
} else {
genomeConfig = idOrConfig //await GenomeUtils.expandReference(this.alert, idOrConfig)
Expand Down Expand Up @@ -793,7 +793,7 @@ class Browser {
*/
async loadTrackHub(options) {

const hub = await Hub.loadHub(options)
const hub = await Hub.loadHub(options.url, options)
const genomeConfig = hub.getGenomeConfig()
const initialLocus = hub.getDefaultPosition()
if (initialLocus) {
Expand Down
4 changes: 3 additions & 1 deletion js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {registerFileFormats} from "./util/trackUtils.js"
import {igvxhr} from "../node_modules/igv-utils/src/index.js"
import {registerTrackClass, registerTrackCreatorFunction} from "./trackFactory.js"
import TrackBase from "./trackBase.js"
import Hub from "./ucsc/ucscHub.js"

const setApiKey = igvxhr.setApiKey

Expand Down Expand Up @@ -45,6 +46,7 @@ export default {
TrackBase,
registerTrackClass,
registerTrackCreatorFunction,
registerFileFormats
registerFileFormats,
Hub
}

20 changes: 11 additions & 9 deletions js/jbrowse/circularViewUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,15 +149,17 @@ const makeVCFChords = (features) => {
function makeCircViewChromosomes(genome) {
const regions = []
const colors = []
for (let chrName of genome.wgChromosomeNames) {
const chr = genome.getChromosome(chrName)
colors.push(getChrColor(chr.name))
regions.push(
{
name: chr.name,
bpLength: chr.bpLength
}
)
if(genome.wgChromosomeNames) {
for (let chrName of genome.wgChromosomeNames) {
const chr = genome.getChromosome(chrName)
colors.push(getChrColor(chr.name))
regions.push(
{
name: chr.name,
bpLength: chr.bpLength
}
)
}
}
return regions
}
Expand Down
83 changes: 58 additions & 25 deletions js/ucsc/ucscHub.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,28 @@ import {igvxhr} from "../../node_modules/igv-utils/src/index.js"

class Hub {

static async loadHub(options) {

if (!options.url) {
throw Error("Expected url")
}
static supportedTypes = new Set(["bigBed", "bigWig", "bigGenePred"])
static filterTracks = new Set(["cytoBandIdeo", "assembly", "gap", "gapOverlap", "allGaps",
"cpgIslandExtUnmasked", "windowMasker"])

const stanzas = await loadStanzas(options)
static async loadHub(url, options) {

const stanzas = await loadStanzas(url, options)
let groups
if ("genome" === stanzas[1].type) {
const genome = stanzas[1]
if (genome.hasProperty("groups")) {
const idx = options.url.lastIndexOf("/")
const baseURL = options.url.substring(0, idx + 1)
const idx = url.lastIndexOf("/")
const baseURL = url.substring(0, idx + 1)
const groupsTxtURL = baseURL + genome.getProperty("groups")
groups = await loadStanzas({url: groupsTxtURL})
groups = await loadStanzas(groupsTxtURL)
}
}
return new Hub(options.url, stanzas, groups)
return new Hub(url, stanzas, groups)
}

static supportedTypes = new Set(["bigBed", "bigWig", "bigGenePred"])
static filterTracks = new Set(["cytoBandIdeo", "assembly", "gap", "gapOverlap", "allGaps",
"cpgIslandExtUnmasked", "windowMasker"])

constructor(url, stanzas, groups) {
constructor(url, stanzas, groupStanzas) {

const idx = url.lastIndexOf("/")
this.baseURL = url.substring(0, idx + 1)
Expand Down Expand Up @@ -69,21 +65,60 @@ class Hub {
}
}

if (groups) {
if (groupStanzas) {
this.groupStanzas = groupStanzas
this.groupPriorityMap = new Map()
for (let g of groups) {
for (let g of groupStanzas) {
if (g.hasProperty("priority")) {
this.groupPriorityMap.set(g.getProperty("name"), Number.parseInt(g.getProperty("priority")) * 10)
}
}
this.groupPriorities = new Map()
}
}

getDefaultPosition() {
return this.genomeStanza.getProperty("defaultPos")
}

getTrackConfigurations() {

// Organize track configs by group
const trackConfigMap = new Map()
for (let c of this.#getTracksConfigs()) {
const name = c.group || "other"
if (trackConfigMap.has(name)) {
trackConfigMap.get(name).push(c)
} else {
trackConfigMap.set(name, [c])
}
}

// Build group structure
const t = []
if (this.groupStanzas) {
for (let g of this.groupStanzas) {
const groupName = g.getProperty("name")
if(trackConfigMap.has(groupName)) {
t.push(
{
label: g.getProperty("label"),
tracks: trackConfigMap.get(g.getProperty("name"))
}
)
}
}
}

if(trackConfigMap.has("other")) {
t.push({
label: "other",
tracks: trackConfigMap.get("other")
})
}

return t
}

/* Example genome stanza
genome GCF_000186305.1
taxId 176946
Expand Down Expand Up @@ -161,7 +196,7 @@ isPcr dynablat-01.soe.ucsc.edu 4040 dynamic GCF/000/186/305/GCF_000186305.1

// Tracks. To prevent loading tracks set `includeTracks`to false
if (includeTracks) {
config.tracks = this.#getTracksConfigs(includeTracks)
config.tracks = this.#getTracksConfigs(Hub.filterTracks)
}

return config
Expand All @@ -170,14 +205,12 @@ isPcr dynablat-01.soe.ucsc.edu 4040 dynamic GCF/000/186/305/GCF_000186305.1
/**
* Return collection of igv track config object, organized by "group*
*/
#getTracksConfigs(group) {
#getTracksConfigs(filter) {
return this.trackStanzas.filter(t => {
return t.getProperty("visibility") !== "hide" &&
Hub.supportedTypes.has(t.format) &&
!Hub.filterTracks.has(t.name) &&
t.hasProperty("bigDataUrl") &&
("all" === group || group === t.getProperty("group"))

(!filter || !Hub.filterTracks.has(t.name) &&
t.hasProperty("bigDataUrl"))
})
.map(t => this.#getTrackConfig(t))
}
Expand Down Expand Up @@ -353,9 +386,9 @@ class Stanza {
* @param url
* @returns {Promise<*[]>}
*/
async function loadStanzas(options) {
async function loadStanzas(url, options) {

const data = await igvxhr.loadString(options.url)
const data = await igvxhr.loadString(url)
const lines = data.split(/\n|\r\n|\r/g)

const nodes = []
Expand Down
47 changes: 47 additions & 0 deletions test/testHubs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import "./utils/mockObjects.js"
import {assert} from 'chai'
import Hub from "../js/ucsc/ucscHub.js"
import Trix from "../js/bigwig/trix.js"
import BWReader from "../js/bigwig/bwReader.js"
import BPTree from "../js/bigwig/bpTree.js"
import {isString} from "../node_modules/igv-utils/src/stringUtils.js"


suite("hub.txt", function () {


test("genome", async function () {

const hub = await Hub.loadHub("test/data/hubs/hub.txt")
assert.ok(hub.hub)
assert.ok(hub.genomeStanza)
assert.equal(22, hub.trackStanzas.length)

const genomeConfig = hub.getGenomeConfig()
//const genome = await Genome.loadGenome(genomeConfig)

assert.ok(genomeConfig)
assert.equal("GCF_000186305.1", genomeConfig.id)
assert.equal("Python bivittatus", genomeConfig.name)
assert.ok(genomeConfig.twoBitBptURL)
assert.ok(genomeConfig.twoBitURL)
assert.ok(genomeConfig.chromAliasBbURL)
assert.ok(genomeConfig.cytobandBbURL)
})

test("track configs", async function () {

const hub = await Hub.loadHub("test/data/hubs/hub.txt")
assert.ok(hub.hub)
assert.ok(hub.genomeStanza)
assert.equal(22, hub.trackStanzas.length)

const trackConfigs = hub.getTrackConfigurations()

assert.ok(trackConfigs.length > 0)

})


})

24 changes: 0 additions & 24 deletions test/testUCSC.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,10 @@ import {assert} from 'chai'
import Hub from "../js/ucsc/ucscHub.js"
import Trix from "../js/bigwig/trix.js"
import BWReader from "../js/bigwig/bwReader.js"
import BPTree from "../js/bigwig/bpTree.js"
import {isString} from "../node_modules/igv-utils/src/stringUtils.js"


suite("ucsc utilities", function () {


test("hub.txt", async function () {

this.timeout(200000)

const hub = await Hub.loadHub({url: "test/data/hubs/hub.txt"})
assert.ok(hub.hub)
assert.ok(hub.genomeStanza)
assert.equal(22, hub.trackStanzas.length)

const genomeConfig = hub.getGenomeConfig()
//const genome = await Genome.loadGenome(genomeConfig)

assert.ok(genomeConfig)
assert.equal("GCF_000186305.1", genomeConfig.id)
assert.equal("Python bivittatus", genomeConfig.name)
assert.ok(genomeConfig.twoBitBptURL)
assert.ok(genomeConfig.twoBitURL)
assert.ok(genomeConfig.chromAliasBbURL)
assert.ok(genomeConfig.cytobandBbURL)
})

test("trix", async function () {

this.timeout(200000)
Expand Down

0 comments on commit 78fbc73

Please sign in to comment.