diff --git a/packages/core/BaseFeatureWidget/BaseFeatureDetail.tsx b/packages/core/BaseFeatureWidget/BaseFeatureDetail.tsx index 98f9d5872f4..e43a4395f21 100644 --- a/packages/core/BaseFeatureWidget/BaseFeatureDetail.tsx +++ b/packages/core/BaseFeatureWidget/BaseFeatureDetail.tsx @@ -23,6 +23,7 @@ import { getSession, defaultCodonTable, generateCodonTable, + revcom, } from '../util' import { Feature } from '../util/simpleFeature' import SanitizedHTML from '../ui/SanitizedHTML' @@ -214,6 +215,17 @@ interface BaseProps extends BaseCardProps { model?: any } +function stitch(subfeats: any, feature: any, sequence: string) { + let chunks = subfeats.map((sub: any) => { + const chunk = sequence.slice(sub.start, sub.end) + return feature.strand === -1 ? revcom(chunk) : chunk + }) + if (feature.strand === -1) { + chunks = chunks.reverse() + } + return chunks.join('') +} + // display the stitched-together sequence of a gene's CDS, cDNA, or protein // sequence. this is a best effort and weird genomic phenomena could lead these // to not be 100% accurate @@ -262,6 +274,7 @@ function SequenceFeatureDetails(props: BaseProps) { const text: React.ReactNode[] = [] if (sequence && feature) { + const { strand } = feature const children = feature.subfeatures .sort((a: any, b: any) => a.start - b.start) .map((sub: any) => { @@ -280,47 +293,46 @@ function SequenceFeatureDetails(props: BaseProps) { const exons = children.filter((sub: any) => sub.type === 'exon') if (mode === 'cds') { - cds.forEach((sub: any) => { + text.push( +
+ {stitch(cds, feature, sequence)} +
, + ) + } else if (mode === 'cdna') { + // if we have CDS, it is a real gene, color the difference between the + // start and end of the CDS as UTR and the rest as CDS + if (cds.length) { text.push(
- {sequence.slice(sub.start, sub.end)} + {feature.strand === -1 + ? revcom(sequence.slice(cds[cds.length - 1].end)) + : sequence.slice(0, cds[0].start)}
, ) - }) - } else if (mode === 'cdna') { - // if we have CDS, it is a real gene, color the difference between the - // start and end of the CDS as UTR and the rest as CDS - if (cds.length) { + text.push(
- {sequence.slice(0, cds[0].start)} + {stitch(cds, feature, sequence)}
, ) - cds.forEach((sub: any) => { - text.push( -
- {sequence.slice(sub.start, sub.end)} -
, - ) - }) text.push(
- {sequence.slice(cds[cds.length - 1].end)} + {feature.strand === -1 + ? revcom(sequence.slice(0, cds[0].start)) + : sequence.slice(cds[cds.length - 1].end)}
, ) } // no CDS, probably a pseudogene, color whole thing as "UTR" else { - exons.forEach((sub: any) => { - text.push( -
- {sequence.slice(sub.start, sub.end)} -
, - ) - }) + text.push( +
+ {stitch(exons, feature, sequence)} +
, + ) } } else if (mode === 'protein') { - let str = '' - cds.forEach((sub: any) => { - str += sequence.slice(sub.start, sub.end) - }) + const str = stitch(cds, feature, sequence) let protein = '' for (let i = 0; i < str.length; i += 3) { protein += codonTable[str.slice(i, i + 3)]