Skip to content
Closed
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
28 changes: 7 additions & 21 deletions packages/apollo-cli/src/test/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -339,13 +339,10 @@ void describe('Test CLI', () => {
assert.deepStrictEqual(p.stdout.trim(), '[]') // No failing check

// Get the ID of the CDS. We need need it to modify the CDS coordinates
const gene = out.filter(
(x: any) =>
JSON.stringify(x.attributes.gff_id) === JSON.stringify(['gene01']),
)
const gene = out.filter((x: any) => x.featureId === 'gene01')
const mrna = Object.values(gene.at(0).children).at(0) as any
const cds = Object.values(mrna.children).find(
(x: any) => x.attributes.gff_id.at(0) === 'cds01',
(x: any) => x.featureId === 'cds01',
) as any
const cds_id = cds._id

Expand Down Expand Up @@ -377,12 +374,11 @@ void describe('Test CLI', () => {

// Get the ID of the CDS. We need need it to modify the CDS coordinates
const gene = out.filter(
(x: any) =>
JSON.stringify(x.attributes.gff_id) === JSON.stringify(['gene01']),
(x: any) => x.featureId === JSON.stringify(['gene01']),
)
const mrna = Object.values(gene.at(0).children).at(0) as any
const cds = Object.values(mrna.children).find(
(x: any) => x.attributes.gff_id.at(0) === 'cds01',
(x: any) => x.featureId === 'cds01',
) as any
const cds_id = cds._id

Expand Down Expand Up @@ -1660,23 +1656,13 @@ void describe('Test CLI', () => {
if (!child.attributes) {
throw new Error('Error getting attributes')
}
if (
JSON.stringify(child.attributes.gff_id) ===
JSON.stringify(['EDEN.1']) ||
JSON.stringify(child.attributes.gff_id) ===
JSON.stringify(['EDEN2.1'])
) {
if (child.featureId === 'EDEN.1' || child.featureId === 'EDEN2.1') {
okMrnaId.push(child._id)
}
if (
JSON.stringify(child.attributes.gff_id) === JSON.stringify(['EDEN.2'])
) {
if (child.featureId === 'EDEN.2') {
warnMrnaIdForw = child._id
}
if (
JSON.stringify(child.attributes.gff_id) ===
JSON.stringify(['EDEN2.2'])
) {
if (child.featureId === 'EDEN2.2') {
warnMrnaIdRev = child._id
}
}
Expand Down
1 change: 1 addition & 0 deletions packages/apollo-cli/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"skipLibCheck": true,
},
"include": ["./src"],
"references": [{ "path": "../apollo-mst" }, { "path": "../apollo-shared" }],
"ts-node": {
"esm": true,
},
Expand Down
8 changes: 5 additions & 3 deletions packages/apollo-mst/src/AnnotationFeatureModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ type TranscriptParts = TranscriptPart[]
export const AnnotationFeatureModel = types
.model('AnnotationFeatureModel', {
_id: types.identifier,
/**
* User-facing identifier for this feature (where _id is the internal
* identifier)
*/
featureId: types.maybe(types.string),
/** Unique ID of the reference sequence on which this feature is located */
refSeq: types.string,
/**
Expand Down Expand Up @@ -79,9 +84,6 @@ export const AnnotationFeatureModel = types
get length() {
return self.max - self.min
},
get featureId() {
return self.attributes.get('id')
},
/**
* Possibly different from `min` because "The GFF3 format does not enforce a
* rule in which features must be wholly contained within the location of
Expand Down
3 changes: 3 additions & 0 deletions packages/apollo-schemas/src/feature.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ export class Feature
@Prop({ type: [String], required: true, index: true })
allIds: string[]

@Prop()
featureId?: string

@Prop({ required: true })
type: string

Expand Down
26 changes: 15 additions & 11 deletions packages/apollo-shared/src/Changes/FromFileBaseChange.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
AssemblySpecificChange,
type ServerDataStore,
} from '@apollo-annotation/common'
import { type AnnotationFeatureSnapshot } from '@apollo-annotation/mst'
import {
type FileDocument,
type RefSeqDocument,
Expand Down Expand Up @@ -206,19 +207,22 @@ export abstract class FromFileBaseChange extends AssemblySpecificChange {
`RefSeq was not found by assembly "${assembly}" and seq_id "${refName}" not found`,
)
}
// Let's add featureId to parent feature
const featureIds: string[] = []

const newFeature = gff3ToAnnotationFeature(
gff3Feature,
refSeqDoc._id,
featureIds,
)
const newFeature = gff3ToAnnotationFeature(gff3Feature, refSeqDoc._id)
const allIds = this.getAllIds(newFeature)

// Add into Mongo
// We cannot use Mongo 'session' / transaction here because Mongo has 16 MB limit for transaction
await featureModel.create([
{ allIds: featureIds, ...newFeature, user, status: -1 },
])
await featureModel.create([{ allIds, ...newFeature, user, status: -1 }])
}

getAllIds(feature: AnnotationFeatureSnapshot): string[] {
const allIds = [feature._id]
if (feature.children) {
for (const child of Object.values(feature.children)) {
const childIds = this.getAllIds(child)
allIds.push(...childIds)
}
}
return allIds
}
}
32 changes: 0 additions & 32 deletions packages/apollo-shared/src/Changes/MergeExonsChange.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,36 +166,4 @@ export class MergeExonsChange extends FeatureChange {
{ logger },
)
}

// mergeAttributes(
// firstExon: AnnotationFeatureSnapshot,
// secondExon: AnnotationFeatureSnapshot,
// ): Record<string, string[]> {
// let mergedAttrs: Record<string, string[]> = {}
// if (firstExon.attributes) {
// // eslint-disable-next-line unicorn/prefer-structured-clone
// mergedAttrs = JSON.parse(JSON.stringify(firstExon.attributes))
// }

// if (secondExon.attributes) {
// // eslint-disable-next-line unicorn/prefer-structured-clone
// const attrs: Record<string, string[]> = JSON.parse(
// JSON.stringify(secondExon.attributes),
// )
// for (const key of Object.keys(attrs)) {
// if (key === '_id' || key === 'gff_id') {
// continue
// }
// if (!Object.keys(mergedAttrs).includes(key)) {
// mergedAttrs[key] = []
// }
// attrs[key].map((x) => {
// if (!mergedAttrs[key].includes(x)) {
// mergedAttrs[key].push(x)
// }
// })
// }
// }
// return mergedAttrs
// }
}
2 changes: 0 additions & 2 deletions packages/apollo-shared/src/Changes/SplitExonChange.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,8 +229,6 @@ export class SplitExonChange extends FeatureChange {
const exon = JSON.parse(JSON.stringify(exonToBeSplit))
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
delete exon.attributes._id
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
delete exon.attributes.gff_id

const leftExon = structuredClone(
exon,
Expand Down
6 changes: 3 additions & 3 deletions packages/apollo-shared/src/Checks/util.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { type AnnotationFeatureSnapshot } from '@apollo-annotation/mst'

export function getPrintableId(feature: AnnotationFeatureSnapshot): string {
const gff_id = feature.attributes?.gff_id?.join(', ')
if (gff_id) {
return `${gff_id} (_id: ${feature._id.toString()})`
const { featureId } = feature
if (featureId) {
return `${featureId} (_id: ${feature._id.toString()})`
}
const gff_name = feature.attributes?.gff_name?.join(', ')
if (gff_name) {
Expand Down
34 changes: 28 additions & 6 deletions packages/apollo-shared/src/GFF3/annotationFeatureToGFF3.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,34 @@
/* eslint-disable prefer-destructuring */
/* eslint-disable @typescript-eslint/no-floating-promises */
import { readFileSync } from 'node:fs'
import { describe, it } from 'node:test'

import { type AnnotationFeatureSnapshot } from '@apollo-annotation/mst'
import { assert } from 'chai'
import { formatSync } from '@gmod/gff'
import { assert, expect } from 'chai'

import { annotationFeatureToGFF3 } from './annotationFeatureToGFF3'
import { readAnnotationFeatureSnapshot } from './gff3ToAnnotationFeature.test'
import { readAnnotationFeatureSnapshot, testCases } from './testUtil'

describe('Converts AnnotationFeatureSnapshot JSON to GFF3 when', () => {
for (const testCase of testCases) {
const { filenameStem, description } = testCase
it(description, () => {
const annotationFeatures = JSON.parse(
readFileSync(`test_data/${filenameStem}.json`, 'utf8'),
) as AnnotationFeatureSnapshot[]
const expectedGFF3 = readFileSync(
`test_data/${filenameStem}.gff3`,
'utf8',
)
const gffFeatures = annotationFeatures.map((annotationFeature) =>
annotationFeatureToGFF3(annotationFeature),
)
const gff3 = formatSync(gffFeatures)
expect(gff3).to.equal(expectedGFF3)
})
}
})

describe('annotationFeatureToGFF3', () => {
it('Test mandatory columns', () => {
Expand Down Expand Up @@ -69,9 +91,9 @@ describe('annotationFeatureToGFF3', () => {
"max": 9000,
"strand": 1,
"attributes": {
"gff_id": ["gene10001"],
"gff_score": ["123", "345"]
}
},
"featureId": "gene10001"
}`) as AnnotationFeatureSnapshot
const [gff3Feature] = annotationFeatureToGFF3(annotationFeature)
assert.deepEqual(gff3Feature.score, 123)
Expand All @@ -85,9 +107,9 @@ describe('annotationFeatureToGFF3', () => {
"max": 9000,
"strand": 1,
"attributes": {
"gff_id": ["gene10001"],
"gff_score": ["xyz"]
}
},
"featureId": "gene10001"
}`) as AnnotationFeatureSnapshot
const [gff3Feature] = annotationFeatureToGFF3(annotationFeature)
assert.deepEqual(gff3Feature.score, null)
Expand Down
7 changes: 5 additions & 2 deletions packages/apollo-shared/src/GFF3/annotationFeatureToGFF3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,13 @@ export function annotationFeatureToGFF3(
if (parentId) {
attributes.Parent = [parentId]
}
if (feature.featureId) {
attributes.ID = [feature.featureId]
}
if (attributes.gff_id) {
attributes.ID = attributes.gff_id
delete attributes.gff_id
} else if (feature.children) {
}
if (feature.children && !attributes.ID) {
attributes.ID = [feature._id]
}
if (attributes.gff_name) {
Expand Down
Loading
Loading