+
@@ -75,19 +87,11 @@ const TranscriptVariantGenomicSequence = (props: Props) => {
const LeftFlankingSequence = ({
flankingSequence,
- variantSequence,
variantToTranscriptStartDistance
}: {
flankingSequence: string;
- variantSequence: string;
variantToTranscriptStartDistance: number;
}) => {
- const leftOffset = calculateLeftOffset({
- flankingSequence,
- variantSequence
- });
- const marginLeft = leftOffset ? `${leftOffset}px` : undefined;
-
const letters = flankingSequence.split('');
const letterClasses = classNames(
@@ -112,7 +116,6 @@ const LeftFlankingSequence = ({
letter={letter}
key={index}
className={hasEllipsis && index === 0 ? ellipsisClasses : letterClasses}
- style={index === 0 && marginLeft ? { marginLeft } : undefined}
/>
));
};
@@ -345,7 +348,7 @@ const getAltAlleleAnchorPosition = ({
refAlleleSequence: string;
variantType: string;
}) => {
- const letterWidth = 16;
+ const letterWidth = SEQUENCE_LETTER_WIDTH;
const halfGenomicSequenceLength = Math.ceil(
DISPLAYED_REFERENCE_SEQUENCE_LENGTH / 2
);
diff --git a/src/content/app/entity-viewer/variant-view/transcript-consequences/useTranscriptDetails.test.ts b/src/content/app/entity-viewer/variant-view/transcript-consequences/useTranscriptDetails.test.ts
index 17ddb01d40..4a1132cfa6 100644
--- a/src/content/app/entity-viewer/variant-view/transcript-consequences/useTranscriptDetails.test.ts
+++ b/src/content/app/entity-viewer/variant-view/transcript-consequences/useTranscriptDetails.test.ts
@@ -496,7 +496,7 @@ describe('functions splitting genomic sequence into parts', () => {
).toBe(expectedVariantSeq);
});
- test('Insertion, near forward-strand start, forward strand', () => {
+ test('insertion, near forward-strand start, forward strand', () => {
const sequence = 'GCGGGGTCCAGCAGGCAGGCTCCGGCCGTG'; // 30 characters
const expectedLeftFlankingSeq = 'GCGGGGTCC'; // first 9 characters
@@ -529,7 +529,7 @@ describe('functions splitting genomic sequence into parts', () => {
).toBe(expectedVariantSeq);
});
- test('Insertion, near forward-strand start, reverse strand', () => {
+ test('insertion, near forward-strand start, reverse strand', () => {
const sequence = 'GCGGGGTCCAGCAGGCAGGCTCCGGCCGTG'; // 30 characters
const expectedLeftFlankingSeq = getReverseComplement(
@@ -563,6 +563,39 @@ describe('functions splitting genomic sequence into parts', () => {
})
).toBe(expectedVariantSeq);
});
+
+ test('allele starts at the start of genomic slice, reverse strand', () => {
+ const sequence = 'TCTCTCACACAGTAATACATG'; // 21 characters
+
+ const expectedLeftFlankingSeq = getReverseComplement(sequence).slice(0, 20);
+ const expectedVariantSeq = getReverseComplement(sequence)[20];
+ const expectedRightFlankingSeq = '';
+
+ expect(
+ getLeftFlankingGenomicSequence({
+ sequence,
+ distanceToSliceStart: 0,
+ distanceToSliceEnd: 20,
+ strand: 'reverse'
+ })
+ ).toBe(expectedLeftFlankingSeq);
+ expect(
+ getRightFlankingGenomicSequence({
+ sequence,
+ distanceToSliceStart: 0,
+ distanceToSliceEnd: 20,
+ strand: 'reverse'
+ })
+ ).toBe(expectedRightFlankingSeq);
+ expect(
+ getReferenceAlleleGenomicSequence({
+ sequence,
+ distanceToSliceStart: 0,
+ distanceToSliceEnd: 20,
+ strand: 'reverse'
+ })
+ ).toBe(expectedVariantSeq);
+ });
});
describe('getProteinSliceCoordinates', () => {
diff --git a/src/content/app/entity-viewer/variant-view/transcript-consequences/useTranscriptDetails.ts b/src/content/app/entity-viewer/variant-view/transcript-consequences/useTranscriptDetails.ts
index 5f9a8617f3..f375724736 100644
--- a/src/content/app/entity-viewer/variant-view/transcript-consequences/useTranscriptDetails.ts
+++ b/src/content/app/entity-viewer/variant-view/transcript-consequences/useTranscriptDetails.ts
@@ -412,9 +412,11 @@ export const getLeftFlankingGenomicSequence = ({
strand: 'forward' | 'reverse';
}) => {
if (strand === 'forward') {
- return sequence.slice(0, distanceToSliceStart);
+ return distanceToSliceStart ? sequence.slice(0, distanceToSliceStart) : '';
} else {
- return getReverseComplement(sequence).slice(0, distanceToSliceEnd);
+ return distanceToSliceEnd
+ ? getReverseComplement(sequence).slice(0, distanceToSliceEnd)
+ : '';
}
};
@@ -430,9 +432,11 @@ export const getRightFlankingGenomicSequence = ({
strand: 'forward' | 'reverse';
}) => {
if (strand === 'forward') {
- return sequence.slice(-1 * distanceToSliceEnd);
+ return distanceToSliceEnd ? sequence.slice(-1 * distanceToSliceEnd) : '';
} else {
- return getReverseComplement(sequence).slice(-1 * distanceToSliceStart);
+ return distanceToSliceStart
+ ? getReverseComplement(sequence).slice(-1 * distanceToSliceStart)
+ : '';
}
};
diff --git a/src/shared/helpers/exon-helpers/exonHelpers.test.ts b/src/shared/helpers/exon-helpers/exonHelpers.test.ts
index 9672f321ed..cc4056f2db 100644
--- a/src/shared/helpers/exon-helpers/exonHelpers.test.ts
+++ b/src/shared/helpers/exon-helpers/exonHelpers.test.ts
@@ -20,6 +20,7 @@ import * as example1 from './fixtures/exons-cds-data-1';
import * as example2 from './fixtures/exons-cds-data-2';
import * as example3 from './fixtures/exons-cds-data-3';
import * as example4 from './fixtures/exons-cds-data-4';
+import * as example5 from './fixtures/exons-cds-data-5';
describe('addRelativeLocationInCDSToExons', () => {
test('transcript with a single exon and no UTRs ', () => {
@@ -68,4 +69,13 @@ describe('addRelativeLocationInCDSToExons', () => {
expect(result).toEqual(example4.exonsWithRelativeLocationInCDS);
});
+
+ test('transcript with two exons and no UTRs', () => {
+ const result = addRelativeLocationInCDSToExons({
+ exons: example5.exons,
+ cds: example5.cds
+ });
+
+ expect(result).toEqual(example5.exonsWithRelativeLocationInCDS);
+ });
});
diff --git a/src/shared/helpers/exon-helpers/exonHelpers.ts b/src/shared/helpers/exon-helpers/exonHelpers.ts
index 58a858b36c..e12d73b43d 100644
--- a/src/shared/helpers/exon-helpers/exonHelpers.ts
+++ b/src/shared/helpers/exon-helpers/exonHelpers.ts
@@ -47,7 +47,7 @@ export const addRelativeLocationInCDSToExons = <
const cds = params.cds;
const exons = structuredClone(params.exons);
- let lastPositionInCDS = 1;
+ let lastPositionInCDS = 0;
for (const exon of exons) {
if (doesExonIncludeCDS({ exon, cds })) {
@@ -86,7 +86,7 @@ export const addRelativeLocationInCDSToExons = <
!isExonEndWithinCDS({ exon, cds })
) {
// last exon in CDS
- const relativeStart = lastPositionInCDS;
+ const relativeStart = lastPositionInCDS + 1;
const remainingExonLength =
cds.relative_end - exon.relative_location.start + 1;
const relativeEnd = relativeStart + remainingExonLength - 1;
@@ -98,7 +98,7 @@ export const addRelativeLocationInCDSToExons = <
};
} else {
// exon fully within CDS
- const relativeStart = lastPositionInCDS;
+ const relativeStart = lastPositionInCDS + 1;
const exonLength =
exon.relative_location.end - exon.relative_location.start + 1;
const relativeEnd = relativeStart + exonLength - 1;
diff --git a/src/shared/helpers/exon-helpers/fixtures/exons-cds-data-3.ts b/src/shared/helpers/exon-helpers/fixtures/exons-cds-data-3.ts
index be1864eee3..a78cf59fbe 100644
--- a/src/shared/helpers/exon-helpers/fixtures/exons-cds-data-3.ts
+++ b/src/shared/helpers/exon-helpers/fixtures/exons-cds-data-3.ts
@@ -52,6 +52,6 @@ export const exonsWithRelativeLocationInCDS = [
{
index: 2,
relative_location: { start: 4257, end: 6314 },
- relative_location_in_cds: { start: 406, end: 851, length: 446 }
+ relative_location_in_cds: { start: 407, end: 852, length: 446 }
}
];
diff --git a/src/shared/helpers/exon-helpers/fixtures/exons-cds-data-4.ts b/src/shared/helpers/exon-helpers/fixtures/exons-cds-data-4.ts
index 9e7682de7c..1e2df5f341 100644
--- a/src/shared/helpers/exon-helpers/fixtures/exons-cds-data-4.ts
+++ b/src/shared/helpers/exon-helpers/fixtures/exons-cds-data-4.ts
@@ -244,97 +244,97 @@ export const exonsWithRelativeLocationInCDS = [
{
index: 3,
relative_location: { start: 3570, end: 3818 },
- relative_location_in_cds: { start: 67, end: 315, length: 249 }
+ relative_location_in_cds: { start: 68, end: 316, length: 249 }
},
{
index: 4,
relative_location: { start: 9569, end: 9677 },
- relative_location_in_cds: { start: 315, end: 423, length: 109 }
+ relative_location_in_cds: { start: 317, end: 425, length: 109 }
},
{
index: 5,
relative_location: { start: 10594, end: 10643 },
- relative_location_in_cds: { start: 423, end: 472, length: 50 }
+ relative_location_in_cds: { start: 426, end: 475, length: 50 }
},
{
index: 6,
relative_location: { start: 10735, end: 10775 },
- relative_location_in_cds: { start: 472, end: 512, length: 41 }
+ relative_location_in_cds: { start: 476, end: 516, length: 41 }
},
{
index: 7,
relative_location: { start: 10992, end: 11106 },
- relative_location_in_cds: { start: 512, end: 626, length: 115 }
+ relative_location_in_cds: { start: 517, end: 631, length: 115 }
},
{
index: 8,
relative_location: { start: 13936, end: 13985 },
- relative_location_in_cds: { start: 626, end: 675, length: 50 }
+ relative_location_in_cds: { start: 632, end: 681, length: 50 }
},
{
index: 9,
relative_location: { start: 15412, end: 15523 },
- relative_location_in_cds: { start: 675, end: 786, length: 112 }
+ relative_location_in_cds: { start: 682, end: 793, length: 112 }
},
{
index: 10,
relative_location: { start: 16765, end: 17880 },
- relative_location_in_cds: { start: 786, end: 1901, length: 1116 }
+ relative_location_in_cds: { start: 794, end: 1909, length: 1116 }
},
{
index: 11,
relative_location: { start: 20758, end: 25689 },
- relative_location_in_cds: { start: 1901, end: 6832, length: 4932 }
+ relative_location_in_cds: { start: 1910, end: 6841, length: 4932 }
},
{
index: 12,
relative_location: { start: 29051, end: 29146 },
- relative_location_in_cds: { start: 6832, end: 6927, length: 96 }
+ relative_location_in_cds: { start: 6842, end: 6937, length: 96 }
},
{
index: 13,
relative_location: { start: 31320, end: 31389 },
- relative_location_in_cds: { start: 6927, end: 6996, length: 70 }
+ relative_location_in_cds: { start: 6938, end: 7007, length: 70 }
},
{
index: 14,
relative_location: { start: 39354, end: 39781 },
- relative_location_in_cds: { start: 6996, end: 7423, length: 428 }
+ relative_location_in_cds: { start: 7008, end: 7435, length: 428 }
},
{
index: 15,
relative_location: { start: 40921, end: 41102 },
- relative_location_in_cds: { start: 7423, end: 7604, length: 182 }
+ relative_location_in_cds: { start: 7436, end: 7617, length: 182 }
},
{
index: 16,
relative_location: { start: 42235, end: 42422 },
- relative_location_in_cds: { start: 7604, end: 7791, length: 188 }
+ relative_location_in_cds: { start: 7618, end: 7805, length: 188 }
},
{
index: 17,
relative_location: { start: 47016, end: 47186 },
- relative_location_in_cds: { start: 7791, end: 7961, length: 171 }
+ relative_location_in_cds: { start: 7806, end: 7976, length: 171 }
},
{
index: 18,
relative_location: { start: 47672, end: 48026 },
- relative_location_in_cds: { start: 7961, end: 8315, length: 355 }
+ relative_location_in_cds: { start: 7977, end: 8331, length: 355 }
},
{
index: 19,
relative_location: { start: 54895, end: 55050 },
- relative_location_in_cds: { start: 8315, end: 8470, length: 156 }
+ relative_location_in_cds: { start: 8332, end: 8487, length: 156 }
},
{
index: 20,
relative_location: { start: 55449, end: 55593 },
- relative_location_in_cds: { start: 8470, end: 8614, length: 145 }
+ relative_location_in_cds: { start: 8488, end: 8632, length: 145 }
},
{
index: 21,
relative_location: { start: 59455, end: 59703 },
- relative_location_in_cds: { start: 8614, end: 8732, length: 119 }
+ relative_location_in_cds: { start: 8633, end: 8751, length: 119 }
},
{
index: 22,
diff --git a/src/shared/helpers/exon-helpers/fixtures/exons-cds-data-5.ts b/src/shared/helpers/exon-helpers/fixtures/exons-cds-data-5.ts
new file mode 100644
index 0000000000..cabaa68ac9
--- /dev/null
+++ b/src/shared/helpers/exon-helpers/fixtures/exons-cds-data-5.ts
@@ -0,0 +1,73 @@
+/**
+ * See the NOTICE file distributed with this work for additional information
+ * regarding copyright ownership.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Exons of human transcript ENST00000622028.1
+// It is a protein-coding transcript with no UTRs
+
+export const exons = [
+ {
+ index: 1,
+ relative_location: {
+ start: 1,
+ end: 46,
+ length: 46
+ }
+ },
+ {
+ index: 2,
+ relative_location: {
+ start: 130,
+ end: 436,
+ length: 307
+ }
+ }
+];
+
+export const cds = {
+ relative_start: 1,
+ relative_end: 436,
+ nucleotide_length: 353
+};
+
+// The expected result
+export const exonsWithRelativeLocationInCDS = [
+ {
+ index: 1,
+ relative_location: {
+ start: 1,
+ end: 46,
+ length: 46
+ },
+ relative_location_in_cds: {
+ start: 1,
+ end: 46,
+ length: 46
+ }
+ },
+ {
+ index: 2,
+ relative_location: {
+ start: 130,
+ end: 436,
+ length: 307
+ },
+ relative_location_in_cds: {
+ start: 47,
+ end: 353,
+ length: 307
+ }
+ }
+];