@jbrowse/core
Version:
JBrowse 2 core libraries used by plugins
116 lines (115 loc) • 4.79 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.BaseFeatureDataAdapter = void 0;
const rxjs_1 = require("rxjs");
const operators_1 = require("rxjs/operators");
const BaseAdapter_1 = require("./BaseAdapter");
const util_1 = require("../../util");
const rxjs_2 = require("../../util/rxjs");
const stats_1 = require("../../util/stats");
const stopToken_1 = require("../../util/stopToken");
class BaseFeatureDataAdapter extends BaseAdapter_1.BaseAdapter {
async getHeader(_opts) {
return null;
}
async getMetadata(_opts) {
return null;
}
getFeaturesInRegion(region, opts = {}) {
return (0, rxjs_2.ObservableCreate)(async (observer) => {
const hasData = await this.hasDataForRefName(region.refName, opts);
(0, stopToken_1.checkStopToken)(opts.stopToken);
if (!hasData) {
observer.complete();
}
else {
this.getFeatures(region, opts).subscribe(observer);
}
});
}
getFeaturesInMultipleRegions(regions, opts = {}) {
return (0, rxjs_1.merge)(...regions.map(region => this.getFeaturesInRegion(region, opts)));
}
async hasDataForRefName(refName, opts = {}) {
const refNames = await this.getRefNames(opts);
return refNames.includes(refName);
}
async getRegionQuantitativeStats(region, opts) {
const feats = this.getFeatures(region, opts);
return (0, stats_1.scoresToStats)(region, feats);
}
async getMultiRegionQuantitativeStats(regions = [], opts) {
if (!regions.length) {
return (0, stats_1.blankStats)();
}
const feats = await Promise.all(regions.map(region => this.getRegionQuantitativeStats(region, opts)));
const scoreMax = (0, util_1.max)(feats.map(a => a.scoreMax));
const scoreMin = (0, util_1.min)(feats.map(a => a.scoreMin));
const scoreSum = (0, util_1.sum)(feats.map(a => a.scoreSum));
const scoreSumSquares = (0, util_1.sum)(feats.map(a => a.scoreSumSquares));
const featureCount = (0, util_1.sum)(feats.map(a => a.featureCount));
const basesCovered = (0, util_1.sum)(feats.map(a => a.basesCovered));
return (0, stats_1.rectifyStats)({
scoreMin,
scoreMax,
featureCount,
basesCovered,
scoreSumSquares,
scoreSum,
});
}
getRegionFeatureDensityStats(region, opts) {
let lastTime = +Date.now();
const statsFromInterval = async (length, expansionTime) => {
const { start, end } = region;
const sampleCenter = start * 0.75 + end * 0.25;
const features = await (0, rxjs_1.firstValueFrom)(this.getFeatures({
...region,
start: Math.max(0, Math.round(sampleCenter - length / 2)),
end: Math.min(Math.round(sampleCenter + length / 2), end),
}, opts).pipe((0, operators_1.toArray)()));
return maybeRecordStats({
interval: length,
statsSampleFeatures: features.length,
expansionTime,
stats: {
featureDensity: features.length / length,
},
});
};
const maybeRecordStats = async ({ interval, stats, statsSampleFeatures, expansionTime, }) => {
const refLen = region.end - region.start;
if (statsSampleFeatures >= 70 || interval * 2 > refLen) {
return stats;
}
else if (expansionTime <= 5000) {
const currTime = +Date.now();
expansionTime += currTime - lastTime;
lastTime = currTime;
return statsFromInterval(interval * 2, expansionTime);
}
else {
console.warn("Stats estimation reached timeout, or didn't get enough features");
return { featureDensity: Number.POSITIVE_INFINITY };
}
};
return statsFromInterval(1000, 0);
}
async getMultiRegionFeatureDensityStats(regions, opts) {
if (!regions.length) {
throw new Error('No regions supplied');
}
return this.getRegionFeatureDensityStats(regions[0], opts);
}
async getSources(regions) {
const features = await (0, rxjs_1.firstValueFrom)(this.getFeaturesInMultipleRegions(regions).pipe((0, operators_1.toArray)()));
const sources = new Set();
for (const f of features) {
sources.add(f.get('source'));
}
return [...sources].map(source => ({
name: source,
}));
}
}
exports.BaseFeatureDataAdapter = BaseFeatureDataAdapter;