@teselagen/range-utils 0.3.14-beta.3 → 0.3.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/adjustRangeToDeletionOfAnotherRange.d.ts +1 -2
- package/adjustRangeToInsert.d.ts +1 -2
- package/adjustRangeToRotation.d.ts +1 -5
- package/checkIfNonCircularRangesOverlap.d.ts +1 -2
- package/checkIfPotentiallyCircularRangesOverlap.d.ts +1 -2
- package/collapseOverlapsGeneratedFromRangeComparisonIfPossible.d.ts +1 -2
- package/convertRangeIndices.d.ts +1 -10
- package/convertRangeTo0Based.d.ts +1 -5
- package/convertRangeTo1Based.d.ts +1 -5
- package/doesRangeSpanEntireSequence.d.ts +1 -2
- package/doesRangeSpanOrigin.d.ts +1 -2
- package/expandOrContractCircularRangeToPosition.d.ts +2 -3
- package/expandOrContractNonCircularRangeToPosition.d.ts +2 -3
- package/expandOrContractRangeByLength.d.ts +1 -5
- package/expandOrContractRangeToPosition.d.ts +2 -3
- package/flipContainedRange.d.ts +1 -5
- package/generateRandomRange.d.ts +3 -3
- package/getAnnotationRangeType.d.ts +1 -2
- package/getEachPositionInRangeAsArray.d.ts +1 -2
- package/getLengthOfOverlappingRegionsBetweenTwoRanges.d.ts +1 -2
- package/getMiddleOfRange.d.ts +1 -2
- package/getOverlapOfNonCircularRanges.d.ts +4 -5
- package/getOverlapsOfPotentiallyCircularRanges.d.ts +1 -2
- package/getPositionFromAngle.d.ts +1 -1
- package/getRangeAngles.d.ts +7 -3
- package/getRangeLength.d.ts +1 -5
- package/getRangesBetweenTwoRanges.d.ts +1 -2
- package/getSequenceWithinRange.d.ts +1 -2
- package/getShortestDistanceBetweenTwoPositions.d.ts +1 -1
- package/getYOffsetForPotentiallyCircularRange.d.ts +1 -2
- package/getYOffsetsForPotentiallyCircularRanges.d.ts +2 -3
- package/getZeroedRangeOverlaps.d.ts +1 -2
- package/index.cjs +41 -52
- package/index.d.ts +0 -1
- package/index.js +41 -52
- package/index.umd.cjs +41 -52
- package/invertRange.d.ts +1 -5
- package/isPositionCloserToRangeStartThanRangeEnd.d.ts +1 -2
- package/isPositionWithinRange.d.ts +2 -3
- package/isRangeOrPositionWithinRange.d.ts +1 -2
- package/isRangeWithinRange.d.ts +1 -2
- package/loopEachPositionInRange.d.ts +1 -2
- package/modulatePositionByRange.d.ts +1 -2
- package/modulateRangeBySequenceLength.d.ts +1 -8
- package/normalizePositionByRangeLength.d.ts +1 -1
- package/normalizePositionByRangeLength1Based.d.ts +1 -1
- package/normalizeRange.d.ts +1 -5
- package/package.json +4 -12
- package/provideInclusiveOptions.d.ts +1 -6
- package/reversePositionInRange.d.ts +1 -1
- package/splitRangeIntoTwoPartsIfItIsCircular.d.ts +3 -4
- package/translateRange.d.ts +1 -5
- package/trimAnnStartEndToFitSeqLength.d.ts +1 -1
- package/trimNonCicularRangeByAnotherNonCircularRange.d.ts +4 -2
- package/trimNumberToFitWithin0ToAnotherNumber.d.ts +1 -1
- package/trimRangeByAnotherRange.d.ts +1 -2
- package/zeroSubrangeByContainerRange.d.ts +1 -2
- package/RangeAngles.d.ts +0 -7
- package/src/RangeAngles.ts +0 -9
- package/src/adjustRangeToDeletionOfAnotherRange.ts +0 -57
- package/src/adjustRangeToInsert.ts +0 -32
- package/src/adjustRangeToRotation.ts +0 -23
- package/src/checkIfNonCircularRangesOverlap.ts +0 -35
- package/src/checkIfPotentiallyCircularRangesOverlap.ts +0 -28
- package/src/collapseOverlapsGeneratedFromRangeComparisonIfPossible.ts +0 -81
- package/src/convertRangeIndices.ts +0 -34
- package/src/convertRangeTo0Based.ts +0 -9
- package/src/convertRangeTo1Based.ts +0 -10
- package/src/doesRangeSpanEntireSequence.ts +0 -12
- package/src/doesRangeSpanOrigin.ts +0 -5
- package/src/expandOrContractCircularRangeToPosition.ts +0 -50
- package/src/expandOrContractNonCircularRangeToPosition.ts +0 -30
- package/src/expandOrContractRangeByLength.ts +0 -18
- package/src/expandOrContractRangeToPosition.ts +0 -16
- package/src/flipContainedRange.ts +0 -156
- package/src/generateRandomRange.ts +0 -26
- package/src/getAnnotationRangeType.ts +0 -30
- package/src/getEachPositionInRangeAsArray.ts +0 -19
- package/src/getLengthOfOverlappingRegionsBetweenTwoRanges.ts +0 -18
- package/src/getMiddleOfRange.ts +0 -11
- package/src/getOverlapOfNonCircularRanges.ts +0 -41
- package/src/getOverlapsOfPotentiallyCircularRanges.ts +0 -60
- package/src/getPositionFromAngle.ts +0 -12
- package/src/getRangeAngles.ts +0 -38
- package/src/getRangeLength.test.ts +0 -30
- package/src/getRangeLength.ts +0 -17
- package/src/getRangesBetweenTwoRanges.ts +0 -42
- package/src/getSequenceWithinRange.test.ts +0 -47
- package/src/getSequenceWithinRange.ts +0 -24
- package/src/getShortestDistanceBetweenTwoPositions.test.ts +0 -12
- package/src/getShortestDistanceBetweenTwoPositions.ts +0 -16
- package/src/getYOffsetForPotentiallyCircularRange.ts +0 -37
- package/src/getYOffsetsForPotentiallyCircularRanges.test.ts +0 -17
- package/src/getYOffsetsForPotentiallyCircularRanges.ts +0 -28
- package/src/getZeroedRangeOverlaps.test.ts +0 -65
- package/src/getZeroedRangeOverlaps.ts +0 -33
- package/src/index.test.ts +0 -39
- package/src/index.ts +0 -53
- package/src/invertRange.ts +0 -25
- package/src/isPositionCloserToRangeStartThanRangeEnd.ts +0 -22
- package/src/isPositionWithinRange.ts +0 -40
- package/src/isRangeOrPositionWithinRange.ts +0 -40
- package/src/isRangeWithinRange.ts +0 -18
- package/src/loopEachPositionInRange.ts +0 -11
- package/src/modulatePositionByRange.ts +0 -15
- package/src/modulateRangeBySequenceLength.ts +0 -13
- package/src/normalizePositionByRangeLength.ts +0 -24
- package/src/normalizePositionByRangeLength1Based.ts +0 -9
- package/src/normalizeRange.ts +0 -12
- package/src/provideInclusiveOptions.ts +0 -79
- package/src/reversePositionInRange.ts +0 -17
- package/src/splitRangeIntoTwoPartsIfItIsCircular.ts +0 -36
- package/src/translateRange.ts +0 -21
- package/src/trimAnnStartEndToFitSeqLength.ts +0 -9
- package/src/trimNonCicularRangeByAnotherNonCircularRange.ts +0 -63
- package/src/trimNumberToFitWithin0ToAnotherNumber.ts +0 -15
- package/src/trimRangeByAnotherRange.ts +0 -103
- package/src/types.ts +0 -12
- package/src/zeroSubrangeByContainerRange.ts +0 -49
- package/types.d.ts +0 -12
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { Range } from "./types";
|
|
2
|
-
import splitRangeIntoTwoPartsIfItIsCircular from "./splitRangeIntoTwoPartsIfItIsCircular";
|
|
3
|
-
import trimRangeByAnotherRange from "./trimRangeByAnotherRange";
|
|
4
|
-
|
|
5
|
-
//takes in two potentially circular ranges and returns the first one trimmed by the second one
|
|
6
|
-
//returns null if no range is left after the trimming
|
|
7
|
-
export default function adjustRangeToDeletionOfAnotherRange(
|
|
8
|
-
rangeToBeAdjusted: Range,
|
|
9
|
-
anotherRange: Range,
|
|
10
|
-
maxLength: number
|
|
11
|
-
) {
|
|
12
|
-
// ac.throw(ac.range, rangeToBeAdjusted)
|
|
13
|
-
// ac.throw(ac.range, anotherRange)
|
|
14
|
-
// ac.throw(ac.posInt, maxLength)
|
|
15
|
-
|
|
16
|
-
const trimmedRange = trimRangeByAnotherRange(
|
|
17
|
-
rangeToBeAdjusted,
|
|
18
|
-
anotherRange,
|
|
19
|
-
maxLength
|
|
20
|
-
);
|
|
21
|
-
if (!trimmedRange) {
|
|
22
|
-
return null; // Explicitly return null when range is completely trimmed
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
//if there is a range left after being trimmed, adjust it by the deleted anotherRange
|
|
26
|
-
//we can make some awesome logical simplifications because we know that the two ranges do not overlap (since we've already trimmed the rangeToBeAdjusted)
|
|
27
|
-
const nonCircularDeletionRanges = splitRangeIntoTwoPartsIfItIsCircular(
|
|
28
|
-
anotherRange,
|
|
29
|
-
maxLength
|
|
30
|
-
);
|
|
31
|
-
nonCircularDeletionRanges.forEach(function (nonCircularDeletionRange) {
|
|
32
|
-
const deletionLength =
|
|
33
|
-
nonCircularDeletionRange.end - nonCircularDeletionRange.start + 1;
|
|
34
|
-
if (trimmedRange.start > trimmedRange.end) {
|
|
35
|
-
//the trimmed range is circular
|
|
36
|
-
if (nonCircularDeletionRange.start < trimmedRange.end) {
|
|
37
|
-
trimmedRange.start -= deletionLength;
|
|
38
|
-
trimmedRange.end -= deletionLength;
|
|
39
|
-
} else if (nonCircularDeletionRange.start < trimmedRange.start) {
|
|
40
|
-
trimmedRange.start -= deletionLength;
|
|
41
|
-
} else {
|
|
42
|
-
//do nothing
|
|
43
|
-
}
|
|
44
|
-
} else {
|
|
45
|
-
if (nonCircularDeletionRange.start < trimmedRange.start) {
|
|
46
|
-
trimmedRange.start -= deletionLength;
|
|
47
|
-
trimmedRange.end -= deletionLength;
|
|
48
|
-
} else if (nonCircularDeletionRange.start < trimmedRange.end) {
|
|
49
|
-
trimmedRange.end -= deletionLength;
|
|
50
|
-
} else {
|
|
51
|
-
//do nothing
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
return trimmedRange;
|
|
57
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { assign } from "lodash-es";
|
|
2
|
-
import { Range } from "./types";
|
|
3
|
-
|
|
4
|
-
export default function adjustRangeToInsert(
|
|
5
|
-
rangeToBeAdjusted: Range,
|
|
6
|
-
insertStart: number,
|
|
7
|
-
insertLength: number
|
|
8
|
-
) {
|
|
9
|
-
// ac.throw([ac.range, ac.posInt, ac.posInt], arguments);
|
|
10
|
-
const newRange = assign({}, rangeToBeAdjusted);
|
|
11
|
-
if (rangeToBeAdjusted.start > rangeToBeAdjusted.end) {
|
|
12
|
-
//circular range
|
|
13
|
-
if (rangeToBeAdjusted.end >= insertStart) {
|
|
14
|
-
//adjust both start and end
|
|
15
|
-
newRange.start += insertLength;
|
|
16
|
-
newRange.end += insertLength;
|
|
17
|
-
} else if (rangeToBeAdjusted.start >= insertStart) {
|
|
18
|
-
//adjust just the start
|
|
19
|
-
newRange.start += insertLength;
|
|
20
|
-
}
|
|
21
|
-
} else {
|
|
22
|
-
if (rangeToBeAdjusted.start >= insertStart) {
|
|
23
|
-
//adjust both start and end
|
|
24
|
-
newRange.start += insertLength;
|
|
25
|
-
newRange.end += insertLength;
|
|
26
|
-
} else if (rangeToBeAdjusted.end >= insertStart) {
|
|
27
|
-
//adjust just the end
|
|
28
|
-
newRange.end += insertLength;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
return newRange;
|
|
32
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { assign } from "lodash-es";
|
|
2
|
-
|
|
3
|
-
import { Range } from "./types";
|
|
4
|
-
|
|
5
|
-
export default function adjustRangeToRotation(
|
|
6
|
-
rangeToBeAdjusted: Range,
|
|
7
|
-
rotateTo = 0,
|
|
8
|
-
rangeLength?: number
|
|
9
|
-
) {
|
|
10
|
-
// ac.throw([ac.range, ac.posInt, ac.posInt], arguments);
|
|
11
|
-
const mod = (n: number) => (rangeLength ? modulo(n, rangeLength) : n);
|
|
12
|
-
|
|
13
|
-
const newRange = assign({}, rangeToBeAdjusted, {
|
|
14
|
-
start: mod(rangeToBeAdjusted.start - (rotateTo || 0)),
|
|
15
|
-
end: mod(rangeToBeAdjusted.end - (rotateTo || 0))
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
return newRange;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function modulo(n: number, m: number) {
|
|
22
|
-
return ((n % m) + m) % m;
|
|
23
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { Range } from "./types";
|
|
2
|
-
|
|
3
|
-
//
|
|
4
|
-
// ac.throw([ac.posInt, ac.posInt, ac.bool], arguments);
|
|
5
|
-
export default function checkIfNonCircularRangesOverlap(
|
|
6
|
-
range: Range,
|
|
7
|
-
comparisonRange: Range
|
|
8
|
-
) {
|
|
9
|
-
// ac.throw([ac.range, ac.range], arguments);
|
|
10
|
-
if (range.start < comparisonRange.start) {
|
|
11
|
-
if (range.end < comparisonRange.start) {
|
|
12
|
-
//----llll
|
|
13
|
-
//--------cccc
|
|
14
|
-
//no overlap
|
|
15
|
-
return false;
|
|
16
|
-
} else {
|
|
17
|
-
//----llll
|
|
18
|
-
//-------cccc
|
|
19
|
-
//overlap
|
|
20
|
-
return true;
|
|
21
|
-
}
|
|
22
|
-
} else {
|
|
23
|
-
if (range.start > comparisonRange.end) {
|
|
24
|
-
//------llll
|
|
25
|
-
// -cccc
|
|
26
|
-
//no overlap
|
|
27
|
-
return false;
|
|
28
|
-
} else {
|
|
29
|
-
//-----llll
|
|
30
|
-
// -cccc
|
|
31
|
-
//overlap
|
|
32
|
-
return true;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
import checkIfNonCircularRangesOverlap from "./checkIfNonCircularRangesOverlap";
|
|
4
|
-
|
|
5
|
-
import splitRangeIntoTwoPartsIfItIsCircular from "./splitRangeIntoTwoPartsIfItIsCircular";
|
|
6
|
-
import { Range } from "./types";
|
|
7
|
-
// ac.throw([ac.posInt, ac.posInt, ac.bool], arguments);
|
|
8
|
-
|
|
9
|
-
export default function checkIfPotentiallyCircularRangesOverlap(
|
|
10
|
-
range: Range,
|
|
11
|
-
comparisonRange: Range
|
|
12
|
-
) {
|
|
13
|
-
// ac.throw([ac.range, ac.range], arguments);
|
|
14
|
-
//split the potentially circular ranges and compare each part for overlap
|
|
15
|
-
return splitRangeIntoTwoPartsIfItIsCircular(range, Infinity).some(
|
|
16
|
-
function (splitRange) {
|
|
17
|
-
return splitRangeIntoTwoPartsIfItIsCircular(
|
|
18
|
-
comparisonRange,
|
|
19
|
-
Infinity
|
|
20
|
-
).some(function (splitComparisonRange) {
|
|
21
|
-
return checkIfNonCircularRangesOverlap(
|
|
22
|
-
splitRange,
|
|
23
|
-
splitComparisonRange
|
|
24
|
-
);
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
);
|
|
28
|
-
}
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { Range } from "./types";
|
|
2
|
-
|
|
3
|
-
//this function is a little confusing, but basically it takes an array of overlaps
|
|
4
|
-
//generated from a range overlaps calculation, and it sews them together if possible
|
|
5
|
-
export default function collapseOverlapsGeneratedFromRangeComparisonIfPossible(
|
|
6
|
-
overlaps: Range[],
|
|
7
|
-
sequenceLength: number,
|
|
8
|
-
optionalOriginalRange?: Range
|
|
9
|
-
): Range[] {
|
|
10
|
-
const originalRangeLinear =
|
|
11
|
-
optionalOriginalRange &&
|
|
12
|
-
optionalOriginalRange.start <= optionalOriginalRange.end;
|
|
13
|
-
if (overlaps.length === 1 || overlaps.length === 0) {
|
|
14
|
-
return overlaps;
|
|
15
|
-
} else if (overlaps.length === 2) {
|
|
16
|
-
if (
|
|
17
|
-
overlaps[0].start === 0 &&
|
|
18
|
-
overlaps[1].end + 1 === sequenceLength &&
|
|
19
|
-
!originalRangeLinear
|
|
20
|
-
) {
|
|
21
|
-
return [
|
|
22
|
-
{
|
|
23
|
-
start: overlaps[1].start,
|
|
24
|
-
end: overlaps[0].end
|
|
25
|
-
}
|
|
26
|
-
];
|
|
27
|
-
} else if (
|
|
28
|
-
overlaps[1].start === 0 &&
|
|
29
|
-
overlaps[0].end + 1 === sequenceLength &&
|
|
30
|
-
!originalRangeLinear
|
|
31
|
-
) {
|
|
32
|
-
return [
|
|
33
|
-
{
|
|
34
|
-
start: overlaps[0].start,
|
|
35
|
-
end: overlaps[1].end
|
|
36
|
-
}
|
|
37
|
-
];
|
|
38
|
-
} else {
|
|
39
|
-
return overlaps;
|
|
40
|
-
}
|
|
41
|
-
} else if (overlaps.length === 3) {
|
|
42
|
-
const firstOverlap = overlaps[0];
|
|
43
|
-
const secondOverlap = overlaps[1];
|
|
44
|
-
const thirdOverlap = overlaps[2];
|
|
45
|
-
let collapsedOverlaps =
|
|
46
|
-
collapseOverlapsGeneratedFromRangeComparisonIfPossible(
|
|
47
|
-
[firstOverlap, secondOverlap],
|
|
48
|
-
sequenceLength,
|
|
49
|
-
optionalOriginalRange
|
|
50
|
-
);
|
|
51
|
-
if (collapsedOverlaps.length === 1) {
|
|
52
|
-
collapsedOverlaps.push(thirdOverlap);
|
|
53
|
-
return collapsedOverlaps;
|
|
54
|
-
} else {
|
|
55
|
-
collapsedOverlaps =
|
|
56
|
-
collapseOverlapsGeneratedFromRangeComparisonIfPossible(
|
|
57
|
-
[firstOverlap, thirdOverlap],
|
|
58
|
-
sequenceLength,
|
|
59
|
-
optionalOriginalRange
|
|
60
|
-
);
|
|
61
|
-
if (collapsedOverlaps.length === 1) {
|
|
62
|
-
collapsedOverlaps.push(secondOverlap);
|
|
63
|
-
return collapsedOverlaps;
|
|
64
|
-
} else {
|
|
65
|
-
collapsedOverlaps =
|
|
66
|
-
collapseOverlapsGeneratedFromRangeComparisonIfPossible(
|
|
67
|
-
[secondOverlap, thirdOverlap],
|
|
68
|
-
sequenceLength,
|
|
69
|
-
optionalOriginalRange
|
|
70
|
-
);
|
|
71
|
-
if (collapsedOverlaps.length === 1) {
|
|
72
|
-
collapsedOverlaps.push(firstOverlap);
|
|
73
|
-
return collapsedOverlaps;
|
|
74
|
-
} else {
|
|
75
|
-
return overlaps;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
return overlaps;
|
|
81
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import { assign } from "lodash-es";
|
|
2
|
-
import { Range } from "./types";
|
|
3
|
-
|
|
4
|
-
interface RangeIndicesOptions {
|
|
5
|
-
inclusive1BasedStart?: boolean;
|
|
6
|
-
inclusive1BasedEnd?: boolean;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export default function convertRangeIndices(
|
|
10
|
-
range: Range,
|
|
11
|
-
inputType: RangeIndicesOptions = {},
|
|
12
|
-
outputType: RangeIndicesOptions = {}
|
|
13
|
-
) {
|
|
14
|
-
return assign({}, range, {
|
|
15
|
-
start:
|
|
16
|
-
Number(range.start) +
|
|
17
|
-
(inputType.inclusive1BasedStart
|
|
18
|
-
? outputType.inclusive1BasedStart
|
|
19
|
-
? 0
|
|
20
|
-
: -1
|
|
21
|
-
: outputType.inclusive1BasedStart
|
|
22
|
-
? 1
|
|
23
|
-
: 0),
|
|
24
|
-
end:
|
|
25
|
-
Number(range.end) +
|
|
26
|
-
(inputType.inclusive1BasedEnd
|
|
27
|
-
? outputType.inclusive1BasedEnd
|
|
28
|
-
? 0
|
|
29
|
-
: -1
|
|
30
|
-
: outputType.inclusive1BasedEnd
|
|
31
|
-
? 1
|
|
32
|
-
: 0)
|
|
33
|
-
});
|
|
34
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import convertRangeIndices from "./convertRangeIndices";
|
|
2
|
-
import { Range } from "./types";
|
|
3
|
-
|
|
4
|
-
export default function convertRangeTo1Based(range: Range) {
|
|
5
|
-
return convertRangeIndices(
|
|
6
|
-
range,
|
|
7
|
-
{},
|
|
8
|
-
{ inclusive1BasedStart: true, inclusive1BasedEnd: true }
|
|
9
|
-
);
|
|
10
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import getRangeLength from "./getRangeLength";
|
|
2
|
-
import { Range } from "./types";
|
|
3
|
-
|
|
4
|
-
export default function doesRangeSpanEntireSequence(
|
|
5
|
-
range: Range,
|
|
6
|
-
sequenceLength: number
|
|
7
|
-
) {
|
|
8
|
-
if (getRangeLength(range, sequenceLength) === sequenceLength) {
|
|
9
|
-
return true;
|
|
10
|
-
}
|
|
11
|
-
return false;
|
|
12
|
-
}
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import normalizePositionByRangeLength from "./normalizePositionByRangeLength";
|
|
2
|
-
import { assign } from "lodash-es";
|
|
3
|
-
|
|
4
|
-
import { Range } from "./types";
|
|
5
|
-
|
|
6
|
-
export default function expandOrContractCircularRangeToPosition(
|
|
7
|
-
range: Range,
|
|
8
|
-
position: number,
|
|
9
|
-
maxLength: number
|
|
10
|
-
) {
|
|
11
|
-
// 0 1 2 3 4 5 6 7 8 9
|
|
12
|
-
// r r r r r - - r r r
|
|
13
|
-
//0 1 2 3 4 5 6 7 8 9 10
|
|
14
|
-
// |
|
|
15
|
-
const newRange = assign({}, range);
|
|
16
|
-
let endMoved = true;
|
|
17
|
-
if (range.end >= position) {
|
|
18
|
-
if (position + maxLength - range.start > range.end - position) {
|
|
19
|
-
newRange.end = normalizePositionByRangeLength(
|
|
20
|
-
position - 1,
|
|
21
|
-
maxLength,
|
|
22
|
-
false
|
|
23
|
-
);
|
|
24
|
-
} else {
|
|
25
|
-
newRange.start = position;
|
|
26
|
-
endMoved = false;
|
|
27
|
-
}
|
|
28
|
-
} else {
|
|
29
|
-
if (range.start < position) {
|
|
30
|
-
if (range.end + maxLength - position > position - range.start) {
|
|
31
|
-
newRange.start = position;
|
|
32
|
-
endMoved = false;
|
|
33
|
-
} else {
|
|
34
|
-
newRange.end = position - 1;
|
|
35
|
-
}
|
|
36
|
-
} else {
|
|
37
|
-
//position somewhere between end and start
|
|
38
|
-
if (range.start - position > position - range.end) {
|
|
39
|
-
newRange.end = position - 1;
|
|
40
|
-
} else {
|
|
41
|
-
endMoved = false;
|
|
42
|
-
newRange.start = position;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
return {
|
|
47
|
-
newRange: newRange,
|
|
48
|
-
endMoved: endMoved
|
|
49
|
-
};
|
|
50
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { assign } from "lodash-es";
|
|
2
|
-
|
|
3
|
-
import { Range } from "./types";
|
|
4
|
-
|
|
5
|
-
export default function expandOrContractNonCircularRangeToPosition(
|
|
6
|
-
range: Range,
|
|
7
|
-
position: number
|
|
8
|
-
) {
|
|
9
|
-
const newRange = assign({}, range);
|
|
10
|
-
let endMoved = true;
|
|
11
|
-
if (range.start > position) {
|
|
12
|
-
newRange.start = position;
|
|
13
|
-
endMoved = false;
|
|
14
|
-
} else {
|
|
15
|
-
if (range.end < position) {
|
|
16
|
-
newRange.end = position - 1;
|
|
17
|
-
} else {
|
|
18
|
-
if (position - range.start > range.end - position) {
|
|
19
|
-
newRange.end = position - 1;
|
|
20
|
-
} else {
|
|
21
|
-
newRange.start = position;
|
|
22
|
-
endMoved = false;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
return {
|
|
27
|
-
newRange: newRange,
|
|
28
|
-
endMoved: endMoved
|
|
29
|
-
};
|
|
30
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { clone } from "lodash-es";
|
|
2
|
-
import { Range } from "./types";
|
|
3
|
-
import normalizeRange from "./normalizeRange";
|
|
4
|
-
|
|
5
|
-
export default function expandOrContractRangeByLength(
|
|
6
|
-
range: Range,
|
|
7
|
-
shiftBy: number,
|
|
8
|
-
shiftStart: boolean,
|
|
9
|
-
sequenceLength: number
|
|
10
|
-
) {
|
|
11
|
-
const rangeToReturn = clone(range);
|
|
12
|
-
if (shiftStart) {
|
|
13
|
-
rangeToReturn.start -= shiftBy;
|
|
14
|
-
} else {
|
|
15
|
-
rangeToReturn.end += shiftBy;
|
|
16
|
-
}
|
|
17
|
-
return normalizeRange(rangeToReturn, sequenceLength);
|
|
18
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import expandOrContractCircularRangeToPosition from "./expandOrContractCircularRangeToPosition";
|
|
2
|
-
import expandOrContractNonCircularRangeToPosition from "./expandOrContractNonCircularRangeToPosition";
|
|
3
|
-
|
|
4
|
-
import { Range } from "./types";
|
|
5
|
-
|
|
6
|
-
export default function expandOrContractRangeToPosition(
|
|
7
|
-
range: Range,
|
|
8
|
-
position: number,
|
|
9
|
-
maxLength: number
|
|
10
|
-
) {
|
|
11
|
-
if (range.start > range.end) {
|
|
12
|
-
return expandOrContractCircularRangeToPosition(range, position, maxLength);
|
|
13
|
-
} else {
|
|
14
|
-
return expandOrContractNonCircularRangeToPosition(range, position);
|
|
15
|
-
}
|
|
16
|
-
}
|
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
import expandOrContractRangeByLength from "./expandOrContractRangeByLength";
|
|
2
|
-
import isRangeWithinRange from "./isRangeWithinRange";
|
|
3
|
-
import getOverlapsOfPotentiallyCircularRanges from "./getOverlapsOfPotentiallyCircularRanges";
|
|
4
|
-
import translateRange from "./translateRange";
|
|
5
|
-
import getRangeLength from "./getRangeLength";
|
|
6
|
-
|
|
7
|
-
import { Range } from "./types";
|
|
8
|
-
|
|
9
|
-
export default function flipRelativeRange(
|
|
10
|
-
innerRange: Range,
|
|
11
|
-
outerRange: Range,
|
|
12
|
-
sequenceLength: number
|
|
13
|
-
) {
|
|
14
|
-
const isFullyContained = isRangeWithinRange(
|
|
15
|
-
innerRange,
|
|
16
|
-
outerRange,
|
|
17
|
-
sequenceLength
|
|
18
|
-
);
|
|
19
|
-
if (isFullyContained) {
|
|
20
|
-
return flipFullyContainedRange(innerRange, outerRange, sequenceLength);
|
|
21
|
-
} else {
|
|
22
|
-
// flip not fully contained range
|
|
23
|
-
return flipNonFullyContainedRange(innerRange, outerRange, sequenceLength);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function flipNonFullyContainedRange(
|
|
28
|
-
innerRange: Range,
|
|
29
|
-
outerRange: Range,
|
|
30
|
-
sequenceLength: number
|
|
31
|
-
) {
|
|
32
|
-
const outerFullyContained = isRangeWithinRange(
|
|
33
|
-
outerRange,
|
|
34
|
-
innerRange,
|
|
35
|
-
sequenceLength
|
|
36
|
-
);
|
|
37
|
-
let flippedInnerRange;
|
|
38
|
-
if (outerFullyContained) {
|
|
39
|
-
//special logic
|
|
40
|
-
// flipFullyContainedRange(outerRange, outerRange, sequenceLength)
|
|
41
|
-
const expandBy1 =
|
|
42
|
-
getRangeLength(
|
|
43
|
-
{
|
|
44
|
-
start: innerRange.start,
|
|
45
|
-
end: outerRange.start
|
|
46
|
-
},
|
|
47
|
-
sequenceLength
|
|
48
|
-
) - 1;
|
|
49
|
-
flippedInnerRange = expandOrContractRangeByLength(
|
|
50
|
-
outerRange,
|
|
51
|
-
expandBy1,
|
|
52
|
-
false,
|
|
53
|
-
sequenceLength
|
|
54
|
-
);
|
|
55
|
-
|
|
56
|
-
const expandBy2 =
|
|
57
|
-
getRangeLength(
|
|
58
|
-
{
|
|
59
|
-
end: innerRange.end,
|
|
60
|
-
start: outerRange.end
|
|
61
|
-
},
|
|
62
|
-
sequenceLength
|
|
63
|
-
) - 1;
|
|
64
|
-
flippedInnerRange = expandOrContractRangeByLength(
|
|
65
|
-
flippedInnerRange,
|
|
66
|
-
expandBy2,
|
|
67
|
-
true,
|
|
68
|
-
sequenceLength
|
|
69
|
-
);
|
|
70
|
-
} else {
|
|
71
|
-
//find overlaps of ranges
|
|
72
|
-
const overlaps = getOverlapsOfPotentiallyCircularRanges(
|
|
73
|
-
innerRange,
|
|
74
|
-
outerRange,
|
|
75
|
-
sequenceLength
|
|
76
|
-
);
|
|
77
|
-
//take first overlap and determine which end of outer range it overlaps
|
|
78
|
-
if (overlaps.length >= 1) {
|
|
79
|
-
const firstOverlap = overlaps[0];
|
|
80
|
-
const overlapExtendsForward = firstOverlap.start !== outerRange.start;
|
|
81
|
-
//flip using fully contained logic
|
|
82
|
-
const flippedTruncatedInner = flipFullyContainedRange(
|
|
83
|
-
firstOverlap,
|
|
84
|
-
outerRange,
|
|
85
|
-
sequenceLength
|
|
86
|
-
);
|
|
87
|
-
//extend in the opposite direction
|
|
88
|
-
const lengthToExtend =
|
|
89
|
-
getRangeLength(innerRange, sequenceLength) -
|
|
90
|
-
getRangeLength(flippedTruncatedInner, sequenceLength);
|
|
91
|
-
flippedInnerRange = expandOrContractRangeByLength(
|
|
92
|
-
flippedTruncatedInner,
|
|
93
|
-
lengthToExtend,
|
|
94
|
-
overlapExtendsForward,
|
|
95
|
-
sequenceLength
|
|
96
|
-
);
|
|
97
|
-
} else {
|
|
98
|
-
throw new Error(
|
|
99
|
-
"This case (relative ranges that do not overlap) is unsupported! "
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
return flippedInnerRange;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function flipFullyContainedRange(
|
|
107
|
-
innerRange: Range,
|
|
108
|
-
outerRange: Range,
|
|
109
|
-
sequenceLength: number
|
|
110
|
-
) {
|
|
111
|
-
//translate both ranges by offset such that outer range start = 0
|
|
112
|
-
const translateBy = -outerRange.start;
|
|
113
|
-
const translatedOuterRange = translateRange(
|
|
114
|
-
outerRange,
|
|
115
|
-
translateBy,
|
|
116
|
-
sequenceLength
|
|
117
|
-
);
|
|
118
|
-
const translatedInnerRange = translateRange(
|
|
119
|
-
innerRange,
|
|
120
|
-
translateBy,
|
|
121
|
-
sequenceLength
|
|
122
|
-
);
|
|
123
|
-
|
|
124
|
-
//flip like non origin spanning range
|
|
125
|
-
const translatedFlippedInnerRange = flipNonOriginSpanningContainedRange(
|
|
126
|
-
translatedInnerRange,
|
|
127
|
-
translatedOuterRange,
|
|
128
|
-
sequenceLength
|
|
129
|
-
);
|
|
130
|
-
|
|
131
|
-
//translate inner range back by negative offset
|
|
132
|
-
const flippedInnerRange = translateRange(
|
|
133
|
-
translatedFlippedInnerRange,
|
|
134
|
-
-translateBy,
|
|
135
|
-
sequenceLength
|
|
136
|
-
);
|
|
137
|
-
return flippedInnerRange;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
function flipNonOriginSpanningContainedRange(
|
|
141
|
-
innerRange: Range,
|
|
142
|
-
outerRange: Range,
|
|
143
|
-
sequenceLength: number
|
|
144
|
-
) {
|
|
145
|
-
//non origin spanning, fully contained inner
|
|
146
|
-
const offsetFromStart = innerRange.start - outerRange.start;
|
|
147
|
-
const newInnerEnd = outerRange.end - offsetFromStart;
|
|
148
|
-
const innerRangeLength = getRangeLength(innerRange, sequenceLength);
|
|
149
|
-
|
|
150
|
-
return {
|
|
151
|
-
end: newInnerEnd,
|
|
152
|
-
start: newInnerEnd - (innerRangeLength - 1)
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
//take 2
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import normalizePositionByRangeLength from "./normalizePositionByRangeLength";
|
|
2
|
-
|
|
3
|
-
export default function generateRandomRange(
|
|
4
|
-
minStart: number,
|
|
5
|
-
maxEnd: number,
|
|
6
|
-
maxLength: number
|
|
7
|
-
) {
|
|
8
|
-
const start = getRandomInt(minStart, maxEnd);
|
|
9
|
-
let end;
|
|
10
|
-
if (maxLength) {
|
|
11
|
-
end = normalizePositionByRangeLength(
|
|
12
|
-
getRandomInt(start, start + maxLength),
|
|
13
|
-
maxEnd
|
|
14
|
-
);
|
|
15
|
-
} else {
|
|
16
|
-
end = getRandomInt(minStart, maxEnd);
|
|
17
|
-
}
|
|
18
|
-
return {
|
|
19
|
-
start: start,
|
|
20
|
-
end: end
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function getRandomInt(min: number, max: number) {
|
|
25
|
-
return Math.floor(Math.random() * (max - min)) + min;
|
|
26
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { Range } from "./types";
|
|
2
|
-
|
|
3
|
-
//function that returns the annotation range type
|
|
4
|
-
export default function getAnnotationRangeType(
|
|
5
|
-
annotationRange: Range,
|
|
6
|
-
enclosingRangeType: Range,
|
|
7
|
-
forward: boolean
|
|
8
|
-
) {
|
|
9
|
-
if (annotationRange.start === enclosingRangeType.start) {
|
|
10
|
-
if (annotationRange.end === enclosingRangeType.end) {
|
|
11
|
-
return "beginningAndEnd";
|
|
12
|
-
} else {
|
|
13
|
-
if (forward) {
|
|
14
|
-
return "start";
|
|
15
|
-
} else {
|
|
16
|
-
return "end";
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
} else {
|
|
20
|
-
if (annotationRange.end === enclosingRangeType.end) {
|
|
21
|
-
if (forward) {
|
|
22
|
-
return "end";
|
|
23
|
-
} else {
|
|
24
|
-
return "start";
|
|
25
|
-
}
|
|
26
|
-
} else {
|
|
27
|
-
return "middle";
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import normalizePositionByRangeLength from "./normalizePositionByRangeLength";
|
|
2
|
-
import getRangeLength from "./getRangeLength";
|
|
3
|
-
import { Range } from "./types";
|
|
4
|
-
|
|
5
|
-
export default function getEachPositionInRangeAsArray(
|
|
6
|
-
range: Range,
|
|
7
|
-
rangeMax: number
|
|
8
|
-
) {
|
|
9
|
-
const output: number[] = [];
|
|
10
|
-
const length = getRangeLength(range, rangeMax);
|
|
11
|
-
if (!(length > 0)) {
|
|
12
|
-
return output;
|
|
13
|
-
}
|
|
14
|
-
for (let i = range.start; i < length + range.start; i++) {
|
|
15
|
-
const position = normalizePositionByRangeLength(i, rangeMax);
|
|
16
|
-
output.push(position);
|
|
17
|
-
}
|
|
18
|
-
return output;
|
|
19
|
-
}
|