@apollo-annotation/shared 0.1.18 → 0.1.20
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/dist/Changes/AddAssemblyAndFeaturesFromFileChange.d.ts +33 -0
- package/dist/Changes/AddAssemblyAndFeaturesFromFileChange.js +83 -0
- package/dist/Changes/AddAssemblyAndFeaturesFromFileChange.js.map +1 -0
- package/dist/Changes/AddAssemblyFromExternalChange.d.ts +34 -0
- package/dist/Changes/AddAssemblyFromExternalChange.js +97 -0
- package/dist/Changes/AddAssemblyFromExternalChange.js.map +1 -0
- package/dist/Changes/AddAssemblyFromFileChange.d.ts +43 -0
- package/dist/Changes/AddAssemblyFromFileChange.js +140 -0
- package/dist/Changes/AddAssemblyFromFileChange.js.map +1 -0
- package/dist/Changes/AddFeatureChange.d.ts +35 -0
- package/dist/Changes/AddFeatureChange.js +169 -0
- package/dist/Changes/AddFeatureChange.js.map +1 -0
- package/dist/Changes/AddFeaturesFromFileChange.d.ts +32 -0
- package/dist/Changes/AddFeaturesFromFileChange.js +76 -0
- package/dist/Changes/AddFeaturesFromFileChange.js.map +1 -0
- package/dist/Changes/AddRefSeqAliasesChange.d.ts +20 -0
- package/dist/Changes/AddRefSeqAliasesChange.js +61 -0
- package/dist/Changes/AddRefSeqAliasesChange.js.map +1 -0
- package/dist/Changes/DeleteAssemblyChange.d.ts +18 -0
- package/dist/Changes/DeleteAssemblyChange.js +72 -0
- package/dist/Changes/DeleteAssemblyChange.js.map +1 -0
- package/dist/Changes/DeleteFeatureChange.d.ts +42 -0
- package/dist/Changes/DeleteFeatureChange.js +143 -0
- package/dist/Changes/DeleteFeatureChange.js.map +1 -0
- package/dist/Changes/DeleteUserChange.d.ts +25 -0
- package/dist/Changes/DeleteUserChange.js +53 -0
- package/dist/Changes/DeleteUserChange.js.map +1 -0
- package/dist/Changes/FeatureAttributeChange.d.ts +31 -0
- package/dist/Changes/FeatureAttributeChange.js +112 -0
- package/dist/Changes/FeatureAttributeChange.js.map +1 -0
- package/dist/Changes/FromFileBaseChange.d.ts +9 -0
- package/dist/Changes/FromFileBaseChange.js +187 -0
- package/dist/Changes/FromFileBaseChange.js.map +1 -0
- package/dist/Changes/ImportJBrowseConfigChange.d.ts +43 -0
- package/dist/Changes/ImportJBrowseConfigChange.js +67 -0
- package/dist/Changes/ImportJBrowseConfigChange.js.map +1 -0
- package/dist/Changes/LocationEndChange.d.ts +32 -0
- package/dist/Changes/LocationEndChange.js +129 -0
- package/dist/Changes/LocationEndChange.js.map +1 -0
- package/dist/Changes/LocationStartChange.d.ts +32 -0
- package/dist/Changes/LocationStartChange.js +129 -0
- package/dist/Changes/LocationStartChange.js.map +1 -0
- package/dist/Changes/StrandChange.d.ts +31 -0
- package/dist/Changes/StrandChange.js +114 -0
- package/dist/Changes/StrandChange.js.map +1 -0
- package/dist/Changes/TypeChange.d.ts +31 -0
- package/dist/Changes/TypeChange.js +114 -0
- package/dist/Changes/TypeChange.js.map +1 -0
- package/dist/Changes/UserChange.d.ts +25 -0
- package/dist/Changes/UserChange.js +51 -0
- package/dist/Changes/UserChange.js.map +1 -0
- package/dist/Changes/index.d.ts +50 -0
- package/dist/Changes/index.js +55 -0
- package/dist/Changes/index.js.map +1 -0
- package/dist/Checks/CDSCheck.d.ts +8 -0
- package/dist/Checks/CDSCheck.js +197 -0
- package/dist/Checks/CDSCheck.js.map +1 -0
- package/dist/Checks/index.d.ts +1 -0
- package/dist/Checks/index.js +5 -0
- package/dist/Checks/index.js.map +1 -0
- package/dist/Common/index.d.ts +1 -0
- package/dist/Common/index.js +5 -0
- package/dist/Common/index.js.map +1 -0
- package/dist/Common/jwtPayload.d.ts +12 -0
- package/dist/Common/jwtPayload.js +16 -0
- package/dist/Common/jwtPayload.js.map +1 -0
- package/dist/GFF3/gff3ToAnnotationFeature.d.ts +3 -0
- package/dist/GFF3/gff3ToAnnotationFeature.js +211 -0
- package/dist/GFF3/gff3ToAnnotationFeature.js.map +1 -0
- package/dist/GFF3/gff3ToAnnotationFeature.test.d.ts +1 -0
- package/dist/GFF3/gff3ToAnnotationFeature.test.js +174 -0
- package/dist/GFF3/gff3ToAnnotationFeature.test.js.map +1 -0
- package/dist/GFF3/gffReservedKeys.d.ts +5 -0
- package/dist/GFF3/gffReservedKeys.js +34 -0
- package/dist/GFF3/gffReservedKeys.js.map +1 -0
- package/dist/GFF3/index.d.ts +2 -0
- package/dist/GFF3/index.js +6 -0
- package/dist/GFF3/index.js.map +1 -0
- package/dist/Messages.d.ts +28 -0
- package/dist/Messages.js +3 -0
- package/dist/Messages.js.map +1 -0
- package/dist/Operations/GetAssembliesOperation.d.ts +13 -0
- package/dist/Operations/GetAssembliesOperation.js +20 -0
- package/dist/Operations/GetAssembliesOperation.js.map +1 -0
- package/dist/Operations/GetFeaturesOperation.d.ts +26 -0
- package/dist/Operations/GetFeaturesOperation.js +42 -0
- package/dist/Operations/GetFeaturesOperation.js.map +1 -0
- package/dist/Operations/index.d.ts +8 -0
- package/dist/Operations/index.js +10 -0
- package/dist/Operations/index.js.map +1 -0
- package/dist/Validations/CoreValidation.d.ts +17 -0
- package/dist/Validations/CoreValidation.js +36 -0
- package/dist/Validations/CoreValidation.js.map +1 -0
- package/dist/Validations/ParentChildValidation.d.ts +17 -0
- package/dist/Validations/ParentChildValidation.js +61 -0
- package/dist/Validations/ParentChildValidation.js.map +1 -0
- package/dist/Validations/Validation.d.ts +27 -0
- package/dist/Validations/Validation.js +27 -0
- package/dist/Validations/Validation.js.map +1 -0
- package/dist/Validations/ValidationSet.d.ts +24 -0
- package/dist/Validations/ValidationSet.js +86 -0
- package/dist/Validations/ValidationSet.js.map +1 -0
- package/dist/Validations/index.d.ts +4 -0
- package/dist/Validations/index.js +8 -0
- package/dist/Validations/index.js.map +1 -0
- package/dist/Validations/soSequenceTypes.d.ts +2 -0
- package/dist/Validations/soSequenceTypes.js +1868 -0
- package/dist/Validations/soSequenceTypes.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/util.d.ts +4 -0
- package/dist/util.js +102 -0
- package/dist/util.js.map +1 -0
- package/package.json +17 -8
- package/src/Changes/AddAssemblyAndFeaturesFromFileChange.ts +13 -9
- package/src/Changes/AddAssemblyFromFileChange.ts +129 -43
- package/src/Changes/AddFeatureChange.ts +2 -3
- package/src/Changes/AddFeaturesFromFileChange.ts +8 -3
- package/src/Changes/AddRefSeqAliasesChange.ts +88 -0
- package/src/Changes/DeleteAssemblyChange.ts +1 -1
- package/src/Changes/DeleteFeatureChange.ts +1 -1
- package/src/Changes/FeatureAttributeChange.ts +1 -1
- package/src/Changes/FromFileBaseChange.ts +221 -0
- package/src/Changes/ImportJBrowseConfigChange.ts +116 -0
- package/src/Changes/LocationEndChange.ts +25 -18
- package/src/Changes/LocationStartChange.ts +25 -18
- package/src/Changes/TypeChange.ts +1 -1
- package/src/Changes/index.ts +6 -6
- package/src/Checks/CDSCheck.ts +125 -173
- package/src/Common/jwtPayload.ts +1 -1
- package/src/GFF3/gff3ToAnnotationFeature.test.ts +209 -0
- package/src/GFF3/gff3ToAnnotationFeature.ts +257 -0
- package/src/GFF3/gffReservedKeys.ts +61 -0
- package/src/GFF3/index.ts +2 -0
- package/src/Operations/GetFeaturesOperation.ts +2 -2
- package/src/Validations/ParentChildValidation.ts +5 -5
- package/src/index.ts +1 -0
- package/src/util.ts +16 -12
- package/test_data/braker.gff +13 -0
- package/test_data/example01.gff3 +26 -0
- package/test_data/example01.json +236 -0
- package/test_data/example02.json +225 -0
- package/test_data/example04.json +225 -0
- package/test_data/example05.gff3 +30 -0
- package/test_data/example06.gff3 +30 -0
- package/test_data/example07.gff3 +30 -0
- package/test_data/gene_mrna.gff3 +4 -0
- package/test_data/gene_representations.gff3 +1781 -0
- package/test_data/one_cds.gff3 +9 -0
- package/test_data/one_cds.json +67 -0
- package/test_data/two_cds.gff3 +9 -0
- package/test_data/two_cds.json +67 -0
- package/tsconfig.json +4 -4
- package/src/Changes/DiscontinuousLocationEndChange.ts +0 -182
- package/src/Changes/DiscontinuousLocationStartChange.ts +0 -182
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { AnnotationFeatureSnapshot } from '@apollo-annotation/mst'
|
|
2
|
+
import { GFF3Feature, GFF3FeatureLineWithRefs } from '@gmod/gff'
|
|
3
|
+
import { doesIntersect2 } from '@jbrowse/core/util'
|
|
4
|
+
import ObjectID from 'bson-objectid'
|
|
5
|
+
|
|
6
|
+
import { gffToInternal, isGFFReservedAttribute } from './gffReservedKeys'
|
|
7
|
+
|
|
8
|
+
export function gff3ToAnnotationFeature(
|
|
9
|
+
gff3Feature: GFF3Feature,
|
|
10
|
+
refSeq?: string,
|
|
11
|
+
featureIds?: string[],
|
|
12
|
+
): AnnotationFeatureSnapshot {
|
|
13
|
+
const [firstFeature] = gff3Feature
|
|
14
|
+
const { end, seq_id: refName, start, strand, type } = firstFeature
|
|
15
|
+
if (!refName) {
|
|
16
|
+
throw new Error(
|
|
17
|
+
`feature does not have seq_id: ${JSON.stringify(firstFeature)}`,
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
if (!type) {
|
|
21
|
+
throw new Error(
|
|
22
|
+
`feature does not have type: ${JSON.stringify(firstFeature)}`,
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
if (start === null) {
|
|
26
|
+
throw new Error(
|
|
27
|
+
`feature does not have start: ${JSON.stringify(firstFeature)}`,
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
if (end === null) {
|
|
31
|
+
throw new Error(
|
|
32
|
+
`feature does not have end: ${JSON.stringify(firstFeature)}`,
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const [min, max] = getFeatureMinMax(gff3Feature)
|
|
37
|
+
|
|
38
|
+
const convertedChildren = convertChildren(gff3Feature, refSeq, featureIds)
|
|
39
|
+
|
|
40
|
+
const convertedAttributes = convertFeatureAttributes(gff3Feature)
|
|
41
|
+
|
|
42
|
+
const feature: AnnotationFeatureSnapshot = {
|
|
43
|
+
_id: new ObjectID().toHexString(),
|
|
44
|
+
refSeq: refSeq ?? refName,
|
|
45
|
+
type,
|
|
46
|
+
min,
|
|
47
|
+
max,
|
|
48
|
+
}
|
|
49
|
+
if (strand) {
|
|
50
|
+
if (strand === '+') {
|
|
51
|
+
feature.strand = 1
|
|
52
|
+
} else if (strand === '-') {
|
|
53
|
+
feature.strand = -1
|
|
54
|
+
} else {
|
|
55
|
+
throw new Error(`Unknown strand: "${strand}"`)
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (convertedChildren) {
|
|
59
|
+
feature.children = convertedChildren
|
|
60
|
+
}
|
|
61
|
+
if (convertedAttributes) {
|
|
62
|
+
feature.attributes = convertedAttributes
|
|
63
|
+
}
|
|
64
|
+
if (featureIds) {
|
|
65
|
+
featureIds.push(feature._id)
|
|
66
|
+
}
|
|
67
|
+
return feature
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function getFeatureMinMax(gff3Feature: GFF3Feature): [number, number] {
|
|
71
|
+
if (gff3Feature.length > 1 && !gff3Feature.every((f) => f.type === 'CDS')) {
|
|
72
|
+
throw new Error('GFF3 features has multiple locations but is not a CDS')
|
|
73
|
+
}
|
|
74
|
+
const mins = gff3Feature.map((f) => f.start).filter((m) => m !== null)
|
|
75
|
+
const maxes = gff3Feature.map((f) => f.end).filter((m) => m !== null)
|
|
76
|
+
const min = Math.min(...mins)
|
|
77
|
+
const max = Math.max(...maxes)
|
|
78
|
+
return [min - 1, max]
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function convertFeatureAttributes(
|
|
82
|
+
gff3Feature: GFF3Feature,
|
|
83
|
+
): Record<string, string[] | undefined> | undefined {
|
|
84
|
+
const convertedAttributes: Record<string, string[] | undefined> | undefined =
|
|
85
|
+
{}
|
|
86
|
+
const scores = gff3Feature
|
|
87
|
+
.map((f) => f.score)
|
|
88
|
+
.filter((score) => score !== null)
|
|
89
|
+
const sources = gff3Feature
|
|
90
|
+
.map((f) => f.source)
|
|
91
|
+
.filter((source) => source !== null)
|
|
92
|
+
const attributesCollections = gff3Feature
|
|
93
|
+
.map((f) => f.attributes)
|
|
94
|
+
.filter((attributes) => attributes !== null)
|
|
95
|
+
if (scores.length > 0) {
|
|
96
|
+
let [score] = scores
|
|
97
|
+
if (scores.length > 1) {
|
|
98
|
+
const scoresSum = scores.reduce(
|
|
99
|
+
(accumulator, currentValue) => accumulator + currentValue,
|
|
100
|
+
0,
|
|
101
|
+
)
|
|
102
|
+
// Average score
|
|
103
|
+
score = scoresSum / scores.length
|
|
104
|
+
}
|
|
105
|
+
convertedAttributes.gff_score = [String(score)]
|
|
106
|
+
}
|
|
107
|
+
if (sources.length > 0) {
|
|
108
|
+
let [source] = sources
|
|
109
|
+
if (sources.length > 1) {
|
|
110
|
+
const sourceSet = new Set(sources)
|
|
111
|
+
source = [...sourceSet].join(',')
|
|
112
|
+
}
|
|
113
|
+
convertedAttributes.gff_source = [source]
|
|
114
|
+
}
|
|
115
|
+
if (attributesCollections.length > 0) {
|
|
116
|
+
for (const attributesCollection of attributesCollections) {
|
|
117
|
+
for (const [key, val] of Object.entries(attributesCollection)) {
|
|
118
|
+
if (!val || key === 'Parent') {
|
|
119
|
+
continue
|
|
120
|
+
}
|
|
121
|
+
const newKey = isGFFReservedAttribute(key) ? gffToInternal[key] : key
|
|
122
|
+
const existingVal = convertedAttributes[newKey]
|
|
123
|
+
if (existingVal) {
|
|
124
|
+
const valSet = new Set([...existingVal, ...val])
|
|
125
|
+
convertedAttributes[newKey] = [...valSet]
|
|
126
|
+
} else {
|
|
127
|
+
convertedAttributes[newKey] = val
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
if (Object.keys(convertedAttributes).length > 0) {
|
|
133
|
+
return convertedAttributes
|
|
134
|
+
}
|
|
135
|
+
return
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function convertChildren(
|
|
139
|
+
gff3Feature: GFF3Feature,
|
|
140
|
+
refSeq?: string,
|
|
141
|
+
featureIds?: string[],
|
|
142
|
+
): Record<string, AnnotationFeatureSnapshot> | undefined {
|
|
143
|
+
const convertedChildren: Record<string, AnnotationFeatureSnapshot> = {}
|
|
144
|
+
const locationsWithChildren = gff3Feature.filter(
|
|
145
|
+
(feature) => feature.child_features.length > 0,
|
|
146
|
+
)
|
|
147
|
+
if (locationsWithChildren.length > 1) {
|
|
148
|
+
throw new Error('Features with multiple locations may not have children')
|
|
149
|
+
}
|
|
150
|
+
if (locationsWithChildren.length === 0) {
|
|
151
|
+
return
|
|
152
|
+
}
|
|
153
|
+
const [firstFeature] = locationsWithChildren
|
|
154
|
+
const { child_features: childFeatures } = firstFeature
|
|
155
|
+
|
|
156
|
+
const cdsFeatures: GFF3Feature[] = []
|
|
157
|
+
for (const childFeature of childFeatures) {
|
|
158
|
+
const [firstChildFeatureLocation] = childFeature
|
|
159
|
+
if (
|
|
160
|
+
firstChildFeatureLocation.type === 'three_prime_UTR' ||
|
|
161
|
+
firstChildFeatureLocation.type === 'five_prime_UTR' ||
|
|
162
|
+
firstChildFeatureLocation.type === 'intron' ||
|
|
163
|
+
firstChildFeatureLocation.type === 'start_codon' ||
|
|
164
|
+
firstChildFeatureLocation.type === 'stop_codon'
|
|
165
|
+
) {
|
|
166
|
+
continue
|
|
167
|
+
}
|
|
168
|
+
if (firstChildFeatureLocation.type === 'CDS') {
|
|
169
|
+
cdsFeatures.push(childFeature)
|
|
170
|
+
} else {
|
|
171
|
+
const child = gff3ToAnnotationFeature(childFeature, refSeq, featureIds)
|
|
172
|
+
convertedChildren[child._id] = child
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
const processedCDS =
|
|
176
|
+
cdsFeatures.length > 0 ? processCDS(cdsFeatures, refSeq, featureIds) : []
|
|
177
|
+
for (const cds of processedCDS) {
|
|
178
|
+
convertedChildren[cds._id] = cds
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (Object.keys(convertedChildren).length > 0) {
|
|
182
|
+
return convertedChildren
|
|
183
|
+
}
|
|
184
|
+
return
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* If a GFF3 file has CDS features that either (1) don't have an ID or (2) have
|
|
189
|
+
* different IDs for each CDS, we have to do a bit of guessing about how they
|
|
190
|
+
* should be represented in our internal structure
|
|
191
|
+
* @param cdsFeatures -
|
|
192
|
+
*/
|
|
193
|
+
function processCDS(
|
|
194
|
+
cdsFeatures: GFF3Feature[],
|
|
195
|
+
refSeq?: string,
|
|
196
|
+
featureIds?: string[],
|
|
197
|
+
): AnnotationFeatureSnapshot[] {
|
|
198
|
+
const locationCounts = cdsFeatures.map((cds) => cds.length)
|
|
199
|
+
// If any CDS have multiple locations, assume it really is multiple CDS
|
|
200
|
+
// (e.g. the mRNA has multiple alternative translational start sites)
|
|
201
|
+
// and process normally.
|
|
202
|
+
if (locationCounts.some((count) => count > 1)) {
|
|
203
|
+
return cdsFeatures.map((cds) =>
|
|
204
|
+
gff3ToAnnotationFeature(cds, refSeq, featureIds),
|
|
205
|
+
)
|
|
206
|
+
}
|
|
207
|
+
// If all CDS have a single location, we guess that this GFF3 represented CDS
|
|
208
|
+
// as multiple features instead of a single feature with multiple locations.
|
|
209
|
+
// To figure out if it's actually representing one vs. multiple CDS features,
|
|
210
|
+
// first check to see if any of the CDS overlap
|
|
211
|
+
const sortedCDSLocations = cdsFeatures
|
|
212
|
+
.map((cds) => cds[0])
|
|
213
|
+
.filter((cds) => cds.start !== null && cds.end !== null)
|
|
214
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
215
|
+
.sort((cdsA, cdsB) => cdsA.start! - cdsB.start!)
|
|
216
|
+
const overlapping = sortedCDSLocations.some((loc, idx) => {
|
|
217
|
+
const nextLoc = sortedCDSLocations.at(idx + 1)
|
|
218
|
+
if (!nextLoc) {
|
|
219
|
+
return false
|
|
220
|
+
}
|
|
221
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
222
|
+
return doesIntersect2(loc.start!, loc.end!, nextLoc.start!, nextLoc.end!)
|
|
223
|
+
})
|
|
224
|
+
// If no overlaps, assume it's a single CDS feature
|
|
225
|
+
if (!overlapping) {
|
|
226
|
+
return [gff3ToAnnotationFeature(sortedCDSLocations, refSeq, featureIds)]
|
|
227
|
+
}
|
|
228
|
+
// Some CDS locations overlap, the best we can do is use the original order to
|
|
229
|
+
// guess how to group the locations into features
|
|
230
|
+
const cdsLocations = cdsFeatures.map((cds) => cds[0])
|
|
231
|
+
const groupedLocations: GFF3FeatureLineWithRefs[][] = []
|
|
232
|
+
for (const location of cdsLocations) {
|
|
233
|
+
const lastGroup = groupedLocations.at(-1)
|
|
234
|
+
if (!lastGroup) {
|
|
235
|
+
groupedLocations.push([location])
|
|
236
|
+
continue
|
|
237
|
+
}
|
|
238
|
+
const overlaps = lastGroup.some((lastGroupLoc) =>
|
|
239
|
+
doesIntersect2(
|
|
240
|
+
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
241
|
+
lastGroupLoc.start!,
|
|
242
|
+
lastGroupLoc.end!,
|
|
243
|
+
location.start!,
|
|
244
|
+
location.end!,
|
|
245
|
+
/* eslint-enable @typescript-eslint/no-non-null-assertion */
|
|
246
|
+
),
|
|
247
|
+
)
|
|
248
|
+
if (overlaps) {
|
|
249
|
+
groupedLocations.push([location])
|
|
250
|
+
} else {
|
|
251
|
+
lastGroup.push(location)
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return groupedLocations.map((group) =>
|
|
255
|
+
gff3ToAnnotationFeature(group, refSeq, featureIds),
|
|
256
|
+
)
|
|
257
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export type GFFReservedAttribute =
|
|
2
|
+
| 'ID'
|
|
3
|
+
| 'Name'
|
|
4
|
+
| 'Alias'
|
|
5
|
+
| 'Parent'
|
|
6
|
+
| 'Target'
|
|
7
|
+
| 'Gap'
|
|
8
|
+
| 'Derives_from'
|
|
9
|
+
| 'Note'
|
|
10
|
+
| 'Dbxref'
|
|
11
|
+
| 'Ontology_term'
|
|
12
|
+
| 'Is_circular'
|
|
13
|
+
|
|
14
|
+
export type GFFInternalAttribute =
|
|
15
|
+
| 'gff_id'
|
|
16
|
+
| 'gff_name'
|
|
17
|
+
| 'gff_alias'
|
|
18
|
+
| 'gff_parent'
|
|
19
|
+
| 'gff_target'
|
|
20
|
+
| 'gff_gap'
|
|
21
|
+
| 'gff_derives_from'
|
|
22
|
+
| 'gff_note'
|
|
23
|
+
| 'gff_dbxref'
|
|
24
|
+
| 'gff_ontology_term'
|
|
25
|
+
| 'gff_is_circular'
|
|
26
|
+
|
|
27
|
+
export const gffToInternal: Record<GFFReservedAttribute, GFFInternalAttribute> =
|
|
28
|
+
{
|
|
29
|
+
ID: 'gff_id',
|
|
30
|
+
Name: 'gff_name',
|
|
31
|
+
Alias: 'gff_alias',
|
|
32
|
+
Parent: 'gff_parent',
|
|
33
|
+
Target: 'gff_target',
|
|
34
|
+
Gap: 'gff_gap',
|
|
35
|
+
Derives_from: 'gff_derives_from',
|
|
36
|
+
Note: 'gff_note',
|
|
37
|
+
Dbxref: 'gff_dbxref',
|
|
38
|
+
Ontology_term: 'gff_ontology_term',
|
|
39
|
+
Is_circular: 'gff_is_circular',
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function isGFFReservedAttribute(
|
|
43
|
+
attribute: string,
|
|
44
|
+
): attribute is GFFReservedAttribute {
|
|
45
|
+
return attribute in gffToInternal
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export const internalToGFF: Record<GFFInternalAttribute, GFFReservedAttribute> =
|
|
49
|
+
{
|
|
50
|
+
gff_id: 'ID',
|
|
51
|
+
gff_name: 'Name',
|
|
52
|
+
gff_alias: 'Alias',
|
|
53
|
+
gff_parent: 'Parent',
|
|
54
|
+
gff_target: 'Target',
|
|
55
|
+
gff_gap: 'Gap',
|
|
56
|
+
gff_derives_from: 'Derives_from',
|
|
57
|
+
gff_note: 'Note',
|
|
58
|
+
gff_dbxref: 'Dbxref',
|
|
59
|
+
gff_ontology_term: 'Ontology_term',
|
|
60
|
+
gff_is_circular: 'Is_circular',
|
|
61
|
+
}
|
|
@@ -45,8 +45,8 @@ export class GetFeaturesOperation extends Operation {
|
|
|
45
45
|
return backend.featureModel
|
|
46
46
|
.find({
|
|
47
47
|
refSeq: this.refSeq,
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
min: { $lte: this.end },
|
|
49
|
+
max: { $gte: this.start },
|
|
50
50
|
status: 0,
|
|
51
51
|
})
|
|
52
52
|
.exec()
|
|
@@ -72,11 +72,11 @@ export class ParentChildValidation extends Validation {
|
|
|
72
72
|
}
|
|
73
73
|
for (const [, childFeature] of feature.children || new Map()) {
|
|
74
74
|
if (
|
|
75
|
-
feature.
|
|
76
|
-
feature.
|
|
77
|
-
childFeature.
|
|
78
|
-
childFeature.
|
|
79
|
-
(childFeature.
|
|
75
|
+
feature.min !== null &&
|
|
76
|
+
feature.max !== null &&
|
|
77
|
+
childFeature.min !== null &&
|
|
78
|
+
childFeature.max !== null &&
|
|
79
|
+
(childFeature.max > feature.max || childFeature.min < feature.min)
|
|
80
80
|
) {
|
|
81
81
|
throw new Error(
|
|
82
82
|
`Feature "${childFeature._id}" exceeds the bounds of its parent, "${feature._id}"`,
|
package/src/index.ts
CHANGED
package/src/util.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
2
|
+
|
|
2
3
|
import { AnnotationFeatureSnapshot } from '@apollo-annotation/mst'
|
|
3
4
|
import { GFF3Feature } from '@gmod/gff'
|
|
4
5
|
|
|
@@ -7,9 +8,10 @@ export function makeGFF3Feature(
|
|
|
7
8
|
parentId?: string,
|
|
8
9
|
refSeqNames?: Record<string, string | undefined>,
|
|
9
10
|
): GFF3Feature {
|
|
10
|
-
const locations = feature.
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
const locations = [{ start: feature.min, end: feature.max }]
|
|
12
|
+
// const locations = feature.discontinuousLocations?.length
|
|
13
|
+
// ? feature.discontinuousLocations
|
|
14
|
+
// : [{ start: feature.start, end: feature.end, phase: feature.phase }]
|
|
13
15
|
const attributes: Record<string, string[] | undefined> = JSON.parse(
|
|
14
16
|
JSON.stringify(feature.attributes),
|
|
15
17
|
)
|
|
@@ -76,16 +78,18 @@ export function makeGFF3Feature(
|
|
|
76
78
|
seq_id: refSeqNames ? refSeqNames[feature.refSeq] ?? null : feature.refSeq,
|
|
77
79
|
source,
|
|
78
80
|
type: feature.type,
|
|
79
|
-
score:
|
|
81
|
+
score: null,
|
|
82
|
+
// score: feature.score ?? null,
|
|
80
83
|
strand: feature.strand ? (feature.strand === 1 ? '+' : '-') : null,
|
|
81
|
-
phase:
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
84
|
+
phase: null,
|
|
85
|
+
// phase:
|
|
86
|
+
// location.phase === 0
|
|
87
|
+
// ? '0'
|
|
88
|
+
// : location.phase === 1
|
|
89
|
+
// ? '1'
|
|
90
|
+
// : location.phase === 2
|
|
91
|
+
// ? '2'
|
|
92
|
+
// : null,
|
|
89
93
|
attributes: Object.keys(attributes).length > 0 ? attributes : null,
|
|
90
94
|
derived_features: [],
|
|
91
95
|
child_features: feature.children
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
##gff-version 3
|
|
2
|
+
CM033580.1 AUGUSTUS gene 15529 16566 0.92 - . ID=g1;
|
|
3
|
+
CM033580.1 AUGUSTUS mRNA 15529 16566 0.92 - . ID=g1.t1;Parent=g1;
|
|
4
|
+
CM033580.1 AUGUSTUS stop_codon 15529 15531 . - 0 ID=g1.t1.stop1;Parent=g1.t1;
|
|
5
|
+
CM033580.1 AUGUSTUS CDS 15529 15659 0.92 - 2 ID=g1.t1.CDS1;Parent=g1.t1;
|
|
6
|
+
CM033580.1 AUGUSTUS exon 15529 15659 . - . ID=g1.t1.exon1;Parent=g1.t1;
|
|
7
|
+
CM033580.1 AUGUSTUS intron 15660 16112 0.96 - . ID=g1.t1.intron1;Parent=g1.t1;
|
|
8
|
+
CM033580.1 AUGUSTUS CDS 16113 16314 0.96 - 0 ID=g1.t1.CDS2;Parent=g1.t1;
|
|
9
|
+
CM033580.1 AUGUSTUS exon 16113 16314 . - . ID=g1.t1.exon2;Parent=g1.t1;
|
|
10
|
+
CM033580.1 AUGUSTUS intron 16315 16536 0.96 - . ID=g1.t1.intron2;Parent=g1.t1;
|
|
11
|
+
CM033580.1 AUGUSTUS CDS 16537 16566 0.99 - 0 ID=g1.t1.CDS3;Parent=g1.t1;
|
|
12
|
+
CM033580.1 AUGUSTUS exon 16537 16566 . - . ID=g1.t1.exon3;Parent=g1.t1;
|
|
13
|
+
CM033580.1 AUGUSTUS start_codon 16564 16566 . - 0 ID=g1.t1.start1;Parent=g1.t1;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
##gff-version 3
|
|
2
|
+
##sequence-region chr1 1000 9000
|
|
3
|
+
#example01
|
|
4
|
+
chr1 . gene 1000 9000 . + . ID=gene10001;Name=EDEN
|
|
5
|
+
chr1 . TF_binding_site 1000 1012 . + . ID=tfbs10001;Parent=gene10001
|
|
6
|
+
chr1 . mRNA 1050 9000 . + . ID=mRNA10001;Parent=gene10001;Name=EDEN.1
|
|
7
|
+
chr1 . mRNA 1050 9000 . + . ID=mRNA10002;Parent=gene10001;Name=EDEN.2
|
|
8
|
+
chr1 . mRNA 1300 9000 . + . ID=mRNA10003;Parent=gene10001;Name=EDEN.3
|
|
9
|
+
chr1 . exon 1050 1500 . + . ID=exon10001;Parent=mRNA10001,mRNA10002
|
|
10
|
+
chr1 . exon 1300 1500 . + . ID=exon10002;Parent=mRNA10003
|
|
11
|
+
chr1 . exon 3000 3902 . + . ID=exon10003;Parent=mRNA10001,mRNA10003
|
|
12
|
+
chr1 . exon 5000 5500 . + . ID=exon10004;Parent=mRNA10001,mRNA10002,mRNA10003
|
|
13
|
+
chr1 . exon 7000 9000 . + . ID=exon10005;Parent=mRNA10001,mRNA10002,mRNA10003
|
|
14
|
+
chr1 . CDS 1201 1500 . + 0 ID=cds10001;Parent=mRNA10001;Name=edenprotein.1
|
|
15
|
+
chr1 . CDS 3000 3902 . + 0 ID=cds10001;Parent=mRNA10001;Name=edenprotein.1
|
|
16
|
+
chr1 . CDS 5000 5500 . + 0 ID=cds10001;Parent=mRNA10001;Name=edenprotein.1
|
|
17
|
+
chr1 . CDS 7000 7600 . + 0 ID=cds10001;Parent=mRNA10001;Name=edenprotein.1
|
|
18
|
+
chr1 . CDS 1201 1500 . + 0 ID=cds10002;Parent=mRNA10002;Name=edenprotein.2
|
|
19
|
+
chr1 . CDS 5000 5500 . + 0 ID=cds10002;Parent=mRNA10002;Name=edenprotein.2
|
|
20
|
+
chr1 . CDS 7000 7600 . + 0 ID=cds10002;Parent=mRNA10002;Name=edenprotein.2
|
|
21
|
+
chr1 . CDS 3301 3902 . + 0 ID=cds10003;Parent=mRNA10003;Name=edenprotein.3
|
|
22
|
+
chr1 . CDS 5000 5500 . + 1 ID=cds10003;Parent=mRNA10003;Name=edenprotein.3
|
|
23
|
+
chr1 . CDS 7000 7600 . + 1 ID=cds10003;Parent=mRNA10003;Name=edenprotein.3
|
|
24
|
+
chr1 . CDS 3391 3902 . + 0 ID=cds10004;Parent=mRNA10003;Name=edenprotein.4
|
|
25
|
+
chr1 . CDS 5000 5500 . + 1 ID=cds10004;Parent=mRNA10003;Name=edenprotein.4
|
|
26
|
+
chr1 . CDS 7000 7600 . + 1 ID=cds10004;Parent=mRNA10003;Name=edenprotein.4
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_id": "66e049f17b9cedae9ad89108",
|
|
3
|
+
"refSeq": "chr1",
|
|
4
|
+
"type": "gene",
|
|
5
|
+
"min": 999,
|
|
6
|
+
"max": 9000,
|
|
7
|
+
"strand": 1,
|
|
8
|
+
"children": {
|
|
9
|
+
"66e049f17b9cedae9ad890f5": {
|
|
10
|
+
"_id": "66e049f17b9cedae9ad890f5",
|
|
11
|
+
"refSeq": "chr1",
|
|
12
|
+
"type": "TF_binding_site",
|
|
13
|
+
"min": 999,
|
|
14
|
+
"max": 1012,
|
|
15
|
+
"strand": 1,
|
|
16
|
+
"attributes": {
|
|
17
|
+
"gff_id": ["tfbs10001"]
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"66e049f17b9cedae9ad890fb": {
|
|
21
|
+
"_id": "66e049f17b9cedae9ad890fb",
|
|
22
|
+
"refSeq": "chr1",
|
|
23
|
+
"type": "mRNA",
|
|
24
|
+
"min": 1049,
|
|
25
|
+
"max": 9000,
|
|
26
|
+
"strand": 1,
|
|
27
|
+
"children": {
|
|
28
|
+
"66e049f17b9cedae9ad890f6": {
|
|
29
|
+
"_id": "66e049f17b9cedae9ad890f6",
|
|
30
|
+
"refSeq": "chr1",
|
|
31
|
+
"type": "exon",
|
|
32
|
+
"min": 1049,
|
|
33
|
+
"max": 1500,
|
|
34
|
+
"strand": 1,
|
|
35
|
+
"attributes": {
|
|
36
|
+
"gff_id": ["exon10002"]
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"66e049f17b9cedae9ad890f7": {
|
|
40
|
+
"_id": "66e049f17b9cedae9ad890f7",
|
|
41
|
+
"refSeq": "chr1",
|
|
42
|
+
"type": "exon",
|
|
43
|
+
"min": 2999,
|
|
44
|
+
"max": 3902,
|
|
45
|
+
"strand": 1,
|
|
46
|
+
"attributes": {
|
|
47
|
+
"gff_id": ["exon10003"]
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"66e049f17b9cedae9ad890f8": {
|
|
51
|
+
"_id": "66e049f17b9cedae9ad890f8",
|
|
52
|
+
"refSeq": "chr1",
|
|
53
|
+
"type": "exon",
|
|
54
|
+
"min": 4999,
|
|
55
|
+
"max": 5500,
|
|
56
|
+
"strand": 1,
|
|
57
|
+
"attributes": {
|
|
58
|
+
"gff_id": ["exon10004"]
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"66e049f17b9cedae9ad890f9": {
|
|
62
|
+
"_id": "66e049f17b9cedae9ad890f9",
|
|
63
|
+
"refSeq": "chr1",
|
|
64
|
+
"type": "exon",
|
|
65
|
+
"min": 6999,
|
|
66
|
+
"max": 9000,
|
|
67
|
+
"strand": 1,
|
|
68
|
+
"attributes": {
|
|
69
|
+
"gff_id": ["exon10005"]
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
"66e049f17b9cedae9ad890fa": {
|
|
73
|
+
"_id": "66e049f17b9cedae9ad890fa",
|
|
74
|
+
"refSeq": "chr1",
|
|
75
|
+
"type": "CDS",
|
|
76
|
+
"min": 1200,
|
|
77
|
+
"max": 7600,
|
|
78
|
+
"strand": 1,
|
|
79
|
+
"attributes": {
|
|
80
|
+
"gff_id": ["cds10001"],
|
|
81
|
+
"gff_name": ["edenprotein.1"]
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
"attributes": {
|
|
86
|
+
"gff_id": ["mRNA10001"],
|
|
87
|
+
"gff_name": ["EDEN.1"]
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
"66e049f17b9cedae9ad89100": {
|
|
91
|
+
"_id": "66e049f17b9cedae9ad89100",
|
|
92
|
+
"refSeq": "chr1",
|
|
93
|
+
"type": "mRNA",
|
|
94
|
+
"min": 1049,
|
|
95
|
+
"max": 9000,
|
|
96
|
+
"strand": 1,
|
|
97
|
+
"children": {
|
|
98
|
+
"66e049f17b9cedae9ad890fc": {
|
|
99
|
+
"_id": "66e049f17b9cedae9ad890fc",
|
|
100
|
+
"refSeq": "chr1",
|
|
101
|
+
"type": "exon",
|
|
102
|
+
"min": 1049,
|
|
103
|
+
"max": 1500,
|
|
104
|
+
"strand": 1,
|
|
105
|
+
"attributes": {
|
|
106
|
+
"gff_id": ["exon10002"]
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
"66e049f17b9cedae9ad890fd": {
|
|
110
|
+
"_id": "66e049f17b9cedae9ad890fd",
|
|
111
|
+
"refSeq": "chr1",
|
|
112
|
+
"type": "exon",
|
|
113
|
+
"min": 4999,
|
|
114
|
+
"max": 5500,
|
|
115
|
+
"strand": 1,
|
|
116
|
+
"attributes": {
|
|
117
|
+
"gff_id": ["exon10004"]
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
"66e049f17b9cedae9ad890fe": {
|
|
121
|
+
"_id": "66e049f17b9cedae9ad890fe",
|
|
122
|
+
"refSeq": "chr1",
|
|
123
|
+
"type": "exon",
|
|
124
|
+
"min": 6999,
|
|
125
|
+
"max": 9000,
|
|
126
|
+
"strand": 1,
|
|
127
|
+
"attributes": {
|
|
128
|
+
"gff_id": ["exon10005"]
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
"66e049f17b9cedae9ad890ff": {
|
|
132
|
+
"_id": "66e049f17b9cedae9ad890ff",
|
|
133
|
+
"refSeq": "chr1",
|
|
134
|
+
"type": "CDS",
|
|
135
|
+
"min": 1200,
|
|
136
|
+
"max": 7600,
|
|
137
|
+
"strand": 1,
|
|
138
|
+
"attributes": {
|
|
139
|
+
"gff_id": ["cds10002"],
|
|
140
|
+
"gff_name": ["edenprotein.2"]
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
"attributes": {
|
|
145
|
+
"gff_id": ["mRNA10002"],
|
|
146
|
+
"gff_name": ["EDEN.2"]
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
"66e049f17b9cedae9ad89107": {
|
|
150
|
+
"_id": "66e049f17b9cedae9ad89107",
|
|
151
|
+
"refSeq": "chr1",
|
|
152
|
+
"type": "mRNA",
|
|
153
|
+
"min": 1299,
|
|
154
|
+
"max": 9000,
|
|
155
|
+
"strand": 1,
|
|
156
|
+
"children": {
|
|
157
|
+
"66e049f17b9cedae9ad89101": {
|
|
158
|
+
"_id": "66e049f17b9cedae9ad89101",
|
|
159
|
+
"refSeq": "chr1",
|
|
160
|
+
"type": "exon",
|
|
161
|
+
"min": 1299,
|
|
162
|
+
"max": 1500,
|
|
163
|
+
"strand": 1,
|
|
164
|
+
"attributes": {
|
|
165
|
+
"gff_id": ["exon10001"]
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
"66e049f17b9cedae9ad89102": {
|
|
169
|
+
"_id": "66e049f17b9cedae9ad89102",
|
|
170
|
+
"refSeq": "chr1",
|
|
171
|
+
"type": "exon",
|
|
172
|
+
"min": 2999,
|
|
173
|
+
"max": 3902,
|
|
174
|
+
"strand": 1,
|
|
175
|
+
"attributes": {
|
|
176
|
+
"gff_id": ["exon10003"]
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
"66e049f17b9cedae9ad89103": {
|
|
180
|
+
"_id": "66e049f17b9cedae9ad89103",
|
|
181
|
+
"refSeq": "chr1",
|
|
182
|
+
"type": "exon",
|
|
183
|
+
"min": 4999,
|
|
184
|
+
"max": 5500,
|
|
185
|
+
"strand": 1,
|
|
186
|
+
"attributes": {
|
|
187
|
+
"gff_id": ["exon10004"]
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
"66e049f17b9cedae9ad89104": {
|
|
191
|
+
"_id": "66e049f17b9cedae9ad89104",
|
|
192
|
+
"refSeq": "chr1",
|
|
193
|
+
"type": "exon",
|
|
194
|
+
"min": 6999,
|
|
195
|
+
"max": 9000,
|
|
196
|
+
"strand": 1,
|
|
197
|
+
"attributes": {
|
|
198
|
+
"gff_id": ["exon10005"]
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
"66e049f17b9cedae9ad89105": {
|
|
202
|
+
"_id": "66e049f17b9cedae9ad89105",
|
|
203
|
+
"refSeq": "chr1",
|
|
204
|
+
"type": "CDS",
|
|
205
|
+
"min": 3300,
|
|
206
|
+
"max": 7600,
|
|
207
|
+
"strand": 1,
|
|
208
|
+
"attributes": {
|
|
209
|
+
"gff_id": ["cds10003"],
|
|
210
|
+
"gff_name": ["edenprotein.3"]
|
|
211
|
+
}
|
|
212
|
+
},
|
|
213
|
+
"66e049f17b9cedae9ad89106": {
|
|
214
|
+
"_id": "66e049f17b9cedae9ad89106",
|
|
215
|
+
"refSeq": "chr1",
|
|
216
|
+
"type": "CDS",
|
|
217
|
+
"min": 3390,
|
|
218
|
+
"max": 7600,
|
|
219
|
+
"strand": 1,
|
|
220
|
+
"attributes": {
|
|
221
|
+
"gff_id": ["cds10004"],
|
|
222
|
+
"gff_name": ["edenprotein.4"]
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
"attributes": {
|
|
227
|
+
"gff_id": ["mRNA10003"],
|
|
228
|
+
"gff_name": ["EDEN.3"]
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
"attributes": {
|
|
233
|
+
"gff_id": ["gene10001"],
|
|
234
|
+
"gff_name": ["EDEN"]
|
|
235
|
+
}
|
|
236
|
+
}
|