From 54608ef7ad2cd675137edb2ee4f523cd2675d773 Mon Sep 17 00:00:00 2001 From: Colin Date: Wed, 13 Nov 2024 02:03:35 -0500 Subject: [PATCH 1/4] Misc --- packages/core/util/stats.test.ts | 32 --------------- packages/core/util/stats.ts | 39 ------------------ .../models/TrackHeightMixin.tsx | 2 +- .../models/configSchema.ts | 2 +- .../src/LinearWiggleDisplay/models/model.ts | 25 +++++++++-- .../models/configSchema.ts | 2 +- .../MultiLinearWiggleDisplay/models/model.ts | 26 ++++++++++-- ...gShared.ts => SharedWiggleConfigSchema.ts} | 0 .../{modelShared.ts => SharedWiggleMixin.ts} | 41 ++++++++++++++++--- plugins/wiggle/src/util.ts | 11 +---- 10 files changed, 85 insertions(+), 95 deletions(-) rename plugins/wiggle/src/shared/{configShared.ts => SharedWiggleConfigSchema.ts} (100%) rename plugins/wiggle/src/shared/{modelShared.ts => SharedWiggleMixin.ts} (94%) diff --git a/packages/core/util/stats.test.ts b/packages/core/util/stats.test.ts index 349a0250af..53eaa139ec 100644 --- a/packages/core/util/stats.test.ts +++ b/packages/core/util/stats.test.ts @@ -4,7 +4,6 @@ import { calcStdFromSums, rectifyStats, scoresToStats, - calcPerBaseStats, UnrectifiedQuantitativeStats, } from './stats' @@ -55,34 +54,3 @@ test('scores to stats', async () => { expect(ret.scoreMin).toEqual(1) expect(ret.scoreStdDev).toEqual(1) // calculated from a webapp }) - -// peter TODO: fix this test -test('calc per base stats', () => { - // one score at start - expect( - calcPerBaseStats({ refName: 'ctgA', start: 0, end: 9 }, [ - new SimpleFeature({ id: 1, data: { start: 0, end: 1, score: 10 } }), - ]), - ).toEqual([10, 0, 0, 0, 0, 0, 0, 0, 0]) - // multiple features - expect( - calcPerBaseStats({ refName: 'ctgA', start: 0, end: 9 }, [ - new SimpleFeature({ id: 1, data: { start: 0, end: 1, score: 10 } }), - new SimpleFeature({ id: 2, data: { start: 8, end: 9, score: 10 } }), - ]), - ).toEqual([10, 0, 0, 0, 0, 0, 0, 0, 10]) - // multiple features - expect( - calcPerBaseStats({ refName: 'ctgA', start: 15, end: 30 }, [ - new SimpleFeature({ id: 1, data: { start: 10, end: 20, score: 10 } }), - new SimpleFeature({ id: 2, data: { start: 25, end: 26, score: 10 } }), - ]), - ).toEqual([10, 10, 10, 10, 10, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0]) - // feature starts before region - expect( - calcPerBaseStats({ refName: 'ctgA', start: 10, end: 19 }, [ - new SimpleFeature({ id: 1, data: { start: 5, end: 15, score: 10 } }), - new SimpleFeature({ id: 1, data: { start: 18, end: 26, score: 10 } }), - ]), - ).toEqual([10, 10, 10, 10, 10, 0, 0, 0, 10]) -}) diff --git a/packages/core/util/stats.ts b/packages/core/util/stats.ts index 513de34f4c..697f2c5dbf 100644 --- a/packages/core/util/stats.ts +++ b/packages/core/util/stats.ts @@ -71,45 +71,6 @@ export function rectifyStats(s: UnrectifiedQuantitativeStats) { } as QuantitativeStats } -/** - * calculates per-base scores for variable width features over a region - * - * @param region - object contains start, end - * @param features - list of features with start, end, score - * @returns array of numeric scores - */ -export function calcPerBaseStats( - region: NoAssemblyRegion, - features: Feature[], -): number[] { - const { start, end } = region - const scores = [] - const feats = features.sort((a, b) => a.get('start') - b.get('start')) - let pos = start - let currentFeat = 0 - let i = 0 - - while (pos < end) { - while ( - currentFeat < feats.length && - pos >= feats[currentFeat]!.get('end') - ) { - currentFeat += 1 - } - const f = feats[currentFeat] - if (!f) { - scores[i] = 0 - } else if (pos >= f.get('start') && pos < f.get('end')) { - scores[i] = f.get('score') - } else { - scores[i] = 0 - } - i += 1 - pos += 1 - } - return scores -} - /** * transform a list of scores to summary statistics * diff --git a/plugins/linear-genome-view/src/BaseLinearDisplay/models/TrackHeightMixin.tsx b/plugins/linear-genome-view/src/BaseLinearDisplay/models/TrackHeightMixin.tsx index d538ba944e..7f4bffcd9b 100644 --- a/plugins/linear-genome-view/src/BaseLinearDisplay/models/TrackHeightMixin.tsx +++ b/plugins/linear-genome-view/src/BaseLinearDisplay/models/TrackHeightMixin.tsx @@ -23,7 +23,7 @@ export default function TrackHeightMixin() { }) .volatile(() => ({ /** - * #property + * #volatile */ scrollTop: 0, })) diff --git a/plugins/wiggle/src/LinearWiggleDisplay/models/configSchema.ts b/plugins/wiggle/src/LinearWiggleDisplay/models/configSchema.ts index 3090d89fc8..84e0883d1c 100644 --- a/plugins/wiggle/src/LinearWiggleDisplay/models/configSchema.ts +++ b/plugins/wiggle/src/LinearWiggleDisplay/models/configSchema.ts @@ -3,7 +3,7 @@ import { types } from 'mobx-state-tree' import PluginManager from '@jbrowse/core/PluginManager' // locals -import sharedWiggleConfigFactory from '../../shared/configShared' +import sharedWiggleConfigFactory from '../../shared/SharedWiggleConfigSchema' /** * #config LinearWiggleDisplay diff --git a/plugins/wiggle/src/LinearWiggleDisplay/models/model.ts b/plugins/wiggle/src/LinearWiggleDisplay/models/model.ts index c85e19249d..7fb4744905 100644 --- a/plugins/wiggle/src/LinearWiggleDisplay/models/model.ts +++ b/plugins/wiggle/src/LinearWiggleDisplay/models/model.ts @@ -3,15 +3,22 @@ import { AnyConfigurationSchemaType, getConf, } from '@jbrowse/core/configuration' -import { AnyReactComponentType, getSession } from '@jbrowse/core/util' +import { + AnyReactComponentType, + getContainingView, + getSession, +} from '@jbrowse/core/util' import { types, Instance } from 'mobx-state-tree' import PluginManager from '@jbrowse/core/PluginManager' import { axisPropsFromTickScale } from 'react-d3-axis-mod' -import { ExportSvgDisplayOptions } from '@jbrowse/plugin-linear-genome-view' +import { + ExportSvgDisplayOptions, + LinearGenomeViewModel, +} from '@jbrowse/plugin-linear-genome-view' // locals import { getScale, YSCALEBAR_LABEL_OFFSET } from '../../util' -import SharedWiggleMixin from '../../shared/modelShared' +import SharedWiggleMixin from '../../shared/SharedWiggleMixin' // lazies const Tooltip = lazy(() => import('../components/Tooltip')) @@ -133,6 +140,18 @@ function stateModelFactory( return 2 } }, + /** + * #getter + */ + get quantitativeStatsReady() { + const view = getContainingView(self) as LinearGenomeViewModel + return ( + view.initialized && + self.featureDensityStatsReady && + !self.regionTooLarge && + !self.error + ) + }, } }) .views(self => { diff --git a/plugins/wiggle/src/MultiLinearWiggleDisplay/models/configSchema.ts b/plugins/wiggle/src/MultiLinearWiggleDisplay/models/configSchema.ts index 4c5c8ad010..56262b145f 100644 --- a/plugins/wiggle/src/MultiLinearWiggleDisplay/models/configSchema.ts +++ b/plugins/wiggle/src/MultiLinearWiggleDisplay/models/configSchema.ts @@ -3,7 +3,7 @@ import { types } from 'mobx-state-tree' import PluginManager from '@jbrowse/core/PluginManager' // locals -import sharedWiggleConfigFactory from '../../shared/configShared' +import sharedWiggleConfigFactory from '../../shared/SharedWiggleConfigSchema' /** * #config MultiLinearWiggleDisplay diff --git a/plugins/wiggle/src/MultiLinearWiggleDisplay/models/model.ts b/plugins/wiggle/src/MultiLinearWiggleDisplay/models/model.ts index e0f5428a21..5288c48637 100644 --- a/plugins/wiggle/src/MultiLinearWiggleDisplay/models/model.ts +++ b/plugins/wiggle/src/MultiLinearWiggleDisplay/models/model.ts @@ -9,15 +9,23 @@ import { AnyConfigurationSchemaType, getConf, } from '@jbrowse/core/configuration' -import { getSession, Feature, AnyReactComponentType } from '@jbrowse/core/util' +import { + getSession, + Feature, + AnyReactComponentType, + getContainingView, +} from '@jbrowse/core/util' import { getRpcSessionId } from '@jbrowse/core/util/tracks' import { set1 as colors } from '@jbrowse/core/ui/colors' import PluginManager from '@jbrowse/core/PluginManager' -import { ExportSvgDisplayOptions } from '@jbrowse/plugin-linear-genome-view' +import { + ExportSvgDisplayOptions, + LinearGenomeViewModel, +} from '@jbrowse/plugin-linear-genome-view' // locals import { getScale, YSCALEBAR_LABEL_OFFSET } from '../../util' -import SharedWiggleMixin from '../../shared/modelShared' +import SharedWiggleMixin from '../../shared/SharedWiggleMixin' const randomColor = () => '#000000'.replaceAll('0', () => (~~(Math.random() * 16)).toString(16)) @@ -212,6 +220,18 @@ export function stateModelFactory( (!this.isMultiRow ? colors[i] || randomColor() : 'blue'), })) }, + /** + * #getter + */ + get quantitativeStatsReady() { + const view = getContainingView(self) as LinearGenomeViewModel + return ( + view.initialized && + self.featureDensityStatsReady && + !self.regionTooLarge && + !self.error + ) + }, })) .views(self => ({ diff --git a/plugins/wiggle/src/shared/configShared.ts b/plugins/wiggle/src/shared/SharedWiggleConfigSchema.ts similarity index 100% rename from plugins/wiggle/src/shared/configShared.ts rename to plugins/wiggle/src/shared/SharedWiggleConfigSchema.ts diff --git a/plugins/wiggle/src/shared/modelShared.ts b/plugins/wiggle/src/shared/SharedWiggleMixin.ts similarity index 94% rename from plugins/wiggle/src/shared/modelShared.ts rename to plugins/wiggle/src/shared/SharedWiggleMixin.ts index c772760753..920daab2ae 100644 --- a/plugins/wiggle/src/shared/modelShared.ts +++ b/plugins/wiggle/src/shared/SharedWiggleMixin.ts @@ -6,11 +6,15 @@ import { } from '@jbrowse/core/configuration' import { Feature, + getContainingView, getEnv, getSession, isSelectionContainer, } from '@jbrowse/core/util' -import { BaseLinearDisplay } from '@jbrowse/plugin-linear-genome-view' +import { + BaseLinearDisplay, + LinearGenomeViewModel, +} from '@jbrowse/plugin-linear-genome-view' import { types } from 'mobx-state-tree' // locals @@ -95,24 +99,49 @@ export default function SharedWiggleMixin( }), ) .volatile(() => ({ + /** + * #volatile + */ + currStatBpPerPx: 0, + /** + * #volatile + */ message: undefined as undefined | string, - stats: undefined as { scoreMin: number; scoreMax: number } | undefined, + /** + * #volatile + */ + stats: undefined as + | { currStatBpPerPx: number; scoreMin: number; scoreMax: number } + | undefined, + /** + * #volatile + */ statsFetchInProgress: undefined as undefined | AbortController, })) .actions(self => ({ + /** + * #action + */ + setCurrStatBpPerPx(n: number) { + self.currStatBpPerPx = n + }, /** * #action */ updateQuantitativeStats(stats: { scoreMin: number; scoreMax: number }) { const { scoreMin, scoreMax } = stats const EPSILON = 0.000001 - if (!self.stats) { - self.stats = { scoreMin, scoreMax } - } else if ( + const view = getContainingView(self) as LinearGenomeViewModel + if ( + !self.stats || Math.abs(self.stats.scoreMax - scoreMax) > EPSILON || Math.abs(self.stats.scoreMin - scoreMin) > EPSILON ) { - self.stats = { scoreMin, scoreMax } + self.stats = { + currStatBpPerPx: view.bpPerPx, + scoreMin, + scoreMax, + } } }, /** diff --git a/plugins/wiggle/src/util.ts b/plugins/wiggle/src/util.ts index abadcb8b9c..02790b2ddc 100644 --- a/plugins/wiggle/src/util.ts +++ b/plugins/wiggle/src/util.ts @@ -259,9 +259,7 @@ export async function getQuantitativeStats( } export function quantitativeStatsAutorun(self: { - featureDensityStatsReady: boolean - regionTooLarge: boolean - error: unknown + quantitativeStatsReady: boolean setLoading: (aborter: AbortController) => void setError: (error: unknown) => void updateQuantitativeStats: ( @@ -283,12 +281,7 @@ export function quantitativeStatsAutorun(self: { const view = getContainingView(self) as LGV self.setLoading(aborter) - if ( - !view.initialized || - !self.featureDensityStatsReady || - self.regionTooLarge || - self.error - ) { + if (!self.quantitativeStatsReady) { return } const statsRegion = JSON.stringify(view.dynamicBlocks) From ce901b44804c76c2e658fd8be9bacdc1da8512fb Mon Sep 17 00:00:00 2001 From: Colin Date: Wed, 13 Nov 2024 02:25:18 -0500 Subject: [PATCH 2/4] More misc --- packages/core/util/stats.ts | 1 + .../src/LinearWiggleDisplay/models/model.ts | 21 ++- .../MultiLinearWiggleDisplay/models/model.ts | 4 +- .../wiggle/src/quantitativeStatsAutorun.ts | 164 ++++++++++++++++++ .../wiggle/src/shared/SharedWiggleMixin.ts | 23 +-- plugins/wiggle/src/util.ts | 157 +---------------- 6 files changed, 198 insertions(+), 172 deletions(-) create mode 100644 plugins/wiggle/src/quantitativeStatsAutorun.ts diff --git a/packages/core/util/stats.ts b/packages/core/util/stats.ts index 697f2c5dbf..3fed51fed6 100644 --- a/packages/core/util/stats.ts +++ b/packages/core/util/stats.ts @@ -14,6 +14,7 @@ export interface UnrectifiedQuantitativeStats { basesCovered: number } export interface QuantitativeStats extends UnrectifiedQuantitativeStats { + currStatsBpPerPx: number featureDensity: number scoreMean: number scoreStdDev: number diff --git a/plugins/wiggle/src/LinearWiggleDisplay/models/model.ts b/plugins/wiggle/src/LinearWiggleDisplay/models/model.ts index 7fb4744905..aa2f3a62d0 100644 --- a/plugins/wiggle/src/LinearWiggleDisplay/models/model.ts +++ b/plugins/wiggle/src/LinearWiggleDisplay/models/model.ts @@ -96,6 +96,14 @@ function stateModelFactory( ? { ...ticks, values: domain } : ticks }, + /** + * #getter + */ + get quantitativeStatsReleventToCurrentZoom() { + const view = getContainingView(self) as LinearGenomeViewModel + console.log(self.stats?.currStatsBpPerPx, view.bpPerPx) + return self.stats?.currStatsBpPerPx === view.bpPerPx + }, })) .views(self => { const { renderProps: superRenderProps } = self @@ -108,7 +116,9 @@ function stateModelFactory( const { filters, ticks, height, resolution, scaleOpts } = self return { ...superProps, - notReady: superProps.notReady || !self.stats, + notReady: + superProps.notReady || + !self.quantitativeStatsReleventToCurrentZoom, rpcDriverName: self.rpcDriverName, displayModel: self, config: self.rendererConfig, @@ -221,7 +231,10 @@ function stateModelFactory( onClick: () => { getSession(self).queueDialog(handleClose => [ SetColorDialog, - { model: self, handleClose }, + { + model: self, + handleClose, + }, ]) }, }, @@ -236,7 +249,9 @@ function stateModelFactory( afterAttach() { // eslint-disable-next-line @typescript-eslint/no-floating-promises ;(async () => { - const { quantitativeStatsAutorun } = await import('../../util') + const { quantitativeStatsAutorun } = await import( + '../../quantitativeStatsAutorun' + ) quantitativeStatsAutorun(self) })() }, diff --git a/plugins/wiggle/src/MultiLinearWiggleDisplay/models/model.ts b/plugins/wiggle/src/MultiLinearWiggleDisplay/models/model.ts index 5288c48637..be50c3714a 100644 --- a/plugins/wiggle/src/MultiLinearWiggleDisplay/models/model.ts +++ b/plugins/wiggle/src/MultiLinearWiggleDisplay/models/model.ts @@ -457,7 +457,9 @@ export function stateModelFactory( afterAttach() { // eslint-disable-next-line @typescript-eslint/no-floating-promises ;(async () => { - const { quantitativeStatsAutorun } = await import('../../util') + const { quantitativeStatsAutorun } = await import( + '../../quantitativeStatsAutorun' + ) quantitativeStatsAutorun(self) addDisposer( self, diff --git a/plugins/wiggle/src/quantitativeStatsAutorun.ts b/plugins/wiggle/src/quantitativeStatsAutorun.ts new file mode 100644 index 0000000000..6a9772414b --- /dev/null +++ b/plugins/wiggle/src/quantitativeStatsAutorun.ts @@ -0,0 +1,164 @@ +import { autorun } from 'mobx' +import { + isAbortException, + getSession, + getContainingView, +} from '@jbrowse/core/util' +import { QuantitativeStats } from '@jbrowse/core/util/stats' +import { getRpcSessionId } from '@jbrowse/core/util/tracks' +import { addDisposer, isAlive } from 'mobx-state-tree' + +import { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view' +import { AnyConfigurationModel, getConf } from '@jbrowse/core/configuration' + +type LGV = LinearGenomeViewModel + +export function quantitativeStatsAutorun(self: { + quantitativeStatsReady: boolean + setLoading: (aborter: AbortController) => void + setError: (error: unknown) => void + updateQuantitativeStats: ( + stats: QuantitativeStats, + statsRegion: string, + ) => void + renderProps: () => Record + configuration: AnyConfigurationModel + adapterConfig: AnyConfigurationModel + autoscaleType: string + setMessage: (str: string) => void +}) { + addDisposer( + self, + autorun( + async () => { + try { + const aborter = new AbortController() + const view = getContainingView(self) as LGV + self.setLoading(aborter) + + console.log(self.quantitativeStatsReady, 'wow') + if (!self.quantitativeStatsReady) { + return + } + console.log(self.quantitativeStatsReady, 'past') + const statsRegion = JSON.stringify(view.dynamicBlocks) + + const wiggleStats = await getQuantitativeStats(self, { + signal: aborter.signal, + filters: [], + currStatsBpPerPx: view.bpPerPx, + ...self.renderProps(), + }) + + if (isAlive(self)) { + self.updateQuantitativeStats(wiggleStats, statsRegion) + } + } catch (e) { + if (!isAbortException(e) && isAlive(self)) { + console.error(e) + self.setError(e) + } + } + }, + { delay: 1000 }, + ), + ) +} + +export async function getQuantitativeStats( + self: { + adapterConfig: AnyConfigurationModel + configuration: AnyConfigurationModel + autoscaleType: string + setMessage: (str: string) => void + }, + opts: { + headers?: Record + signal?: AbortSignal + filters: string[] + currStatsBpPerPx: number + }, +): Promise { + const { rpcManager } = getSession(self) + const numStdDev = getConf(self, 'numStdDev') || 3 + const { adapterConfig, autoscaleType } = self + const sessionId = getRpcSessionId(self) + const { currStatsBpPerPx } = opts + const params = { + sessionId, + adapterConfig, + statusCallback: (message: string) => { + if (isAlive(self)) { + self.setMessage(message) + } + }, + ...opts, + } + + if (autoscaleType === 'global' || autoscaleType === 'globalsd') { + const results = (await rpcManager.call( + sessionId, + 'WiggleGetGlobalQuantitativeStats', + params, + )) as QuantitativeStats + const { scoreMin, scoreMean, scoreStdDev } = results + // globalsd uses heuristic to avoid unnecessary scoreMin<0 + // + // if the scoreMin is never less than 0 helps with most coverage bigwigs + // just being >0 + return autoscaleType === 'globalsd' + ? { + ...results, + scoreMin: scoreMin >= 0 ? 0 : scoreMean - numStdDev * scoreStdDev, + scoreMax: scoreMean + numStdDev * scoreStdDev, + currStatsBpPerPx, + } + : { + ...results, + currStatsBpPerPx, + } + } + if (autoscaleType === 'local' || autoscaleType === 'localsd') { + const { dynamicBlocks, bpPerPx } = getContainingView(self) as LGV + const results = (await rpcManager.call( + sessionId, + 'WiggleGetMultiRegionQuantitativeStats', + { + ...params, + regions: dynamicBlocks.contentBlocks.map(region => { + const { start, end } = region + return { + ...JSON.parse(JSON.stringify(region)), + start: Math.floor(start), + end: Math.ceil(end), + } + }), + bpPerPx, + }, + )) as QuantitativeStats + const { scoreMin, scoreMean, scoreStdDev } = results + + // localsd uses heuristic to avoid unnecessary scoreMin<0 if the + // scoreMin is never less than 0 helps with most coverage bigwigs + // just being >0 + return autoscaleType === 'localsd' + ? { + ...results, + scoreMin: scoreMin >= 0 ? 0 : scoreMean - numStdDev * scoreStdDev, + scoreMax: scoreMean + numStdDev * scoreStdDev, + currStatsBpPerPx, + } + : { + ...results, + currStatsBpPerPx, + } + } + if (autoscaleType === 'zscale') { + return rpcManager.call( + sessionId, + 'WiggleGetGlobalQuantitativeStats', + params, + ) as Promise + } + throw new Error(`invalid autoscaleType '${autoscaleType}'`) +} diff --git a/plugins/wiggle/src/shared/SharedWiggleMixin.ts b/plugins/wiggle/src/shared/SharedWiggleMixin.ts index 920daab2ae..90753e69ce 100644 --- a/plugins/wiggle/src/shared/SharedWiggleMixin.ts +++ b/plugins/wiggle/src/shared/SharedWiggleMixin.ts @@ -99,10 +99,6 @@ export default function SharedWiggleMixin( }), ) .volatile(() => ({ - /** - * #volatile - */ - currStatBpPerPx: 0, /** * #volatile */ @@ -111,7 +107,7 @@ export default function SharedWiggleMixin( * #volatile */ stats: undefined as - | { currStatBpPerPx: number; scoreMin: number; scoreMax: number } + | { currStatsBpPerPx: number; scoreMin: number; scoreMax: number } | undefined, /** * #volatile @@ -122,23 +118,20 @@ export default function SharedWiggleMixin( /** * #action */ - setCurrStatBpPerPx(n: number) { - self.currStatBpPerPx = n - }, - /** - * #action - */ - updateQuantitativeStats(stats: { scoreMin: number; scoreMax: number }) { - const { scoreMin, scoreMax } = stats + updateQuantitativeStats(stats: { + currStatsBpPerPx: number + scoreMin: number + scoreMax: number + }) { + const { currStatsBpPerPx, scoreMin, scoreMax } = stats const EPSILON = 0.000001 - const view = getContainingView(self) as LinearGenomeViewModel if ( !self.stats || Math.abs(self.stats.scoreMax - scoreMax) > EPSILON || Math.abs(self.stats.scoreMin - scoreMin) > EPSILON ) { self.stats = { - currStatBpPerPx: view.bpPerPx, + currStatsBpPerPx, scoreMin, scoreMax, } diff --git a/plugins/wiggle/src/util.ts b/plugins/wiggle/src/util.ts index 02790b2ddc..7153a12ea5 100644 --- a/plugins/wiggle/src/util.ts +++ b/plugins/wiggle/src/util.ts @@ -3,20 +3,6 @@ import { scaleLog, scaleQuantize, } from '@mui/x-charts-vendor/d3-scale' -import { autorun } from 'mobx' -import { - isAbortException, - getSession, - getContainingView, -} from '@jbrowse/core/util' -import { QuantitativeStats } from '@jbrowse/core/util/stats' -import { getRpcSessionId } from '@jbrowse/core/util/tracks' -import { addDisposer, isAlive } from 'mobx-state-tree' - -import { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view' -import { AnyConfigurationModel, getConf } from '@jbrowse/core/configuration' - -type LGV = LinearGenomeViewModel export const YSCALEBAR_LABEL_OFFSET = 5 @@ -81,7 +67,8 @@ export function getScale({ return scale } /** - * gets the origin for drawing the graph. for linear this is 0, for log this is arbitrarily set to log(1)==0 + * gets the origin for drawing the graph. for linear this is 0, for log this is + * arbitrarily set to log(1)==0 * * @param scaleType - */ @@ -105,8 +92,8 @@ export function getOrigin(scaleType: string /* , pivot, stats */) { } /** - * produces a "nice" domain that actually rounds down to 0 for the min - * or 0 to the max depending on if all values are positive or negative + * produces a "nice" domain that actually rounds down to 0 for the min or 0 to + * the max depending on if all values are positive or negative * * @param object - containing attributes * - domain [min,max] @@ -171,142 +158,6 @@ export function getNiceDomain({ return scale.domain() as [number, number] } -export async function getQuantitativeStats( - self: { - adapterConfig: AnyConfigurationModel - configuration: AnyConfigurationModel - autoscaleType: string - setMessage: (str: string) => void - }, - opts: { - headers?: Record - signal?: AbortSignal - filters: string[] - }, -): Promise { - const { rpcManager } = getSession(self) - const numStdDev = getConf(self, 'numStdDev') || 3 - const { adapterConfig, autoscaleType } = self - const sessionId = getRpcSessionId(self) - const params = { - sessionId, - adapterConfig, - statusCallback: (message: string) => { - if (isAlive(self)) { - self.setMessage(message) - } - }, - ...opts, - } - - if (autoscaleType === 'global' || autoscaleType === 'globalsd') { - const results = (await rpcManager.call( - sessionId, - 'WiggleGetGlobalQuantitativeStats', - params, - )) as QuantitativeStats - const { scoreMin, scoreMean, scoreStdDev } = results - // globalsd uses heuristic to avoid unnecessary scoreMin<0 - // if the scoreMin is never less than 0 - // helps with most coverage bigwigs just being >0 - return autoscaleType === 'globalsd' - ? { - ...results, - scoreMin: scoreMin >= 0 ? 0 : scoreMean - numStdDev * scoreStdDev, - scoreMax: scoreMean + numStdDev * scoreStdDev, - } - : results - } - if (autoscaleType === 'local' || autoscaleType === 'localsd') { - const { dynamicBlocks, bpPerPx } = getContainingView(self) as LGV - const results = (await rpcManager.call( - sessionId, - 'WiggleGetMultiRegionQuantitativeStats', - { - ...params, - regions: dynamicBlocks.contentBlocks.map(region => { - const { start, end } = region - return { - ...JSON.parse(JSON.stringify(region)), - start: Math.floor(start), - end: Math.ceil(end), - } - }), - bpPerPx, - }, - )) as QuantitativeStats - const { scoreMin, scoreMean, scoreStdDev } = results - - // localsd uses heuristic to avoid unnecessary scoreMin<0 if the - // scoreMin is never less than 0 helps with most coverage bigwigs - // just being >0 - return autoscaleType === 'localsd' - ? { - ...results, - scoreMin: scoreMin >= 0 ? 0 : scoreMean - numStdDev * scoreStdDev, - scoreMax: scoreMean + numStdDev * scoreStdDev, - } - : results - } - if (autoscaleType === 'zscale') { - return rpcManager.call( - sessionId, - 'WiggleGetGlobalQuantitativeStats', - params, - ) as Promise - } - throw new Error(`invalid autoscaleType '${autoscaleType}'`) -} - -export function quantitativeStatsAutorun(self: { - quantitativeStatsReady: boolean - setLoading: (aborter: AbortController) => void - setError: (error: unknown) => void - updateQuantitativeStats: ( - stats: QuantitativeStats, - statsRegion: string, - ) => void - renderProps: () => Record - configuration: AnyConfigurationModel - adapterConfig: AnyConfigurationModel - autoscaleType: string - setMessage: (str: string) => void -}) { - addDisposer( - self, - autorun( - async () => { - try { - const aborter = new AbortController() - const view = getContainingView(self) as LGV - self.setLoading(aborter) - - if (!self.quantitativeStatsReady) { - return - } - const statsRegion = JSON.stringify(view.dynamicBlocks) - - const wiggleStats = await getQuantitativeStats(self, { - signal: aborter.signal, - filters: [], - ...self.renderProps(), - }) - - if (isAlive(self)) { - self.updateQuantitativeStats(wiggleStats, statsRegion) - } - } catch (e) { - if (!isAbortException(e) && isAlive(self)) { - console.error(e) - self.setError(e) - } - } - }, - { delay: 1000 }, - ), - ) -} - export function toP(s = 0) { return +(+s).toPrecision(6) } From d3063e0f2d8e599cdacf216c64f94b453fb199ac Mon Sep 17 00:00:00 2001 From: Colin Date: Wed, 13 Nov 2024 02:42:19 -0500 Subject: [PATCH 3/4] Move some stuff around --- .../components/WiggleDisplayComponent.tsx | 2 +- .../LinearWiggleDisplay/{models => }/configSchema.ts | 2 +- plugins/wiggle/src/LinearWiggleDisplay/index.ts | 6 +++--- .../src/LinearWiggleDisplay/{models => }/model.ts | 11 +++++------ .../LinearWiggleDisplay/{models => }/renderSvg.tsx | 3 ++- .../components/ColorLegend.tsx | 2 +- .../components/ScoreLegend.tsx | 2 +- .../components/WiggleDisplayComponent.tsx | 2 +- .../components/YScaleBars.tsx | 2 +- .../src/MultiLinearWiggleDisplay/components/util.ts | 2 +- .../{models => }/configSchema.ts | 2 +- plugins/wiggle/src/MultiLinearWiggleDisplay/index.ts | 4 ++-- .../MultiLinearWiggleDisplay/{models => }/model.ts | 10 +++++----- .../{models => }/renderSvg.tsx | 2 +- plugins/wiggle/src/index.ts | 2 +- plugins/wiggle/src/quantitativeStatsAutorun.ts | 2 -- plugins/wiggle/src/shared/SharedWiggleMixin.ts | 6 +----- 17 files changed, 28 insertions(+), 34 deletions(-) rename plugins/wiggle/src/LinearWiggleDisplay/{models => }/configSchema.ts (94%) rename plugins/wiggle/src/LinearWiggleDisplay/{models => }/model.ts (95%) rename plugins/wiggle/src/LinearWiggleDisplay/{models => }/renderSvg.tsx (94%) rename plugins/wiggle/src/MultiLinearWiggleDisplay/{models => }/configSchema.ts (96%) rename plugins/wiggle/src/MultiLinearWiggleDisplay/{models => }/model.ts (97%) rename plugins/wiggle/src/MultiLinearWiggleDisplay/{models => }/renderSvg.tsx (94%) diff --git a/plugins/wiggle/src/LinearWiggleDisplay/components/WiggleDisplayComponent.tsx b/plugins/wiggle/src/LinearWiggleDisplay/components/WiggleDisplayComponent.tsx index 201942fbdc..0bb51aded6 100644 --- a/plugins/wiggle/src/LinearWiggleDisplay/components/WiggleDisplayComponent.tsx +++ b/plugins/wiggle/src/LinearWiggleDisplay/components/WiggleDisplayComponent.tsx @@ -12,7 +12,7 @@ import { } from '@jbrowse/plugin-linear-genome-view' // locals -import { WiggleDisplayModel } from '../models/model' +import { WiggleDisplayModel } from '../model' import YScaleBar from '../../shared/YScaleBar' type LGV = LinearGenomeViewModel diff --git a/plugins/wiggle/src/LinearWiggleDisplay/models/configSchema.ts b/plugins/wiggle/src/LinearWiggleDisplay/configSchema.ts similarity index 94% rename from plugins/wiggle/src/LinearWiggleDisplay/models/configSchema.ts rename to plugins/wiggle/src/LinearWiggleDisplay/configSchema.ts index 84e0883d1c..8bc0450289 100644 --- a/plugins/wiggle/src/LinearWiggleDisplay/models/configSchema.ts +++ b/plugins/wiggle/src/LinearWiggleDisplay/configSchema.ts @@ -3,7 +3,7 @@ import { types } from 'mobx-state-tree' import PluginManager from '@jbrowse/core/PluginManager' // locals -import sharedWiggleConfigFactory from '../../shared/SharedWiggleConfigSchema' +import sharedWiggleConfigFactory from '../shared/SharedWiggleConfigSchema' /** * #config LinearWiggleDisplay diff --git a/plugins/wiggle/src/LinearWiggleDisplay/index.ts b/plugins/wiggle/src/LinearWiggleDisplay/index.ts index ec642999c3..a4687913ec 100644 --- a/plugins/wiggle/src/LinearWiggleDisplay/index.ts +++ b/plugins/wiggle/src/LinearWiggleDisplay/index.ts @@ -1,8 +1,8 @@ import PluginManager from '@jbrowse/core/PluginManager' import DisplayType from '@jbrowse/core/pluggableElementTypes/DisplayType' -import configSchemaFactory from './models/configSchema' -import modelFactory from './models/model' +import configSchemaFactory from './configSchema' +import modelFactory from './model' import { lazy } from 'react' export default function LinearWiggleDisplayF(pluginManager: PluginManager) { @@ -23,4 +23,4 @@ export default function LinearWiggleDisplayF(pluginManager: PluginManager) { export { default as Tooltip } from './components/Tooltip' export { default as ReactComponent } from './components/WiggleDisplayComponent' -export { default as modelFactory } from './models/model' +export { default as modelFactory } from './model' diff --git a/plugins/wiggle/src/LinearWiggleDisplay/models/model.ts b/plugins/wiggle/src/LinearWiggleDisplay/model.ts similarity index 95% rename from plugins/wiggle/src/LinearWiggleDisplay/models/model.ts rename to plugins/wiggle/src/LinearWiggleDisplay/model.ts index aa2f3a62d0..b502b7c6fe 100644 --- a/plugins/wiggle/src/LinearWiggleDisplay/models/model.ts +++ b/plugins/wiggle/src/LinearWiggleDisplay/model.ts @@ -17,12 +17,12 @@ import { } from '@jbrowse/plugin-linear-genome-view' // locals -import { getScale, YSCALEBAR_LABEL_OFFSET } from '../../util' -import SharedWiggleMixin from '../../shared/SharedWiggleMixin' +import { getScale, YSCALEBAR_LABEL_OFFSET } from '../util' +import SharedWiggleMixin from '../shared/SharedWiggleMixin' // lazies -const Tooltip = lazy(() => import('../components/Tooltip')) -const SetColorDialog = lazy(() => import('../components/SetColorDialog')) +const Tooltip = lazy(() => import('./components/Tooltip')) +const SetColorDialog = lazy(() => import('./components/SetColorDialog')) // using a map because it preserves order const rendererTypes = new Map([ @@ -101,7 +101,6 @@ function stateModelFactory( */ get quantitativeStatsReleventToCurrentZoom() { const view = getContainingView(self) as LinearGenomeViewModel - console.log(self.stats?.currStatsBpPerPx, view.bpPerPx) return self.stats?.currStatsBpPerPx === view.bpPerPx }, })) @@ -250,7 +249,7 @@ function stateModelFactory( // eslint-disable-next-line @typescript-eslint/no-floating-promises ;(async () => { const { quantitativeStatsAutorun } = await import( - '../../quantitativeStatsAutorun' + '../quantitativeStatsAutorun' ) quantitativeStatsAutorun(self) })() diff --git a/plugins/wiggle/src/LinearWiggleDisplay/models/renderSvg.tsx b/plugins/wiggle/src/LinearWiggleDisplay/renderSvg.tsx similarity index 94% rename from plugins/wiggle/src/LinearWiggleDisplay/models/renderSvg.tsx rename to plugins/wiggle/src/LinearWiggleDisplay/renderSvg.tsx index 5c9df57c37..410a14bba8 100644 --- a/plugins/wiggle/src/LinearWiggleDisplay/models/renderSvg.tsx +++ b/plugins/wiggle/src/LinearWiggleDisplay/renderSvg.tsx @@ -1,11 +1,12 @@ import React from 'react' import { getContainingView } from '@jbrowse/core/util' import { when } from 'mobx' -import YScaleBar from '../../shared/YScaleBar' import { ExportSvgDisplayOptions, LinearGenomeViewModel, } from '@jbrowse/plugin-linear-genome-view' +// locals +import YScaleBar from '../shared/YScaleBar' import { WiggleDisplayModel } from './model' export async function renderSvg( diff --git a/plugins/wiggle/src/MultiLinearWiggleDisplay/components/ColorLegend.tsx b/plugins/wiggle/src/MultiLinearWiggleDisplay/components/ColorLegend.tsx index 853a84e290..e4959ebfe7 100644 --- a/plugins/wiggle/src/MultiLinearWiggleDisplay/components/ColorLegend.tsx +++ b/plugins/wiggle/src/MultiLinearWiggleDisplay/components/ColorLegend.tsx @@ -2,7 +2,7 @@ import React from 'react' import { observer } from 'mobx-react' // locals -import { WiggleDisplayModel } from '../models/model' +import { WiggleDisplayModel } from '../model' import RectBg from './RectBg' const ColorLegend = observer(function ({ diff --git a/plugins/wiggle/src/MultiLinearWiggleDisplay/components/ScoreLegend.tsx b/plugins/wiggle/src/MultiLinearWiggleDisplay/components/ScoreLegend.tsx index 3915d838ae..1483529e90 100644 --- a/plugins/wiggle/src/MultiLinearWiggleDisplay/components/ScoreLegend.tsx +++ b/plugins/wiggle/src/MultiLinearWiggleDisplay/components/ScoreLegend.tsx @@ -4,7 +4,7 @@ import { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view' import { observer } from 'mobx-react' // locals -import { WiggleDisplayModel } from '../models/model' +import { WiggleDisplayModel } from '../model' import RectBg from './RectBg' type LGV = LinearGenomeViewModel diff --git a/plugins/wiggle/src/MultiLinearWiggleDisplay/components/WiggleDisplayComponent.tsx b/plugins/wiggle/src/MultiLinearWiggleDisplay/components/WiggleDisplayComponent.tsx index f797e8b78e..d0a68f807c 100644 --- a/plugins/wiggle/src/MultiLinearWiggleDisplay/components/WiggleDisplayComponent.tsx +++ b/plugins/wiggle/src/MultiLinearWiggleDisplay/components/WiggleDisplayComponent.tsx @@ -3,7 +3,7 @@ import { BaseLinearDisplayComponent } from '@jbrowse/plugin-linear-genome-view' import { observer } from 'mobx-react' // locals -import { WiggleDisplayModel } from '../models/model' +import { WiggleDisplayModel } from '../model' import YScaleBars from './YScaleBars' const MultiLinearWiggleDisplayComponent = observer(function (props: { diff --git a/plugins/wiggle/src/MultiLinearWiggleDisplay/components/YScaleBars.tsx b/plugins/wiggle/src/MultiLinearWiggleDisplay/components/YScaleBars.tsx index 54fb60ed24..e823b5e1c0 100644 --- a/plugins/wiggle/src/MultiLinearWiggleDisplay/components/YScaleBars.tsx +++ b/plugins/wiggle/src/MultiLinearWiggleDisplay/components/YScaleBars.tsx @@ -4,7 +4,7 @@ import { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view' import { observer } from 'mobx-react' // locals -import { WiggleDisplayModel } from '../models/model' +import { WiggleDisplayModel } from '../model' import YScaleBar from '../../shared/YScaleBar' import ColorLegend from './ColorLegend' import ScoreLegend from './ScoreLegend' diff --git a/plugins/wiggle/src/MultiLinearWiggleDisplay/components/util.ts b/plugins/wiggle/src/MultiLinearWiggleDisplay/components/util.ts index 131b34664c..fa91fe9630 100644 --- a/plugins/wiggle/src/MultiLinearWiggleDisplay/components/util.ts +++ b/plugins/wiggle/src/MultiLinearWiggleDisplay/components/util.ts @@ -3,7 +3,7 @@ import { getContainingView, measureText, } from '@jbrowse/core/util' -import { WiggleDisplayModel } from '../models/model' +import { WiggleDisplayModel } from '../model' import { getConf } from '@jbrowse/core/configuration' import { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view' diff --git a/plugins/wiggle/src/MultiLinearWiggleDisplay/models/configSchema.ts b/plugins/wiggle/src/MultiLinearWiggleDisplay/configSchema.ts similarity index 96% rename from plugins/wiggle/src/MultiLinearWiggleDisplay/models/configSchema.ts rename to plugins/wiggle/src/MultiLinearWiggleDisplay/configSchema.ts index 56262b145f..f8f079f334 100644 --- a/plugins/wiggle/src/MultiLinearWiggleDisplay/models/configSchema.ts +++ b/plugins/wiggle/src/MultiLinearWiggleDisplay/configSchema.ts @@ -3,7 +3,7 @@ import { types } from 'mobx-state-tree' import PluginManager from '@jbrowse/core/PluginManager' // locals -import sharedWiggleConfigFactory from '../../shared/SharedWiggleConfigSchema' +import sharedWiggleConfigFactory from '../shared/SharedWiggleConfigSchema' /** * #config MultiLinearWiggleDisplay diff --git a/plugins/wiggle/src/MultiLinearWiggleDisplay/index.ts b/plugins/wiggle/src/MultiLinearWiggleDisplay/index.ts index b4e9c9e0d6..ee56272b17 100644 --- a/plugins/wiggle/src/MultiLinearWiggleDisplay/index.ts +++ b/plugins/wiggle/src/MultiLinearWiggleDisplay/index.ts @@ -1,8 +1,8 @@ import PluginManager from '@jbrowse/core/PluginManager' import DisplayType from '@jbrowse/core/pluggableElementTypes/DisplayType' -import configSchemaFactory from './models/configSchema' -import modelFactory from './models/model' +import configSchemaFactory from './configSchema' +import modelFactory from './model' import { lazy } from 'react' export default function MultiLinearWiggleDisplayF( diff --git a/plugins/wiggle/src/MultiLinearWiggleDisplay/models/model.ts b/plugins/wiggle/src/MultiLinearWiggleDisplay/model.ts similarity index 97% rename from plugins/wiggle/src/MultiLinearWiggleDisplay/models/model.ts rename to plugins/wiggle/src/MultiLinearWiggleDisplay/model.ts index be50c3714a..daeb624359 100644 --- a/plugins/wiggle/src/MultiLinearWiggleDisplay/models/model.ts +++ b/plugins/wiggle/src/MultiLinearWiggleDisplay/model.ts @@ -24,15 +24,15 @@ import { } from '@jbrowse/plugin-linear-genome-view' // locals -import { getScale, YSCALEBAR_LABEL_OFFSET } from '../../util' -import SharedWiggleMixin from '../../shared/SharedWiggleMixin' +import { getScale, YSCALEBAR_LABEL_OFFSET } from '../util' +import SharedWiggleMixin from '../shared/SharedWiggleMixin' const randomColor = () => '#000000'.replaceAll('0', () => (~~(Math.random() * 16)).toString(16)) // lazies -const Tooltip = lazy(() => import('../components/Tooltip')) -const SetColorDialog = lazy(() => import('../components/SetColorDialog')) +const Tooltip = lazy(() => import('./components/Tooltip')) +const SetColorDialog = lazy(() => import('./components/SetColorDialog')) // using a map because it preserves order const rendererTypes = new Map([ @@ -458,7 +458,7 @@ export function stateModelFactory( // eslint-disable-next-line @typescript-eslint/no-floating-promises ;(async () => { const { quantitativeStatsAutorun } = await import( - '../../quantitativeStatsAutorun' + '../quantitativeStatsAutorun' ) quantitativeStatsAutorun(self) addDisposer( diff --git a/plugins/wiggle/src/MultiLinearWiggleDisplay/models/renderSvg.tsx b/plugins/wiggle/src/MultiLinearWiggleDisplay/renderSvg.tsx similarity index 94% rename from plugins/wiggle/src/MultiLinearWiggleDisplay/models/renderSvg.tsx rename to plugins/wiggle/src/MultiLinearWiggleDisplay/renderSvg.tsx index a83a0416f4..4dbe78db8c 100644 --- a/plugins/wiggle/src/MultiLinearWiggleDisplay/models/renderSvg.tsx +++ b/plugins/wiggle/src/MultiLinearWiggleDisplay/renderSvg.tsx @@ -8,7 +8,7 @@ import { // locals import { WiggleDisplayModel } from './model' -import YScaleBars from '../components/YScaleBars' +import YScaleBars from './components/YScaleBars' export async function renderSvg( self: WiggleDisplayModel, diff --git a/plugins/wiggle/src/index.ts b/plugins/wiggle/src/index.ts index ba6c2912ea..cd1bbdc804 100644 --- a/plugins/wiggle/src/index.ts +++ b/plugins/wiggle/src/index.ts @@ -126,6 +126,6 @@ export { ReactComponent as LinearWiggleDisplayReactComponent, modelFactory as linearWiggleDisplayModelFactory, } from './LinearWiggleDisplay' -export { type TooltipContentsComponent } from './Tooltip' +export type { TooltipContentsComponent } from './Tooltip' export { default as WiggleBaseRenderer } from './WiggleBaseRenderer' diff --git a/plugins/wiggle/src/quantitativeStatsAutorun.ts b/plugins/wiggle/src/quantitativeStatsAutorun.ts index 6a9772414b..8b2fa6e16d 100644 --- a/plugins/wiggle/src/quantitativeStatsAutorun.ts +++ b/plugins/wiggle/src/quantitativeStatsAutorun.ts @@ -36,11 +36,9 @@ export function quantitativeStatsAutorun(self: { const view = getContainingView(self) as LGV self.setLoading(aborter) - console.log(self.quantitativeStatsReady, 'wow') if (!self.quantitativeStatsReady) { return } - console.log(self.quantitativeStatsReady, 'past') const statsRegion = JSON.stringify(view.dynamicBlocks) const wiggleStats = await getQuantitativeStats(self, { diff --git a/plugins/wiggle/src/shared/SharedWiggleMixin.ts b/plugins/wiggle/src/shared/SharedWiggleMixin.ts index 90753e69ce..6cdf978845 100644 --- a/plugins/wiggle/src/shared/SharedWiggleMixin.ts +++ b/plugins/wiggle/src/shared/SharedWiggleMixin.ts @@ -6,15 +6,11 @@ import { } from '@jbrowse/core/configuration' import { Feature, - getContainingView, getEnv, getSession, isSelectionContainer, } from '@jbrowse/core/util' -import { - BaseLinearDisplay, - LinearGenomeViewModel, -} from '@jbrowse/plugin-linear-genome-view' +import { BaseLinearDisplay } from '@jbrowse/plugin-linear-genome-view' import { types } from 'mobx-state-tree' // locals From 92023f8b8783c7293fd09400ce36a8f56706ae71 Mon Sep 17 00:00:00 2001 From: Colin Date: Wed, 13 Nov 2024 02:51:40 -0500 Subject: [PATCH 4/4] Reduce calculations on change height --- .../alignments/src/BamAdapter/BamAdapter.ts | 1 - .../src/LinearSNPCoverageDisplay/model.ts | 61 +++--- .../wiggle/src/LinearWiggleDisplay/model.ts | 132 +++++++------ .../src/MultiLinearWiggleDisplay/model.ts | 182 +++++++++--------- .../wiggle/src/quantitativeStatsAutorun.ts | 8 +- 5 files changed, 209 insertions(+), 175 deletions(-) diff --git a/plugins/alignments/src/BamAdapter/BamAdapter.ts b/plugins/alignments/src/BamAdapter/BamAdapter.ts index 3c03fb05eb..33788a5c3f 100644 --- a/plugins/alignments/src/BamAdapter/BamAdapter.ts +++ b/plugins/alignments/src/BamAdapter/BamAdapter.ts @@ -207,7 +207,6 @@ export default class BamAdapter extends BaseFeatureDataAdapter { if (tagFilter) { const readVal = record.tags[tagFilter.tag] const filterVal = tagFilter.value - console.log({ readVal, filterVal }) if ( filterVal === '*' ? readVal === undefined diff --git a/plugins/alignments/src/LinearSNPCoverageDisplay/model.ts b/plugins/alignments/src/LinearSNPCoverageDisplay/model.ts index b70f15fdaa..3a987b8c9c 100644 --- a/plugins/alignments/src/LinearSNPCoverageDisplay/model.ts +++ b/plugins/alignments/src/LinearSNPCoverageDisplay/model.ts @@ -135,7 +135,7 @@ function stateModelFactory( }, })) .views(self => { - const { renderProps: superRenderProps } = self + const { adapterProps: superAdapterProps } = self return { /** * #getter @@ -196,36 +196,16 @@ function stateModelFactory( ) }, - /** - * #getter - */ - get renderReady() { - const superProps = superRenderProps() - return !superProps.notReady && self.modificationsReady - }, - - /** - * #getter - */ - get ready() { - return this.renderReady - }, - /** * #method */ - renderProps() { - const superProps = superRenderProps() - const { filters, colorBy, filterBy, visibleModifications } = self + adapterProps() { + const superProps = superAdapterProps() + const { filters, filterBy } = self return { ...superProps, - notReady: !this.ready, filters, - colorBy, filterBy, - visibleModifications: Object.fromEntries( - visibleModifications.toJSON(), - ), } }, } @@ -288,8 +268,39 @@ function stateModelFactory( })) .views(self => { - const { trackMenuItems: superTrackMenuItems } = self + const { + renderProps: superRenderProps, + trackMenuItems: superTrackMenuItems, + } = self return { + /** + * #getter + */ + get renderReady() { + const superProps = superRenderProps() + return !superProps.notReady && self.modificationsReady + }, + + /** + * #getter + */ + get ready() { + return this.renderReady + }, + /** + * #method + */ + renderProps() { + const { colorBy, visibleModifications } = self + return { + ...superRenderProps(), + notReady: !this.ready, + colorBy, + visibleModifications: Object.fromEntries( + visibleModifications.toJSON(), + ), + } + }, /** * #getter */ diff --git a/plugins/wiggle/src/LinearWiggleDisplay/model.ts b/plugins/wiggle/src/LinearWiggleDisplay/model.ts index b502b7c6fe..0ffd02604b 100644 --- a/plugins/wiggle/src/LinearWiggleDisplay/model.ts +++ b/plugins/wiggle/src/LinearWiggleDisplay/model.ts @@ -71,61 +71,33 @@ function stateModelFactory( } return rendererType }, - })) - - .views(self => ({ - /** - * #getter - */ - get ticks() { - const { scaleType, domain, height } = self - const minimalTicks = getConf(self, 'minimalTicks') - const inverted = getConf(self, 'inverted') - const range = [height - YSCALEBAR_LABEL_OFFSET, YSCALEBAR_LABEL_OFFSET] - if (!domain) { - return undefined - } - const scale = getScale({ - scaleType, - domain, - range, - inverted, - }) - const ticks = axisPropsFromTickScale(scale, 4) - return height < 100 || minimalTicks - ? { ...ticks, values: domain } - : ticks - }, /** * #getter */ - get quantitativeStatsReleventToCurrentZoom() { + get quantitativeStatsRelevantToCurrentZoom() { const view = getContainingView(self) as LinearGenomeViewModel return self.stats?.currStatsBpPerPx === view.bpPerPx }, })) + .views(self => { const { renderProps: superRenderProps } = self return { /** * #method */ - renderProps() { + adapterProps() { const superProps = superRenderProps() - const { filters, ticks, height, resolution, scaleOpts } = self + const { filters, resolution, scaleOpts } = self return { ...superProps, - notReady: - superProps.notReady || - !self.quantitativeStatsReleventToCurrentZoom, + rpcDriverName: self.rpcDriverName, displayModel: self, config: self.rendererConfig, displayCrossHatches: self.displayCrossHatchesSetting, scaleOpts, resolution, - height, - ticks, filters, } }, @@ -133,36 +105,78 @@ function stateModelFactory( /** * #getter */ - get needsScalebar() { - const { rendererTypeName: type } = self - return type === 'XYPlotRenderer' || type === 'LinePlotRenderer' - }, - /** - * #getter - */ - get fillSetting() { - if (self.filled) { - return 0 - } else if (self.minSize === 1) { - return 1 - } else { - return 2 + get ticks() { + const { scaleType, domain, height } = self + const minimalTicks = getConf(self, 'minimalTicks') + const inverted = getConf(self, 'inverted') + const range = [ + height - YSCALEBAR_LABEL_OFFSET, + YSCALEBAR_LABEL_OFFSET, + ] + if (!domain) { + return undefined } - }, - /** - * #getter - */ - get quantitativeStatsReady() { - const view = getContainingView(self) as LinearGenomeViewModel - return ( - view.initialized && - self.featureDensityStatsReady && - !self.regionTooLarge && - !self.error - ) + const scale = getScale({ + scaleType, + domain, + range, + inverted, + }) + const ticks = axisPropsFromTickScale(scale, 4) + return height < 100 || minimalTicks + ? { ...ticks, values: domain } + : ticks }, } }) + .views(self => ({ + /** + * #method + */ + renderProps() { + const { ticks, height } = self + const superProps = self.adapterProps() + return { + ...self.adapterProps(), + notReady: + superProps.notReady || !self.quantitativeStatsRelevantToCurrentZoom, + height, + ticks, + } + }, + + /** + * #getter + */ + get needsScalebar() { + const { rendererTypeName: type } = self + return type === 'XYPlotRenderer' || type === 'LinePlotRenderer' + }, + /** + * #getter + */ + get fillSetting() { + if (self.filled) { + return 0 + } else if (self.minSize === 1) { + return 1 + } else { + return 2 + } + }, + /** + * #getter + */ + get quantitativeStatsReady() { + const view = getContainingView(self) as LinearGenomeViewModel + return ( + view.initialized && + self.featureDensityStatsReady && + !self.regionTooLarge && + !self.error + ) + }, + })) .views(self => { const { trackMenuItems: superTrackMenuItems } = self const hasRenderings = getConf(self, 'defaultRendering') diff --git a/plugins/wiggle/src/MultiLinearWiggleDisplay/model.ts b/plugins/wiggle/src/MultiLinearWiggleDisplay/model.ts index daeb624359..cdf142aafe 100644 --- a/plugins/wiggle/src/MultiLinearWiggleDisplay/model.ts +++ b/plugins/wiggle/src/MultiLinearWiggleDisplay/model.ts @@ -258,119 +258,129 @@ export function stateModelFactory( ) }, })) - .views(self => ({ - /** - * #getter - */ - get ticks() { - const { scaleType, domain, isMultiRow, rowHeight, useMinimalTicks } = - self - - if (!domain) { - return undefined - } - - const offset = isMultiRow ? 0 : YSCALEBAR_LABEL_OFFSET - const ticks = axisPropsFromTickScale( - getScale({ - scaleType, - domain, - range: [rowHeight - offset, offset], - inverted: getConf(self, 'inverted') as boolean, - }), - 4, - ) - return useMinimalTicks ? { ...ticks, values: domain } : ticks - }, - - /** - * #getter - */ - get colors() { - return [ - 'red', - 'blue', - 'green', - 'orange', - 'purple', - 'cyan', - 'pink', - 'darkblue', - 'darkred', - 'pink', - ] - }, - })) .views(self => { const { renderProps: superRenderProps } = self return { /** * #method */ - renderProps() { + adapterProps() { const superProps = superRenderProps() - const { - displayCrossHatches, - filters, - height, - resolution, - rpcDriverName, - scaleOpts, - stats, - sources, - ticks, - rendererConfig: config, - } = self return { ...superProps, - notReady: superProps.notReady || !sources || !stats, displayModel: self, - config, - displayCrossHatches, - filters, - height, - resolution, - rpcDriverName, - scaleOpts, - sources, - ticks, - onMouseMove: (_: unknown, f: Feature) => { - self.setFeatureUnderMouse(f) - }, - onMouseLeave: () => { - self.setFeatureUnderMouse(undefined) - }, + config: self.rendererConfig, + filters: self.filters, + resolution: self.resolution, + rpcDriverName: self.rpcDriverName, + sources: self.sources, } }, - /** * #getter */ - get hasResolution() { - return self.adapterCapabilities.includes('hasResolution') + get ticks() { + const { scaleType, domain, isMultiRow, rowHeight, useMinimalTicks } = + self + + if (!domain) { + return undefined + } + + const offset = isMultiRow ? 0 : YSCALEBAR_LABEL_OFFSET + const ticks = axisPropsFromTickScale( + getScale({ + scaleType, + domain, + range: [rowHeight - offset, offset], + inverted: getConf(self, 'inverted') as boolean, + }), + 4, + ) + return useMinimalTicks ? { ...ticks, values: domain } : ticks }, /** * #getter */ - get hasGlobalStats() { - return self.adapterCapabilities.includes('hasGlobalStats') + get colors() { + return [ + 'red', + 'blue', + 'green', + 'orange', + 'purple', + 'cyan', + 'pink', + 'darkblue', + 'darkred', + 'pink', + ] }, - /** * #getter */ - get fillSetting() { - if (self.filled) { - return 0 - } else if (self.minSize === 1) { - return 1 - } else { - return 2 - } + get quantitativeStatsRelevantToCurrentZoom() { + const view = getContainingView(self) as LinearGenomeViewModel + return self.stats?.currStatsBpPerPx === view.bpPerPx }, } }) + .views(self => ({ + /** + * #method + */ + renderProps() { + const superProps = self.adapterProps() + return { + ...superProps, + notReady: + superProps.notReady || + !self.sources || + !self.quantitativeStatsRelevantToCurrentZoom, + displayModel: self, + rpcDriverName: self.rpcDriverName, + displayCrossHatches: self.displayCrossHatches, + height: self.height, + ticks: self.ticks, + stats: self.stats, + scaleOpts: self.scaleOpts, + onMouseMove: (_: unknown, f: Feature) => { + self.setFeatureUnderMouse(f) + }, + onMouseLeave: () => { + self.setFeatureUnderMouse(undefined) + }, + } + }, + + /** + * #getter + */ + get hasResolution() { + return self.adapterCapabilities.includes('hasResolution') + }, + + /** + * #getter + */ + get hasGlobalStats() { + return self.adapterCapabilities.includes('hasGlobalStats') + }, + + /** + * #getter + */ + get fillSetting() { + if (self.filled) { + return 0 + } else if (self.minSize === 1) { + return 1 + } else { + return 2 + } + }, + })) .views(self => { const { trackMenuItems: superTrackMenuItems } = self const hasRenderings = getConf(self, 'defaultRendering') diff --git a/plugins/wiggle/src/quantitativeStatsAutorun.ts b/plugins/wiggle/src/quantitativeStatsAutorun.ts index 8b2fa6e16d..edd5ef83e4 100644 --- a/plugins/wiggle/src/quantitativeStatsAutorun.ts +++ b/plugins/wiggle/src/quantitativeStatsAutorun.ts @@ -1,4 +1,6 @@ import { autorun } from 'mobx' +import { addDisposer, isAlive } from 'mobx-state-tree' +// jbrowse import { isAbortException, getSession, @@ -6,8 +8,6 @@ import { } from '@jbrowse/core/util' import { QuantitativeStats } from '@jbrowse/core/util/stats' import { getRpcSessionId } from '@jbrowse/core/util/tracks' -import { addDisposer, isAlive } from 'mobx-state-tree' - import { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view' import { AnyConfigurationModel, getConf } from '@jbrowse/core/configuration' @@ -21,7 +21,7 @@ export function quantitativeStatsAutorun(self: { stats: QuantitativeStats, statsRegion: string, ) => void - renderProps: () => Record + adapterProps: () => Record configuration: AnyConfigurationModel adapterConfig: AnyConfigurationModel autoscaleType: string @@ -45,7 +45,7 @@ export function quantitativeStatsAutorun(self: { signal: aborter.signal, filters: [], currStatsBpPerPx: view.bpPerPx, - ...self.renderProps(), + ...self.adapterProps(), }) if (isAlive(self)) {