diff --git a/plugins/gccontent/src/GCContentAdapter/GCContentAdapter.ts b/plugins/gccontent/src/GCContentAdapter/GCContentAdapter.ts index ffcee6b34c..9d09f34791 100644 --- a/plugins/gccontent/src/GCContentAdapter/GCContentAdapter.ts +++ b/plugins/gccontent/src/GCContentAdapter/GCContentAdapter.ts @@ -4,8 +4,14 @@ import { } from '@jbrowse/core/data_adapters/BaseAdapter' import { firstValueFrom } from 'rxjs' import { ObservableCreate } from '@jbrowse/core/util/rxjs' -import { SimpleFeature, Feature, Region } from '@jbrowse/core/util' +import { + SimpleFeature, + Feature, + Region, + updateStatus, +} from '@jbrowse/core/util' import { toArray } from 'rxjs/operators' +import { checkStopToken } from '@jbrowse/core/util/stopToken' export default class GCContentAdapter extends BaseFeatureDataAdapter { private gcMode = 'content' @@ -26,6 +32,7 @@ export default class GCContentAdapter extends BaseFeatureDataAdapter { } public getFeatures(query: Region, opts: BaseOptions) { + const { statusCallback = () => {}, stopToken } = opts || {} return ObservableCreate(async observer => { const sequenceAdapter = await this.configure() const windowSize = this.getConf('windowSize') @@ -42,50 +49,61 @@ export default class GCContentAdapter extends BaseFeatureDataAdapter { return } - const ret = sequenceAdapter.getFeatures( - { - ...query, - start: queryStart, - end: queryEnd, - }, - opts, + const feats = await firstValueFrom( + sequenceAdapter + .getFeatures( + { + ...query, + start: queryStart, + end: queryEnd, + }, + opts, + ) + .pipe(toArray()), ) - const feats = await firstValueFrom(ret.pipe(toArray())) const residues = feats[0]?.get('seq') || '' - for (let i = hw; i < residues.length - hw; i += windowDelta) { - const r = f ? residues[i] : residues.slice(i - hw, i + hw) - let nc = 0 - let ng = 0 - let len = 0 - for (const letter of r) { - if (letter === 'c' || letter === 'C') { - nc++ - } else if (letter === 'g' || letter === 'G') { - ng++ + let start = performance.now() + await updateStatus('Calculating GC', statusCallback, () => { + for (let i = hw; i < residues.length - hw; i += windowDelta) { + if (performance.now() - start > 400) { + checkStopToken(stopToken) + start = performance.now() } - if (letter !== 'N') { - len++ + const r = f ? residues[i] : residues.slice(i - hw, i + hw) + let nc = 0 + let ng = 0 + let len = 0 + for (const letter of r) { + if (letter === 'c' || letter === 'C') { + nc++ + } else if (letter === 'g' || letter === 'G') { + ng++ + } + if (letter !== 'N') { + len++ + } } + const pos = queryStart + const score = + this.gcMode === 'content' + ? (ng + nc) / (len || 1) + : this.gcMode === 'skew' + ? (ng - nc) / (ng + nc || 1) + : 0 + + observer.next( + new SimpleFeature({ + uniqueId: `${this.id}_${pos + i}`, + refName: query.refName, + start: pos + i, + end: pos + i + windowDelta, + score, + }), + ) } - const pos = queryStart - const score = - this.gcMode === 'content' - ? (ng + nc) / (len || 1) - : this.gcMode === 'skew' - ? (ng - nc) / (ng + nc || 1) - : 0 + }) - observer.next( - new SimpleFeature({ - uniqueId: `${this.id}_${pos + i}`, - refName: query.refName, - start: pos + i, - end: pos + i + windowDelta, - score, - }), - ) - } observer.complete() }) } diff --git a/plugins/wiggle/src/getQuantitativeStatsAutorun.ts b/plugins/wiggle/src/getQuantitativeStatsAutorun.ts index 83f6f5cd9a..abe0924f05 100644 --- a/plugins/wiggle/src/getQuantitativeStatsAutorun.ts +++ b/plugins/wiggle/src/getQuantitativeStatsAutorun.ts @@ -1,7 +1,7 @@ import { autorun } from 'mobx' import { addDisposer, isAlive } from 'mobx-state-tree' // jbrowse -import { getContainingView } from '@jbrowse/core/util' +import { getContainingView, isAbortException } from '@jbrowse/core/util' import { QuantitativeStats } from '@jbrowse/core/util/stats' import { LinearGenomeViewModel } from '@jbrowse/plugin-linear-genome-view' import { AnyConfigurationModel } from '@jbrowse/core/configuration' @@ -44,8 +44,8 @@ export function getQuantitativeStatsAutorun(self: { } } } catch (e) { - console.error(e) - if (isAlive(self)) { + if (isAlive(self) && !isAbortException(e)) { + console.error(e) self.setError(e) } } diff --git a/plugins/wiggle/src/shared/SharedWiggleMixin.ts b/plugins/wiggle/src/shared/SharedWiggleMixin.ts index 896e367c9a..bfe2f20d2e 100644 --- a/plugins/wiggle/src/shared/SharedWiggleMixin.ts +++ b/plugins/wiggle/src/shared/SharedWiggleMixin.ts @@ -16,6 +16,7 @@ import { types } from 'mobx-state-tree' // locals import { getNiceDomain } from '../util' import { lazy } from 'react' +import { stopStopToken } from '@jbrowse/core/util/stopToken' // lazies const SetMinMaxDialog = lazy(() => import('./SetMinMaxDialog')) @@ -155,8 +156,11 @@ export default function SharedWiggleMixin( /** * #action */ - setStatsLoading() { - /* do nothing */ + setStatsLoading(arg?: string) { + if (self.statsFetchInProgress) { + stopStopToken(self.statsFetchInProgress) + } + self.statsFetchInProgress = arg }, /**