Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Variant fixes #9

Merged
merged 3 commits into from
Jan 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 40 additions & 20 deletions src/main/ResolutionCache.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,10 @@ import _ from 'underscore';
import Interval from './Interval';
import ContigInterval from './ContigInterval';

type ResolutionObject<T: Object> = {
resolution: number;
object: T;
}

class ResolutionCache<T: Object> {
coveredRanges: ResolutionCacheKey[];
cache: {[key: string]: ResolutionObject<T>};
cache: {[resolution: number]: {[key: string]: T}};
// used to filter out elements in the cache based on resolution.
filterFunction: Function; // should take form (range: ContigInterval<string>, T) => boolean;
keyFunction: Function; // should take form (d: T) => string;
Expand All @@ -35,19 +31,41 @@ class ResolutionCache<T: Object> {
if (!range) return [];
var res = {};
if (!resolution) {
res = _.map(_.filter(this.cache, d => this.filterFunction(range, d.object)),
obj => obj.object);
res = _.filter(this.cache[1], d => this.filterFunction(range, d));
} else {
res = _.map(_.filter(this.cache, d => this.filterFunction(range, d.object) && d.resolution == resolution),
obj => obj.object);
res = _.filter(this.cache[resolution], d => this.filterFunction(range, d));
}

return res;
}

/**
* Find the disjoint subintervals not covered by any interval in the list with the same resolution.
*
* If comp = interval.complementIntervals(ranges), then this guarantees that:
* - comp union ranges = interval
* - a int b = 0 forall a \in comp, b in ranges
*
* (The input ranges need not be disjoint.)
*/
complementInterval(range: ContigInterval<string>, resolution: ?number): ContigInterval<string>[] {
if (!resolution) {
resolution = ResolutionCache.getResolution(range.interval);
}

// filter ranges by correct resolution
var resolutionIntervals = _.filter(this.coveredRanges, r => r.resolution == resolution)
.map(r => r.contigInterval);

return range.complementIntervals(resolutionIntervals);

}

// puts new ranges into list of ranges covered by cache
coverRange(range: ContigInterval<string>) {
var resolution = ResolutionCache.getResolution(range.interval);
coverRange(range: ContigInterval<string>, resolution: ?number) {
if (!resolution) {
resolution = ResolutionCache.getResolution(range.interval);
}
var resolvedRange = new ResolutionCacheKey(range, resolution);
this.coveredRanges.push(resolvedRange);
// coalesce new contigIntervals
Expand All @@ -59,13 +77,13 @@ class ResolutionCache<T: Object> {
if (!resolution) {
resolution = 1;
}
var resObject = {
resolution: resolution,
object: value
};
var key = this.keyFunction(value);
if (!this.cache[key]) {
this.cache[key] = resObject;

// initialize cache resolution, if not already initialized
if (!this.cache[resolution]) this.cache[resolution] = {};

if (!this.cache[resolution][key]) {
this.cache[resolution][key] = value;
}
}

Expand Down Expand Up @@ -101,11 +119,13 @@ class ResolutionCache<T: Object> {
* - For regions >= 1,000,000, bin 1000 bp into 1 (return 1000)
*/
static getResolution(range: Interval): number {
if (range.length() < 10000)
// subtract one because length() adds one
var rangeLength = range.length() - 1;
if (rangeLength < 10000)
return 1;
else if (range.length() >= 10000 && range.length() < 100000 )
else if (rangeLength >= 10000 && rangeLength < 100000 )
return 10;
else if (range.length() >= 100000 && range.length() < 1000000 )
else if (rangeLength >= 100000 && rangeLength < 1000000 )
return 100;
else
return 1000;
Expand Down
32 changes: 0 additions & 32 deletions src/main/data/GenotypeEndpoint.js

This file was deleted.

27 changes: 0 additions & 27 deletions src/main/data/VariantEndpoint.js

This file was deleted.

6 changes: 6 additions & 0 deletions src/main/data/vcf.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ export type Variant = {
end: number;
}

// holds variant and genotype sample ids
export type VariantContext = {
variant: Variant,
sampleIds: string[]
}

// This is a minimally-parsed line for facilitating binary search.
type LocusLine = {
contig: string;
Expand Down
2 changes: 0 additions & 2 deletions src/main/pileup.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import ReferenceDataSource from './sources/ReferenceDataSource';
import BigBedDataSource from './sources/BigBedDataSource';
import VcfDataSource from './sources/VcfDataSource';
import VariantDataSource from './sources/VariantDataSource';
import GenotypeDataSource from './sources/GenotypeDataSource';
import BamDataSource from './sources/BamDataSource';
import GA4GHDataSource from './sources/GA4GHDataSource';
import CoverageDataSource from './sources/CoverageDataSource';
Expand Down Expand Up @@ -132,7 +131,6 @@ var pileup = {
ga4gh: GA4GHDataSource.create,
vcf: VcfDataSource.create,
variants: VariantDataSource.create,
genotypes: GenotypeDataSource.create,
features: FeatureDataSource.create,
twoBit: TwoBitDataSource.create,
reference: ReferenceDataSource.create,
Expand Down
43 changes: 23 additions & 20 deletions src/main/sources/CoverageDataSource.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,30 +72,33 @@ function createFromCoverageUrl(remoteSource: RemoteRequest): CoverageDataSource
var resolution = ResolutionCache.getResolution(interval.interval);
var endpointModifier = `binning=${resolution}`;

// get all smaller intervals not yet covered in cache
var newRanges = cache.complementInterval(interval, resolution);

// Cover the range immediately to prevent duplicate fetches.
cache.coverRange(interval);
var numRequests = 1;
o.trigger('networkprogress', {numRequests});
return remoteSource.getFeaturesInRange(interval, endpointModifier).then(json => {
var response = json.response;
if (json.status >= 400) {
notifyFailure(json.status + ' ' + json.statusText + ' ' + JSON.stringify(response));
} else {
if (response.errorCode) {
notifyFailure('Error from CoverageDataSource: ' + JSON.stringify(response));
o.trigger('networkprogress', newRanges.length);
return Q.all(newRanges.map(range =>
remoteSource.getFeaturesInRange(range, endpointModifier).then(json => {
var response = json.response;
if (json.status >= 400) {
notifyFailure(json.status + ' ' + json.statusText + ' ' + JSON.stringify(response));
} else {
// add new data to cache
response.forEach(p => cache.put({
"contig": range.contig,
"start": p.start,
"end": p.end,
"count": p.count
}, resolution));
o.trigger('newdata', interval);
if (response.errorCode) {
notifyFailure('Error from CoverageDataSource: ' + JSON.stringify(response));
} else {
// add new data to cache
response.forEach(p => cache.put({
"contig": range.contig,
"start": p.start,
"end": p.end,
"count": p.count
}, resolution));
o.trigger('newdata', interval);
}
}
}
o.trigger('networkdone');
});
o.trigger('networkdone');
})));
}

function getCoverageInRange(range: ContigInterval<string>,
Expand Down
122 changes: 0 additions & 122 deletions src/main/sources/GenotypeDataSource.js

This file was deleted.

Loading