diff --git a/packages/apollo-mst/src/AnnotationFeatureModel.ts b/packages/apollo-mst/src/AnnotationFeatureModel.ts index dc093d34f..cf5b07cff 100644 --- a/packages/apollo-mst/src/AnnotationFeatureModel.ts +++ b/packages/apollo-mst/src/AnnotationFeatureModel.ts @@ -1,4 +1,4 @@ -import { intersection2 } from '@jbrowse/core/util' +import { getSession, intersection2 } from '@jbrowse/core/util' import { IAnyModelType, IMSTMap, @@ -109,7 +109,14 @@ export const AnnotationFeatureModel = types return false }, get cdsLocations(): { min: number; max: number; phase: 0 | 1 | 2 }[][] { - if (self.type !== 'mRNA') { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any + const session = getSession(self) as any + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const { apolloDataStore } = session + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access + const { featureTypeOntology } = apolloDataStore.ontologyManager + // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access + if (!featureTypeOntology.isTypeOf(self.type, 'mRNA')) { throw new Error( 'Only features of type "mRNA" or equivalent can calculate CDS locations', ) @@ -119,7 +126,8 @@ export const AnnotationFeatureModel = types throw new Error('no CDS or exons in mRNA') } const cdsChildren = [...children.values()].filter( - (child) => child.type === 'CDS', + // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access + (child) => featureTypeOntology.isTypeOf(child.type, 'CDS'), ) if (cdsChildren.length === 0) { throw new Error('no CDS in mRNA') @@ -130,7 +138,8 @@ export const AnnotationFeatureModel = types const { max: cdsMax, min: cdsMin } = cds const locs: { min: number; max: number }[] = [] for (const [, child] of children) { - if (child.type !== 'exon') { + // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access + if (!featureTypeOntology.isTypeOf(child.type, 'exon')) { continue } const [start, end] = intersection2( diff --git a/packages/jbrowse-plugin-apollo/src/FeatureDetailsWidget/TranscriptBasic.tsx b/packages/jbrowse-plugin-apollo/src/FeatureDetailsWidget/TranscriptBasic.tsx index acc7db878..9b25f310a 100644 --- a/packages/jbrowse-plugin-apollo/src/FeatureDetailsWidget/TranscriptBasic.tsx +++ b/packages/jbrowse-plugin-apollo/src/FeatureDetailsWidget/TranscriptBasic.tsx @@ -83,8 +83,11 @@ export const TranscriptBasicInformation = observer( const { notify } = session as unknown as AbstractSessionModel const currentAssembly = session.apolloDataStore.assemblies.get(assembly) const refData = currentAssembly?.getByRefName(refName) - const { changeManager } = session.apolloDataStore - + const { changeManager, ontologyManager } = session.apolloDataStore + const { featureTypeOntology } = ontologyManager + if (!featureTypeOntology) { + throw new Error('featureTypeOntology is undefined') + } function handleStartChange( newStart: number, featureId: string, @@ -100,10 +103,14 @@ export const TranscriptBasicInformation = observer( if (!subFeature?.children) { return } + if (!featureTypeOntology) { + throw new Error('featureTypeOntology is undefined') + } // Let's check CDS start and end values. And possibly update those too for (const child of subFeature.children) { if ( - (child[1].type === 'CDS' || child[1].type === 'exon') && + (featureTypeOntology.isTypeOf(child[1].type, 'CDS') || + featureTypeOntology.isTypeOf(child[1].type, 'exon')) && child[1].min === oldStart ) { const change = new LocationStartChange({ @@ -135,10 +142,14 @@ export const TranscriptBasicInformation = observer( if (!subFeature?.children) { return } + if (!featureTypeOntology) { + throw new Error('featureTypeOntology is undefined') + } // Let's check CDS start and end values. And possibly update those too for (const child of subFeature.children) { if ( - (child[1].type === 'CDS' || child[1].type === 'exon') && + (featureTypeOntology.isTypeOf(child[1].type, 'CDS') || + featureTypeOntology.isTypeOf(child[1].type, 'exon')) && child[1].max === oldEnd ) { const change = new LocationEndChange({ @@ -160,7 +171,7 @@ export const TranscriptBasicInformation = observer( const featureNew = feature let exonsArray: ExonInfo[] = [] const traverse = (currentFeature: AnnotationFeature) => { - if (currentFeature.type === 'exon') { + if (featureTypeOntology.isTypeOf(currentFeature.type, 'exon')) { exonsArray.push({ min: currentFeature.min + 1, max: currentFeature.max, @@ -384,10 +395,10 @@ export const TranscriptBasicInformation = observer( {transcriptItems.map((item, index) => (
- {item.type === 'three_prime_UTR' + {featureTypeOntology.isTypeOf(item.type, 'three_prime_UTR') ? '3 UTR' : // eslint-disable-next-line unicorn/no-nested-ternary - item.type === 'five_prime_UTR' + featureTypeOntology.isTypeOf(item.type, 'five_prime_UTR') ? '5 UTR' : 'CDS'} @@ -397,7 +408,7 @@ export const TranscriptBasicInformation = observer( { const CDSresult: CDSInfo[] = [] const traverse = ( @@ -36,9 +38,9 @@ const getCDSInfo = ( ) => { if ( isParentMRNA && - (currentFeature.type === 'CDS' || - currentFeature.type === 'three_prime_UTR' || - currentFeature.type === 'five_prime_UTR') + (featureTypeOntology.isTypeOf(currentFeature.type, 'CDS') || + featureTypeOntology.isTypeOf(currentFeature.type, 'three_prime_UTR') || + featureTypeOntology.isTypeOf(currentFeature.type, 'five_prime_UTR')) ) { let startSeq = refData.getSequence( Number(currentFeature.min) - 2, @@ -149,14 +151,22 @@ export const TranscriptSequence = observer(function TranscriptSequence({ if (!refSeq) { return null } - const transcriptItems = getCDSInfo(feature, refData) + const { featureTypeOntology } = session.apolloDataStore.ontologyManager + if (!featureTypeOntology) { + throw new Error('featureTypeOntology is undefined') + } + const transcriptItems = getCDSInfo(feature, refData, featureTypeOntology) const { max, min } = feature let sequence = '' if (showSequence) { - getSequenceAsString(min, max) + getSequenceAsString(min, max, featureTypeOntology) } - function getSequenceAsString(start: number, end: number): string { + function getSequenceAsString( + start: number, + end: number, + featureTypeOntology: OntologyRecord, + ): string { sequence = refSeq?.getSequence(start, end) ?? '' if (sequence === '') { void session.apolloDataStore.loadRefSeq([ @@ -165,7 +175,7 @@ export const TranscriptSequence = observer(function TranscriptSequence({ } else { sequence = formatSequence(sequence, refName, start, end) } - getSequenceAsTextSegment(selectedOption) // For color coded sequence + getSequenceAsTextSegment(selectedOption, featureTypeOntology) // For color coded sequence return sequence } @@ -173,7 +183,10 @@ export const TranscriptSequence = observer(function TranscriptSequence({ setShowSequence(!showSequence) } - function getSequenceAsTextSegment(option: string) { + function getSequenceAsTextSegment( + option: string, + featureTypeOntology: OntologyRecord, + ) { let seqData = '' textSegments = [] if (!refData) { @@ -183,7 +196,7 @@ export const TranscriptSequence = observer(function TranscriptSequence({ case 'CDS': { textSegments.push({ text: `>${refName} : CDS\n`, color: 'black' }) for (const item of transcriptItems) { - if (item.type === 'CDS') { + if (featureTypeOntology.isTypeOf(item.type, 'CDS')) { const refSeq: string = refData.getSequence( Number(item.min + 1), Number(item.max), @@ -198,16 +211,16 @@ export const TranscriptSequence = observer(function TranscriptSequence({ textSegments.push({ text: `>${refName} : cDNA\n`, color: 'black' }) for (const item of transcriptItems) { if ( - item.type === 'CDS' || - item.type === 'three_prime_UTR' || - item.type === 'five_prime_UTR' + featureTypeOntology.isTypeOf(item.type, 'CDS') || + featureTypeOntology.isTypeOf(item.type, 'three_prime_UTR') || + featureTypeOntology.isTypeOf(item.type, 'five_prime_UTR') ) { const refSeq: string = refData.getSequence( Number(item.min + 1), Number(item.max), ) seqData += item.strand === -1 && refSeq ? revcom(refSeq) : refSeq - if (item.type === 'CDS') { + if (featureTypeOntology.isTypeOf(item.type, 'CDS')) { textSegments.push({ text: seqData, color: cdsColor }) } else { textSegments.push({ text: seqData, color: utrColor }) @@ -239,9 +252,9 @@ export const TranscriptSequence = observer(function TranscriptSequence({ textSegments.push({ text: seqData, color: 'black' }) } if ( - item.type === 'CDS' || - item.type === 'three_prime_UTR' || - item.type === 'five_prime_UTR' + featureTypeOntology.isTypeOf(item.type, 'CDS') || + featureTypeOntology.isTypeOf(item.type, 'three_prime_UTR') || + featureTypeOntology.isTypeOf(item.type, 'five_prime_UTR') ) { const refSeq: string = refData.getSequence( Number(item.min + 1), @@ -274,10 +287,13 @@ export const TranscriptSequence = observer(function TranscriptSequence({ } } - function handleChangeSeqOption(e: SelectChangeEvent) { + function handleChangeSeqOption( + e: SelectChangeEvent, + featureTypeOntology: OntologyRecord, + ) { const option = e.target.value setSelectedOption(option) - getSequenceAsTextSegment(option) + getSequenceAsTextSegment(option, featureTypeOntology) } // Function to copy text to clipboard @@ -329,7 +345,9 @@ export const TranscriptSequence = observer(function TranscriptSequence({ {showSequence && (