diff --git a/plugins/linear-genome-view/src/LinearGenomeView/components/LinearGenomeView.tsx b/plugins/linear-genome-view/src/LinearGenomeView/components/LinearGenomeView.tsx index 0ee5ece5f7f..d7ef1954807 100644 --- a/plugins/linear-genome-view/src/LinearGenomeView/components/LinearGenomeView.tsx +++ b/plugins/linear-genome-view/src/LinearGenomeView/components/LinearGenomeView.tsx @@ -64,17 +64,13 @@ const LinearGenomeView = observer(({ model }: { model: LGV }) => { {model.seqDialogDisplayed ? ( { - model.setSequenceDialogOpen(false) - }} + handleClose={() => model.setSequenceDialogOpen(false)} /> ) : null} {model.isSearchDialogDisplayed ? ( { - model.setSearchResults(undefined, undefined) - }} + handleClose={() => model.setSearchResults(undefined, undefined)} /> ) : null} {!hideHeader ? ( diff --git a/plugins/wiggle/src/LinearWiggleDisplay/models/model.tsx b/plugins/wiggle/src/LinearWiggleDisplay/models/model.tsx index ac686fd1d84..2f48d86544d 100644 --- a/plugins/wiggle/src/LinearWiggleDisplay/models/model.tsx +++ b/plugins/wiggle/src/LinearWiggleDisplay/models/model.tsx @@ -57,6 +57,7 @@ const stateModelFactory = ( selectedRendering: types.optional(types.string, ''), resolution: types.optional(types.number, 1), fill: types.maybe(types.boolean), + minSize: types.maybe(types.number), color: types.maybe(types.string), posColor: types.maybe(types.string), negColor: types.maybe(types.string), @@ -123,8 +124,17 @@ const stateModelFactory = ( self.resolution = res }, - setFill(fill: boolean) { - self.fill = fill + setFill(fill: number) { + if (fill === 0) { + self.fill = true + self.minSize = 0 + } else if (fill === 1) { + self.fill = false + self.minSize = 0 + } else if (fill === 2) { + self.fill = false + self.minSize = 2 + } }, toggleLogScale() { @@ -213,12 +223,13 @@ const stateModelFactory = ( const { color, - posColor, + displayCrossHatches, + fill, + minSize, negColor, + posColor, summaryScoreMode, scaleType, - displayCrossHatches, - fill, } = self return self.rendererType.configSchema.create( @@ -230,9 +241,10 @@ const stateModelFactory = ( ? { displayCrossHatches } : {}), ...(summaryScoreMode !== undefined ? { summaryScoreMode } : {}), - ...(color !== undefined ? { color: color } : {}), - ...(negColor !== undefined ? { negColor: negColor } : {}), - ...(posColor !== undefined ? { posColor: posColor } : {}), + ...(color !== undefined ? { color } : {}), + ...(negColor !== undefined ? { negColor } : {}), + ...(posColor !== undefined ? { posColor } : {}), + ...(minSize !== undefined ? { minSize } : {}), }, getEnv(self), ) @@ -351,6 +363,16 @@ const stateModelFactory = ( get hasGlobalStats() { return self.adapterCapabilities.includes('hasGlobalStats') }, + + get fillSetting() { + if (self.filled) { + return 0 + } else if (!self.filled && self.minSize === 0) { + return 1 + } else { + return 2 + } + }, } }) .views(self => { @@ -379,18 +401,26 @@ const stateModelFactory = ( label: 'Summary score mode', subMenu: ['min', 'max', 'avg', 'whiskers'].map(elt => ({ label: elt, + type: 'radio', + checked: self.summaryScoreModeSetting === elt, onClick: () => self.setSummaryScoreMode(elt), })), }, ] : []), + ...(self.canHaveFill ? [ { - label: self.filled - ? 'Turn off histogram fill' - : 'Turn on histogram fill', - onClick: () => self.setFill(!self.filled), + label: 'Fill mode', + subMenu: ['filled', 'no fill', 'no fill w/ emphasis'].map( + (elt, idx) => ({ + label: elt, + type: 'radio', + checked: self.fillSetting === idx, + onClick: () => self.setFill(idx), + }), + ), }, ] : []), diff --git a/plugins/wiggle/src/MultiLineRenderer/configSchema.ts b/plugins/wiggle/src/MultiLineRenderer/configSchema.ts index 5bfe6c76667..cd2719599c6 100644 --- a/plugins/wiggle/src/MultiLineRenderer/configSchema.ts +++ b/plugins/wiggle/src/MultiLineRenderer/configSchema.ts @@ -5,10 +5,12 @@ import ConfigSchema from '../configSchema' const configSchema = ConfigurationSchema( 'MultiLineRenderer', { - filled: { + displayCrossHatches: { type: 'boolean', + description: 'choose to draw cross hatches (sideways lines)', defaultValue: false, }, + summaryScoreMode: { type: 'stringEnum', model: types.enumeration('Score type', ['max', 'min', 'avg', 'whiskers']), diff --git a/plugins/wiggle/src/MultiLinearWiggleDisplay/models/model.tsx b/plugins/wiggle/src/MultiLinearWiggleDisplay/models/model.tsx index 68dbaecaab0..610035cf6fc 100644 --- a/plugins/wiggle/src/MultiLinearWiggleDisplay/models/model.tsx +++ b/plugins/wiggle/src/MultiLinearWiggleDisplay/models/model.tsx @@ -75,6 +75,7 @@ const stateModelFactory = ( selectedRendering: types.optional(types.string, ''), resolution: types.optional(types.number, 1), fill: types.maybe(types.boolean), + minSize: types.maybe(types.number), height: 200, color: types.maybe(types.string), posColor: types.maybe(types.string), @@ -161,8 +162,17 @@ const stateModelFactory = ( self.resolution = res }, - setFill(fill: boolean) { - self.fill = fill + setFill(fill: number) { + if (fill === 0) { + self.fill = true + self.minSize = 0 + } else if (fill === 1) { + self.fill = false + self.minSize = 0 + } else if (fill === 2) { + self.fill = false + self.minSize = 2 + } }, toggleLogScale() { @@ -252,12 +262,13 @@ const stateModelFactory = ( const { color, - posColor, + displayCrossHatches, + fill, + minSize, negColor, + posColor, summaryScoreMode, scaleType, - displayCrossHatches, - fill, } = self return self.rendererType.configSchema.create( @@ -269,9 +280,10 @@ const stateModelFactory = ( ? { displayCrossHatches } : {}), ...(summaryScoreMode !== undefined ? { summaryScoreMode } : {}), - ...(color !== undefined ? { color: color } : {}), - ...(negColor !== undefined ? { negColor: negColor } : {}), - ...(posColor !== undefined ? { posColor: posColor } : {}), + ...(color !== undefined ? { color } : {}), + ...(negColor !== undefined ? { negColor } : {}), + ...(posColor !== undefined ? { posColor } : {}), + ...(minSize !== undefined ? { minSize } : {}), }, getEnv(self), ) @@ -503,6 +515,16 @@ const stateModelFactory = ( get hasGlobalStats() { return self.adapterCapabilities.includes('hasGlobalStats') }, + + get fillSetting() { + if (self.filled) { + return 0 + } else if (!self.filled && self.minSize === 0) { + return 1 + } else { + return 2 + } + }, } }) .views(self => { @@ -529,22 +551,27 @@ const stateModelFactory = ( }, { label: 'Summary score mode', - subMenu: ['min', 'max', 'avg', 'whiskers'].map(elt => { - return { - label: elt, - onClick: () => self.setSummaryScoreMode(elt), - } - }), + subMenu: ['min', 'max', 'avg', 'whiskers'].map(elt => ({ + label: elt, + type: 'radio', + checked: self.summaryScoreModeSetting === elt, + onClick: () => self.setSummaryScoreMode(elt), + })), }, ] : []), ...(self.canHaveFill ? [ { - label: self.filled - ? 'Turn off histogram fill' - : 'Turn on histogram fill', - onClick: () => self.setFill(!self.filled), + label: 'Fill mode', + subMenu: ['filled', 'no fill', 'no fill w/ emphasis'].map( + (elt, idx) => ({ + label: elt, + type: 'radio', + checked: self.fillSetting === idx, + onClick: () => self.setFill(idx), + }), + ), }, ] : []), diff --git a/plugins/wiggle/src/MultiRowLineRenderer/configSchema.ts b/plugins/wiggle/src/MultiRowLineRenderer/configSchema.ts index bcf2284f84c..6e6b75c0233 100644 --- a/plugins/wiggle/src/MultiRowLineRenderer/configSchema.ts +++ b/plugins/wiggle/src/MultiRowLineRenderer/configSchema.ts @@ -4,11 +4,12 @@ import { ConfigurationSchema } from '@jbrowse/core/configuration' import ConfigSchema from '../configSchema' const configSchema = ConfigurationSchema( - 'MultiRowXYPlotRenderer', + 'MultiRowLineRenderer', { - filled: { + displayCrossHatches: { type: 'boolean', - defaultValue: true, + description: 'choose to draw cross hatches (sideways lines)', + defaultValue: false, }, summaryScoreMode: { type: 'stringEnum', diff --git a/plugins/wiggle/src/MultiRowXYPlotRenderer/configSchema.ts b/plugins/wiggle/src/MultiRowXYPlotRenderer/configSchema.ts index 06364570835..414fcea5faf 100644 --- a/plugins/wiggle/src/MultiRowXYPlotRenderer/configSchema.ts +++ b/plugins/wiggle/src/MultiRowXYPlotRenderer/configSchema.ts @@ -10,6 +10,11 @@ const configSchema = ConfigurationSchema( type: 'boolean', defaultValue: true, }, + displayCrossHatches: { + type: 'boolean', + description: 'choose to draw cross hatches (sideways lines)', + defaultValue: false, + }, summaryScoreMode: { type: 'stringEnum', model: types.enumeration('Score type', ['max', 'min', 'avg', 'whiskers']), @@ -17,6 +22,10 @@ const configSchema = ConfigurationSchema( 'choose whether to use max/min/average or whiskers which combines all three into the same rendering', defaultValue: 'whiskers', }, + minSize: { + type: 'number', + defaultValue: 0, + }, }, { baseConfiguration: ConfigSchema, explicitlyTyped: true }, ) diff --git a/plugins/wiggle/src/MultiXYPlotRenderer/configSchema.ts b/plugins/wiggle/src/MultiXYPlotRenderer/configSchema.ts index 5a6a55627fa..233cf56449c 100644 --- a/plugins/wiggle/src/MultiXYPlotRenderer/configSchema.ts +++ b/plugins/wiggle/src/MultiXYPlotRenderer/configSchema.ts @@ -9,6 +9,11 @@ const configSchema = ConfigurationSchema( type: 'boolean', defaultValue: true, }, + displayCrossHatches: { + type: 'boolean', + description: 'choose to draw cross hatches (sideways lines)', + defaultValue: false, + }, summaryScoreMode: { type: 'stringEnum', model: types.enumeration('Score type', ['max', 'min', 'avg', 'whiskers']), @@ -16,6 +21,10 @@ const configSchema = ConfigurationSchema( 'choose whether to use max/min/average or whiskers which combines all three into the same rendering', defaultValue: 'avg', }, + minSize: { + type: 'number', + defaultValue: 0, + }, }, { baseConfiguration: ConfigSchema, explicitlyTyped: true }, ) diff --git a/plugins/wiggle/src/XYPlotRenderer/configSchema.ts b/plugins/wiggle/src/XYPlotRenderer/configSchema.ts index e9656565414..11a057440da 100644 --- a/plugins/wiggle/src/XYPlotRenderer/configSchema.ts +++ b/plugins/wiggle/src/XYPlotRenderer/configSchema.ts @@ -21,6 +21,10 @@ const configSchema = ConfigurationSchema( 'choose whether to use max/min/average or whiskers which combines all three into the same rendering', defaultValue: 'whiskers', }, + minSize: { + type: 'number', + defaultValue: 0, + }, }, { baseConfiguration: ConfigSchema, explicitlyTyped: true }, ) diff --git a/plugins/wiggle/src/drawxy.ts b/plugins/wiggle/src/drawxy.ts index eae9e38028b..2b26ee62288 100644 --- a/plugins/wiggle/src/drawxy.ts +++ b/plugins/wiggle/src/drawxy.ts @@ -72,6 +72,7 @@ export function drawXY( const clipColor = readConfObject(config, 'clipColor') const summaryScoreMode = readConfObject(config, 'summaryScoreMode') const pivotValue = readConfObject(config, 'bicolorPivotValue') + const minSize = readConfObject(config, 'minSize') const scale = getScale({ ...scaleOpts, range: [0, height] }) const originY = getOrigin(scaleOpts.scaleType) @@ -79,7 +80,7 @@ export function drawXY( const toY = (n: number) => clamp(height - (scale(n) || 0), 0, height) + offset const toOrigin = (n: number) => toY(originY) - toY(n) - const getHeight = (n: number) => (filled ? toOrigin(n) : 1) + const getHeight = (n: number) => (filled ? toOrigin(n) : Math.max(minSize, 1)) let hasClipping = false let prevLeftPx = 0 @@ -107,6 +108,8 @@ export function drawXY( lastCol = c } } + lastMix = undefined + lastCol = undefined for (const feature of features.values()) { const [leftPx, rightPx] = featureSpanPx(feature, region, bpPerPx) const score = feature.get('score') @@ -122,7 +125,7 @@ export function drawXY( .mix(Color(colorCallback(feature, min))) .toString()) : c - const w = rightPx - leftPx + fudgeFactor + const w = Math.max(rightPx - leftPx + fudgeFactor, minSize) // create reduced features, avoiding multiple features per px if (Math.floor(leftPx) !== Math.floor(prevLeftPx)) { reducedFeatures.push(feature) @@ -132,13 +135,15 @@ export function drawXY( fillRectCtx(leftPx, toY(score), w, getHeight(score), ctx, effectiveC) lastCol = c } + lastMix = undefined + lastCol = undefined for (const feature of features.values()) { const [leftPx, rightPx] = featureSpanPx(feature, region, bpPerPx) if (feature.get('summary')) { const min = feature.get('minScore') const c = colorCallback(feature, min) - const w = rightPx - leftPx + fudgeFactor + const w = Math.max(rightPx - leftPx + fudgeFactor, minSize) const effectiveC = crossingOrigin ? c : c === lastCol @@ -163,7 +168,7 @@ export function drawXY( const c = colorCallback(feature, score) hasClipping = hasClipping || score < niceMin || score > niceMax - const w = rightPx - leftPx + fudgeFactor + const w = Math.max(rightPx - leftPx + fudgeFactor, minSize) if (summaryScoreMode === 'max') { const s = feature.get('summary') ? feature.get('maxScore') : score