Skip to content

Commit

Permalink
shoebox updates
Browse files Browse the repository at this point in the history
  • Loading branch information
jrobinso committed Oct 12, 2024
1 parent 78aec24 commit 195de66
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 75 deletions.
88 changes: 88 additions & 0 deletions js/shoebox/shoeboxColorScale.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2016-2017 The Regents of the University of California
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
* following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/

import {IGVMath} from "../../node_modules/igv-utils/src/index.js"

const defaultColorScaleConfig = {min: 0, max: 3000, color: "rgb(0,0,255)"}

class ShoeboxColorScale {

constructor(scale) {

scale = scale || defaultColorScaleConfig
this.max = scale.max
this.min = scale.min || 0
this.cache = []
this.nbins = 1000
this.binsize = (this.max - this.min) / this.nbins
this.updateColor(scale.color || "rgb(0,0,255)")

}
updateColor(color) {
const comps = color.substring(4).replace(")", "").split(",")
if (comps.length === 3) {
this.r = Number.parseInt(comps[0].trim())
this.g = Number.parseInt(comps[1].trim())
this.b = Number.parseInt(comps[2].trim())
}
}

setMinMax(min, max) {
this.min = min
this.max = max
this.cache = []
this.binsize = (this.max - this.min) / this.nbins
}

getColor(value) {
const low = 0
if (value < this.min) return "white"

const bin = Math.floor((Math.min(this.max, value) - this.min) / this.binsize)
if (undefined === this.cache[bin]) {
const alpha = (IGVMath.clamp(value, low, this.max) - low) / (this.max - low)
this.cache[bin] = `rgba(${this.r},${this.g},${this.b}, ${alpha})`
}
return this.cache[bin]
}

stringify() {
return "" + this.min + "," + this.max + ',' + `rgb(${this.r},${this.g},${this.b})`
}

static parse(string) {

const tokens = str.split(",")

const cs = {
min: Number.parseFloat(tokens[0]),
max: Number.parseFloat(tokens[1]),
color: tokens[2]
}
return new ShoeboxColorScale(cs)
}

}


export default ShoeboxColorScale
120 changes: 47 additions & 73 deletions js/feature/shoeboxTrack.js → js/shoebox/shoeboxTrack.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,8 @@
import $ from "../vendor/jquery-3.3.1.slim.js"
import FeatureSource from './featureSource.js'
import FeatureSource from "../feature/featureSource.js"
import TrackBase from "../trackBase.js"
import IGVGraphics from "../igv-canvas.js"
import {IGVMath} from "../../node_modules/igv-utils/src/index.js"
import {createCheckbox} from "../igv-icons.js"
import {GradientColorScale} from "../util/colorScale.js"
import {ColorTable} from "../util/colorPalletes.js"
import SampleInfo from "../sample/sampleInfo.js"
import HicColorScale from "../hic/hicColorScale.js"
import ShoeboxSource from "../hic/shoeboxSource.js"
import {doSortByAttributes} from "../sample/sampleUtils.js"
import ShoeboxColorScale from "./shoeboxColorScale.js"


class ShoeboxTrack extends TrackBase {
Expand All @@ -18,7 +11,6 @@ class ShoeboxTrack extends TrackBase {
height: 300,
rowHeight: 3,
max: 3000,
color: "rgb(0,0,255)"
}

constructor(config, browser) {
Expand Down Expand Up @@ -57,49 +49,58 @@ class ShoeboxTrack extends TrackBase {
// Must do the following after setting track properties as they can be overriden via a track line

// Color settings
const max = this.dataRange.max
let r = 0;
let g = 0;
let b = 0;
if(this.color && this.color.startsWith("rgb(")) {
const comps = this.color.substring(4).replace(")","").split(",")
if(comps.length === 3) {
r = Number.parseInt(comps[0].trim())
g = Number.parseInt(comps[1].trim())
b = Number.parseInt(comps[2].trim())
}
if (this.config.colorScale) {
this.colorScale = ShoeboxColorScale.parse(this.config.colorScale)
} else {
const min = this.dataRange.min
const max = this.dataRange.max
this.colorScale = new ShoeboxColorScale({min, max, color: this.color})
}
this.colorScale = new HicColorScale({threshold: max, r,g,b})
}

get color() {
return this._color || "rgb(0,0,255)"
}

set color(color) {
this._color = color
if (this.colorScale) {
this.colorScale.updateColor(color)
}
}

menuItemList() {

const menuItems = []

if (this.colorScale) {
menuItems.push('<hr/>')

function dialogPresentationHandler(e) {
this.browser.inputDialog.present({
label: 'Color Scale Threshold',
value: this.colorScale.threshold,
callback: () => {
const t = Number(this.browser.inputDialog.value, 10)
if (t) {
this.colorScale.setThreshold(t)
this.trackView.repaintViews()
}
}
}, e)
}

menuItems.push({object: $('<div>Set color scale threshold</div>'), dialog: dialogPresentationHandler})
menuItems.push('<hr/>')

// Data range
let object = $('<div>')
object.text('Set data range')

function dialogPresentationHandler() {

if (this.trackView.track.selected) {
this.browser.dataRangeDialog.configure(this.trackView.browser.getSelectedTrackViews())
} else {
this.browser.dataRangeDialog.configure(this.trackView)
}
this.browser.dataRangeDialog.present($(this.browser.columnContainer))
}

menuItems.push({object, dialog: dialogPresentationHandler})

return menuItems
}

setDataRange({min, max}) {
this.dataRange.min = min
this.dataRange.max = max
this.colorScale.min = min
this.colorScale.max = max
this.trackView.repaintViews()
}

hasSamples() {
Expand Down Expand Up @@ -231,43 +232,16 @@ class ShoeboxTrack extends TrackBase {
return items
}

contextMenuItemList(clickState) {
get supportsWholeGenome() {
return false
}

const genomicLocation = clickState.genomicLocation
getState() {

const sortHandler = (sort) => {
const viewport = clickState.viewport
const features = viewport.cachedFeatures
this.sortByValue(sort, features)
}
const config = super.getState()
config.colorScale = this.colorScale.stringify()
return config

// We can't know genomic location intended with precision, define a buffer 5 "pixels" wide in genomic coordinates
const bpWidth = clickState.referenceFrame.toBP(2.5)

return ["DESC", "ASC"].map(direction => {
const dirLabel = direction === "DESC" ? "descending" : "ascending"
const sortLabel = this.type === 'seg' || this.type === 'shoebox' ?
`Sort by value (${dirLabel})` :
`Sort by type (${dirLabel})`
return {
label: sortLabel,
click: () => {
const sort = {
option: "VALUE", // Either VALUE or ATTRIBUTE
direction,
chr: clickState.referenceFrame.chr,
start: Math.floor(genomicLocation - bpWidth),
end: Math.floor(genomicLocation + bpWidth)
}
sortHandler(sort)
this.config.sort = sort
}
}
})
}

get supportsWholeGenome() {
return false
}

}
Expand Down
2 changes: 1 addition & 1 deletion js/trackFactory.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import IdeogramTrack from "./ideogramTrack.js"
import SpliceJunctionTrack from "./feature/spliceJunctionTrack.js"
import BlatTrack from "./blat/blatTrack.js"
import CNVPytorTrack from "./cnvpytor/cnvpytorTrack.js"
import ShoeboxTrack from "./feature/shoeboxTrack.js"
import ShoeboxTrack from "./shoebox/shoeboxTrack.js"
//import CNVPytorTrack from "./CNVpytor/cnvpytorTrack.js"


Expand Down
2 changes: 1 addition & 1 deletion js/ui/menuUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Dialog from "./components/dialog.js"
import $ from "../vendor/jquery-3.3.1.slim.js"
import {colorPalettes} from "../util/colorPalletes.js"

const colorPickerTrackTypeSet = new Set(['bedtype', 'alignment', 'annotation', 'variant', 'wig', 'interact'])
const colorPickerTrackTypeSet = new Set(['bedtype', 'alignment', 'annotation', 'variant', 'wig', 'interact', 'shoebox'])

const vizWindowTypes = new Set(['alignment', 'annotation', 'variant', 'eqtl', 'qtl', 'snp', 'shoebox', 'wig'])

Expand Down

0 comments on commit 195de66

Please sign in to comment.